#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Dictionary class to be used by all Text Metrics (both normal and
processed data text metrics)

"""
import itertools
import re
import os
import pandas as pd
import numpy as np
import configparser

config = configparser.ConfigParser()
config.read("config.ini")
dictFolder = config["data"]["dicts"]


def nyman_dicts():
    """
    Internal function which loads up the Nyman dicts from file
    """
    dict_paths = [
        os.path.join(dictFolder, x) for x in ["anxiety.txt", "excitement.txt"]
    ]
    AnxietyDict = pd.read_csv(dict_paths[0], names=["anxiety"]).values.tolist()
    AnxietyDict = dict(
        zip(
            [item for sublist in AnxietyDict for item in sublist],
            np.full(len(AnxietyDict), -1),
        )
    )
    ExciteDict = pd.read_csv(dict_paths[1], names=["excite"]).values.tolist()
    ExciteDict = dict(
        zip(
            [item for sublist in ExciteDict for item in sublist],
            np.ones(len(ExciteDict)),
        )
    )
    return [ExciteDict, AnxietyDict]


def opinion_dicts():
    """
    Internal function which loads up the Opinion dicts from file
    """
    dict_paths = [
        os.path.join(dictFolder, x) for x in ["op_negative.txt", "op_positive.txt"]
    ]
    NegativeDict = pd.read_csv(
        dict_paths[0], names=["negative"], encoding="latin-1"
    ).values.tolist()
    NegativeDict = dict(
        zip(
            [item for sublist in NegativeDict for item in sublist],
            np.full(len(NegativeDict), -1),
        )
    )
    PositiveDict = pd.read_csv(
        dict_paths[1], names=["positive"], encoding="utf-8"
    ).values.tolist()
    PositiveDict = dict(
        zip(
            [item for sublist in PositiveDict for item in sublist],
            np.ones(len(PositiveDict)),
        )
    )
    return [NegativeDict, PositiveDict]


def afinn_sentiment_dicts():
    """
    Loads up the Afinn sentiment dictionary
    """
    dict_path = os.path.join(dictFolder, "AFINN-111.txt")
    AfinnDict = pd.read_csv(dict_path, names=["afinn"], sep="\t")
    AfinnDict["afinn"] = AfinnDict["afinn"].astype(np.float64)
    AfinnPosDict = AfinnDict.loc[(AfinnDict["afinn"] > 0)].to_dict()["afinn"]
    AfinnNegDict = AfinnDict.loc[(AfinnDict["afinn"] < 0)].to_dict()["afinn"]
    return [AfinnPosDict, AfinnNegDict]


def harvard_sentiment_dicts():
    """
    Loads up Harvard sentiment dictionary
    """
    excelSentFile = os.path.join(dictFolder, "inquirerbasicHarvard.xls")
    Sdf = pd.read_excel(excelSentFile)
    Sdf["Entry"] = Sdf["Entry"].astype(str)
    Sdf["Entry"] = Sdf["Entry"].apply(lambda x: x.lower())
    # Sdf[Sdf.columns[1:-1]] = Sdf[Sdf.columns[1:-1]].astype(float)
    # Take neg and pos as dicts
    # Edit entry col to remove ending hashes
    Sdf["Entry"] = Sdf["Entry"].apply(lambda x: x.replace("#", ""))
    Sdf["Entry"] = Sdf["Entry"].apply(lambda x: re.sub(r"[0-9]", "", x))
    Sdf = Sdf.set_index("Entry")
    Sdf = Sdf[((Sdf["Source"] == "H4") | (Sdf["Source"] == "H4Lvd"))]
    Sdf.loc[Sdf["Positiv"] == "Positiv", "Positiv"] = 1.0
    Sdf.loc[Sdf["Negativ"] == "Negativ", "Negativ"] = -1.0
    Sdf.loc[(Sdf["Positiv"] != 1.0), "Positiv"] = 0.0
    Sdf.loc[(Sdf["Negativ"] != -1.0), "Negativ"] = 0.0
    Sdf = Sdf[((Sdf["Positiv"] > 0) | (Sdf["Negativ"] < 0))]
    Sdf = Sdf.drop_duplicates()
    PosDict = Sdf.loc[(Sdf["Positiv"] > 0), "Positiv"].to_dict()
    NegDict = Sdf.loc[(Sdf["Negativ"] < 0), "Negativ"].to_dict()
    return [PosDict, NegDict]


def loughran_sentiment_dicts():
    """
    Loads up the Loughran and McDonald dictionary
    """
    excelSentFile = os.path.join(
        dictFolder, "LoughranMcDonald_MasterDictionary_2014.xlsx"
    )
    Sdf = pd.read_excel(excelSentFile)
    Sdf["Word"] = Sdf["Word"].astype(str)
    Sdf["Word"] = Sdf["Word"].apply(lambda x: x.lower())
    Sdf[Sdf.columns[1:-1]] = Sdf[Sdf.columns[1:-1]].astype(float)
    Sdf[["Positive", "Negative"]] = Sdf[["Positive", "Negative"]] / 2009.0
    Sdf["Negative"] = -Sdf["Negative"]
    # Take neg and pos as dicts
    Sdf = Sdf.set_index("Word")
    Sdf = Sdf[((Sdf["Positive"] > 0) | (Sdf["Negative"] < 0))]
    PosDict = Sdf.loc[(Sdf["Positive"] > 0), "Positive"].to_dict()
    NegDict = Sdf.loc[(Sdf["Negative"] < 0), "Negative"].to_dict()
    return [PosDict, NegDict]


def apel_sentiment_dicts():
    """
    Loads up the apel sentiment dictionary
    """

    dict_paths = [
        os.path.join(dictFolder, x)
        for x in ["apel_hawk.txt", "apel_dove.txt", "apel_nouns.txt"]
    ]
    # read the dictionaries
    HawkDict = pd.read_csv(dict_paths[0], names=None).values.tolist()
    DoveDict = pd.read_csv(dict_paths[1], names=None).values.tolist()
    NounDict = pd.read_csv(dict_paths[2], names=["noun"]).values.tolist()

    # tranform the dictionaries on the desirable bi-grams combinations
    Hawk_comb = [list((y, x)) for x in NounDict for y in HawkDict]
    Hawk_comb = [list(itertools.chain(*sublist)) for sublist in Hawk_comb]
    Hawk_comb = [" ".join(x) for x in Hawk_comb]
    # HawkDict= {el:-1 for el in Hawk_comb}

    Dove_comb = [list((y, x)) for x in NounDict for y in DoveDict]
    Dove_comb = [list(itertools.chain(*sublist)) for sublist in Dove_comb]
    Dove_comb = [" ".join(x) for x in Dove_comb]
    # DoveDict= {el:1 for el in Dove_comb}

    return [Hawk_comb, Dove_comb]


def stability_sentiment_dicts():
    """
    Loads up the stability sentiment dictionary
    Probably from
    Correa, R., K. Garud, J. M. Londono, N. Mislang,
    et al. (2017): “Constructing a Dictionary for
    Financial Stability,” Board of Governors of the
    Federal Reserve System (US).
    """
    excelSentFile = os.path.join(dictFolder, "financial_stability.xlsx")
    Sdf = pd.read_excel(excelSentFile)
    Sdf["Word"] = Sdf["Word"].astype(str)
    Sdf["Word"] = Sdf["Word"].apply(lambda x: x.lower())
    Sdf = Sdf.set_index("Word")
    Sdf["Negative"] = -Sdf["Negative"]
    Sdf.loc[(Sdf["Positive"] != 1.0), "Positive"] = 0.0
    Sdf.loc[(Sdf["Negative"] != -1.0), "Negative"] = 0.0
    Sdf = Sdf[((Sdf["Positive"] > 0) | (Sdf["Negative"] < 0))]
    PosDict = Sdf.loc[(Sdf["Positive"] > 0), "Positive"].to_dict()
    NegDict = Sdf.loc[(Sdf["Negative"] < 0), "Negative"].to_dict()
    return [PosDict, NegDict]


def econDicts():
    dict_paths = [
        os.path.join(dictFolder, x)
        for x in ["economist.txt", "ubalt.txt", "ubaltFin.txt"]
    ]
    EconomistDicts = pd.read_csv(dict_paths[0], names=["economist"])
    UbaltDict = pd.read_csv(dict_paths[1], names=["ubalt"])
    UbaltFinDict = pd.read_csv(dict_paths[2], names=["ubaltfinance"])
    econdict = dict((el, 0) for el in EconomistDicts["economist"])
    ubaltdict = dict((el, 0) for el in UbaltDict["ubalt"])
    ubaltfindict = dict((el, 0) for el in UbaltFinDict["ubaltfinance"])
    return econdict, ubaltdict, ubaltfindict


def unionOfDicts():
    filepath = os.path.join(dictFolder, "unionOfDicts.txt")
    unionDicts = pd.read_csv(filepath, names=["unionofDict"])
    dictionary = dict((el, 0) for el in unionDicts["unionofDict"])
    return dictionary


class RefDictClass:
    def __init__(self):
        """Initiates an instance of the Reference Dictionary Class, which supplies
        dictionary objects of positive and negative words

        """
        ### all dictionaries

        [self.ny_excite_dict, self.ny_anxiety_dict] = nyman_dicts()
        [self.op_positive_dict, self.op_negative_dict] = opinion_dicts()
        [self.harv_pos_dict, self.harv_neg_dict] = harvard_sentiment_dicts()
        [self.lm_pos_dict, self.lm_neg_dict] = loughran_sentiment_dicts()
        [self.afinn_pos_dict, self.afinn_neg_dict] = afinn_sentiment_dicts()
        [self.stability_pos_dict, self.stability_neg_dict] = stability_sentiment_dicts()
        [self.economist_dict, self.ubalt_dict, self.ubaltfin_dict] = econDicts()
        self.union_dictionary = unionOfDicts()
        dict_list_pos = [
            self.ny_excite_dict,
            self.harv_pos_dict,
            self.lm_pos_dict,
            self.afinn_pos_dict,
            self.stability_pos_dict,
            # self.op_positive_dict,
        ]
        dict_list_neg = [
            self.ny_anxiety_dict,
            self.harv_neg_dict,
            self.lm_neg_dict,
            self.afinn_neg_dict,
            self.stability_neg_dict,
            #  self.op_negative_dict,
        ]
        # keep only the unique terms
        unique_pos = list(set().union(*dict_list_pos))
        self.unique_dict_pos = {el: 1 for el in unique_pos}
        unique_neg = list(set().union(*dict_list_neg))
        self.unique_dict_neg = {el: -1 for el in unique_neg}
