import csv
import emoji
import numpy as np
emoji_dictionary = {"0": "\u2764\uFE0F", "1": ":baseball:", "2": ":smile:", "3": ":disappointed:", "4": ":fork_and_knife:"}


def read_glove_vecs(glove_file):
    with open(glove_file, encoding="utf8") as f:
        words = set()
        word_to_vec_map = {}
        for line in f:
            line = line.strip().split()
            curr_word = line[0]
            words.add(curr_word)
            word_to_vec_map[curr_word] = np.array(line[1:], dtype=np.float64)
        i = 1
        words_to_index = {}
        index_to_words = {}
        for w in sorted(words):
            words_to_index[w] = i
            index_to_words[i] = w
            i = i + 1
    return words_to_index, index_to_words, word_to_vec_map


def softmax(x):
    # Compute softmax values for each sets of scores in x
    e_x = np.exp(x - np.max(x))
    return e_x / e_x.sum()


def read_csv(filename='data/emojify_data.csv'):
    phrase = []
    emoji = []
    with open(filename) as csvDataFile:
        csvReader = csv.reader(csvDataFile)
        for row in csvReader:
            phrase.append(row[0])
            emoji.append(row[1])
    X = np.asarray(phrase)
    Y = np.asarray(emoji, dtype=int)
    return X, Y


def convert_to_one_hot(Y, C):
    Y = np.eye(C)[Y.reshape(-1)]
    return Y


def label_to_emoji(label):
    # Converts a label (int or string) into the corresponding emoji code (string) ready to be printed
    return emoji.emojize(emoji_dictionary[str(label)], use_aliases=True)


def print_predictions(X, pred):
    for i in range(X.shape[0]):
        print(X[i], label_to_emoji(int(pred[i])))


def predict(X, Y, W, b, word_to_vec_map):
    """
    Given X (sentences) and Y (emoji indices), predict emojis and compute the accuracy of your model over the given set.
    
    Arguments:
    X -- input data containing sentences, numpy array of shape (m, None)
    Y -- labels, containing index of the label emoji, numpy array of shape (m, 1)
    
    Returns:
    pred -- numpy array of shape (m, 1) with your predictions
    """
    m = X.shape[0]
    pred = np.zeros((m, 1))
    for j in range(m):  # Loop over training examples
        # Split jth test example (sentence) into list of lower case words
        words = X[j].lower().split()
        # Average words' vectors
        avg = np.zeros((50,))
        for w in words:
            avg += word_to_vec_map[w]
        avg /= len(words)
        # Forward propagation
        Z = W @ avg + b
        A = softmax(Z)
        pred[j] = np.argmax(A)
    print("Accuracy: " + str(np.mean((pred[:] == Y.reshape(Y.shape[0], 1)[:]))))
    return pred
