# -*- coding: utf-8 -*-


import codecs
import os
import sys
import traceback


unknown_word = 'UNK'


def create_sm_txt(path, name=""):
    pass


def get_sm(path):
    """
    Creates and returns a StringMap. The mapping is loaded from the file given by `path`.

    Args:
        path: path to text file, should contain the mappings like 'character=key'.

    Returns:
        StringMap with loaded mapping.
    """
    sm = StringMapper()
    try:
        if path.endswith('tsv'):
            sm.load_mapping_from_freq(path)
        elif path.endswith('txt'):
            sm.load_mapping_from_txt(path)
        else:
            sm.load_mapping_from_sm(path)
    except Exception as inst:
        print('Original Exception: ', inst)
        exc_info = sys.exc_info()
        traceback.print_exception(*exc_info)
        raise RuntimeError("Can't load StringMap! Check if this is a valid path: ", os.path.abspath(path))
    return sm


class StringMapper:
    def __init__(self):
        self.word_to_id_map = {}
        self.id_to_word_map = {}
        self.loaded = False

        self.unknown_id = -1
        # self.unknown_id = 0
        self._freq_map = {}

    def get_oov_id(self):
        return self.unknown_id

    def has_channel(self, string):
        return string in self.word_to_id_map

    def get_channel(self, string):
        if self.has_channel(string):
            return self.word_to_id_map[string]
        else:
            # print("unknown word: ", string, " returning ", self.unknown_id)
            return self.unknown_id

    def get_value(self, channel):
        if channel < self.size():
            return self.id_to_word_map[channel]
        else:
            return unknown_word

    def size(self):
        return len(self.id_to_word_map)

    def add(self, string, channel=-1):
        if channel == -1:
            channel = len(self.word_to_id_map)
            # print("len = " + str(index))
        self.word_to_id_map[string] = channel
        if channel not in self.id_to_word_map:
            self.id_to_word_map[channel] = string
        # print("pos = " + str(index))
        # self.unknown_id = len(self.id_to_word_map)
        return channel

    def get_mapping(self, file_path):
        with codecs.open(file_path, 'r', encoding='utf-8') as cm_file:
            raw = cm_file.readlines()
            return raw

    def get_freq_from_id(self, id):
        return self._freq_map[id]

    def get_freq_from_word(self, word):
        return self._freq_map[self.word_to_id_map[word]]

    def load_mapping_from_sm(self, file_path):
        if self.loaded:
            raise RuntimeError("map already loaded")
        with codecs.open(file_path, 'r', encoding='utf-8') as cm_file:
            raw = cm_file.readlines()
            for line in raw:
                if line[-1] == '\n':
                    line = line[:-1]
                split = line.rsplit('=', 1)
                key = split[0]
                index = int(split[1]) - 1
                # specific values which are escaped by '\': delete '\'
                if key[0] == '\\':
                    key = key[1:]
                if key == unknown_word:
                    self.unknown_id = id
                # print("'" + key + "' ==> " + str(index))
                self.add(key, index)
        self.loaded = True
        # self.unknown_id = len(self.dictBwd)
        if self.unknown_id < 0:
            self.unknown_id = len(self.id_to_word_map)
            self.add(unknown_word, self.unknown_id)

    def load_mapping_from_freq(self, file_path):
        if self.loaded:
            raise RuntimeError("map already loaded")
        with codecs.open(file_path, 'r', encoding='utf-8') as cm_file:
            raw = cm_file.readlines()
            id = 0
            for line in raw:
                if line[-1] == '\n':
                    line = line[:-1]
                split = line.rsplit('\t', 1)
                key = split[0]
                if key == unknown_word:
                    self.unknown_id = id
                freq = float(split[1])

                # specific values which are escaped by '\': delete '\'
                if key[0] == '\\':
                    key = key[1:]
                # print("'" + key + "' ==> " + str(index))
                self.add(key, id)
                self._freq_map[id] = freq
                id += 1
        self.loaded = True
        # self.unknown_id = len(self.dictBwd)
        if self.unknown_id < 0:
            self.unknown_id = len(self.id_to_word_map)
            self.add(unknown_word, self.unknown_id)
        # print("unknown id: ", self.unknown_id)

    def load_mapping_from_txt(self, file_path):
        if self.loaded:
            raise RuntimeError("map already loaded")
        with codecs.open(file_path, 'r', encoding='utf-8') as cm_file:
            raw = cm_file.readlines()
            id = 0
            for line in raw:
                if line[-1] == '\n':
                    line = line[:-1]
                key = line
                # specific values which are escaped by '\': delete '\'
                if key[0] == '\\':
                    key = key[1:]
                # print("'" + key + "' ==> " + str(index))
                self.add(key, id)
                if key == unknown_word:
                    self.unknown_id = id
                id += 1
        self.loaded = True
        # self.unknown_id = len(self.dictBwd)
        if self.unknown_id < 0:
            self.unknown_id = len(self.id_to_word_map)
            self.add(unknown_word, self.unknown_id)

    def save_mapping(self, file_path):
        with codecs.open(file_path, 'w', encoding='utf-8') as cm_file:
            for key, value in self.word_to_id_map.iteritems():
                if key == '\\' or key == '=':
                    cm_file.write('\\')
                cm_file.write(key)
                cm_file.write('=')
                cm_file.write(str(value + 1))
                cm_file.write('\n')
                # file.write('NaC')
                # file.write('=')
                # file.write(str(len(self.dictBwd)))
        self.loaded = True

    def print2(self):
        # for key in self.dictBwd.keys():
        # print(key)
        # print(str(key)+" => "+(self.dictBwd.get(key)))
        print(self.word_to_id_map)
        print(self.id_to_word_map)


if __name__ == '__main__':
    os.chdir("..")
    # char_map = CharacterMapper()
    # char_map.load_mapping('./private/data/meganet/char_map.txt')
    # char_map.print()
    # print("value = " + str(char_map.get_channel('-')))
    # print("value of " + (u'\u2014') + " = " + str(char_map.get_channel(u'\u2014')))
    # print("value of " + (u'\xe4') + " = " + str(char_map.get_channel(u'\xe4')))
    # print("#############################################")
    # char_map = get_cm_lp()
    # char_map.print()
    # print("char_map = " + str(char_map.dictFwd))
    # print(char_map.get_channels(u'012-Ö4'))

    # barlach=get_cm_barlach()
    # print(barlach.size())

    create_sm_txt("./private/data/bentham/train_and_val.txt", "bentham")
    # char_map = CharacterMapper()
    # char_map.load_mapping("./private/data/cm_esposalles.txt")
    # char_map.print()

# -*- coding: utf-8 -*-


import codecs
import os
import sys
import traceback


unknown_word = 'UNK'


def create_sm_txt(path, name=""):
    pass


def get_sm(path):
    """
    Creates and returns a StringMap. The mapping is loaded from the file given by `path`.

    Args:
        path: path to text file, should contain the mappings like 'character=key'.

    Returns:
        StringMap with loaded mapping.
    """
    sm = StringMapper()
    try:
        if path.endswith('tsv'):
            sm.load_mapping_from_freq(path)
        elif path.endswith('txt'):
            sm.load_mapping_from_txt(path)
        else:
            sm.load_mapping_from_sm(path)
    except Exception as inst:
        print('Original Exception: ', inst)
        exc_info = sys.exc_info()
        traceback.print_exception(*exc_info)
        raise RuntimeError("Can't load StringMap! Check if this is a valid path: ", os.path.abspath(path))
    return sm


class StringMapper:
    def __init__(self):
        self.word_to_id_map = {}
        self.id_to_word_map = {}
        self.loaded = False

        self.unknown_id = -1
        # self.unknown_id = 0
        self._freq_map = {}

    def get_oov_id(self):
        return self.unknown_id

    def has_channel(self, string):
        return string in self.word_to_id_map

    def get_channel(self, string):
        if self.has_channel(string):
            return self.word_to_id_map[string]
        else:
            # print("unknown word: ", string, " returning ", self.unknown_id)
            return self.unknown_id

    def get_value(self, channel):
        if channel < self.size():
            return self.id_to_word_map[channel]
        else:
            return unknown_word

    def size(self):
        return len(self.id_to_word_map)

    def add(self, string, channel=-1):
        if channel == -1:
            channel = len(self.word_to_id_map)
            # print("len = " + str(index))
        self.word_to_id_map[string] = channel
        if channel not in self.id_to_word_map:
            self.id_to_word_map[channel] = string
        # print("pos = " + str(index))
        # self.unknown_id = len(self.id_to_word_map)
        return channel

    def get_mapping(self, file_path):
        with codecs.open(file_path, 'r', encoding='utf-8') as cm_file:
            raw = cm_file.readlines()
            return raw

    def get_freq_from_id(self, id):
        return self._freq_map[id]

    def get_freq_from_word(self, word):
        return self._freq_map[self.word_to_id_map[word]]

    def load_mapping_from_sm(self, file_path):
        if self.loaded:
            raise RuntimeError("map already loaded")
        with codecs.open(file_path, 'r', encoding='utf-8') as cm_file:
            raw = cm_file.readlines()
            for line in raw:
                if line[-1] == '\n':
                    line = line[:-1]
                split = line.rsplit('=', 1)
                key = split[0]
                index = int(split[1]) - 1
                # specific values which are escaped by '\': delete '\'
                if key[0] == '\\':
                    key = key[1:]
                if key == unknown_word:
                    self.unknown_id = id
                # print("'" + key + "' ==> " + str(index))
                self.add(key, index)
        self.loaded = True
        # self.unknown_id = len(self.dictBwd)
        if self.unknown_id < 0:
            self.unknown_id = len(self.id_to_word_map)
            self.add(unknown_word, self.unknown_id)

    def load_mapping_from_freq(self, file_path):
        if self.loaded:
            raise RuntimeError("map already loaded")
        with codecs.open(file_path, 'r', encoding='utf-8') as cm_file:
            raw = cm_file.readlines()
            id = 0
            for line in raw:
                if line[-1] == '\n':
                    line = line[:-1]
                split = line.rsplit('\t', 1)
                key = split[0]
                if key == unknown_word:
                    self.unknown_id = id
                freq = float(split[1])

                # specific values which are escaped by '\': delete '\'
                if key[0] == '\\':
                    key = key[1:]
                # print("'" + key + "' ==> " + str(index))
                self.add(key, id)
                self._freq_map[id] = freq
                id += 1
        self.loaded = True
        # self.unknown_id = len(self.dictBwd)
        if self.unknown_id < 0:
            self.unknown_id = len(self.id_to_word_map)
            self.add(unknown_word, self.unknown_id)
        # print("unknown id: ", self.unknown_id)

    def load_mapping_from_txt(self, file_path):
        if self.loaded:
            raise RuntimeError("map already loaded")
        with codecs.open(file_path, 'r', encoding='utf-8') as cm_file:
            raw = cm_file.readlines()
            id = 0
            for line in raw:
                if line[-1] == '\n':
                    line = line[:-1]
                key = line
                # specific values which are escaped by '\': delete '\'
                if key[0] == '\\':
                    key = key[1:]
                # print("'" + key + "' ==> " + str(index))
                self.add(key, id)
                if key == unknown_word:
                    self.unknown_id = id
                id += 1
        self.loaded = True
        # self.unknown_id = len(self.dictBwd)
        if self.unknown_id < 0:
            self.unknown_id = len(self.id_to_word_map)
            self.add(unknown_word, self.unknown_id)

    def save_mapping(self, file_path):
        with codecs.open(file_path, 'w', encoding='utf-8') as cm_file:
            for key, value in self.word_to_id_map.iteritems():
                if key == '\\' or key == '=':
                    cm_file.write('\\')
                cm_file.write(key)
                cm_file.write('=')
                cm_file.write(str(value + 1))
                cm_file.write('\n')
                # file.write('NaC')
                # file.write('=')
                # file.write(str(len(self.dictBwd)))
        self.loaded = True

    def print2(self):
        # for key in self.dictBwd.keys():
        # print(key)
        # print(str(key)+" => "+(self.dictBwd.get(key)))
        print(self.word_to_id_map)
        print(self.id_to_word_map)


if __name__ == '__main__':
    os.chdir("..")
    # char_map = CharacterMapper()
    # char_map.load_mapping('./private/data/meganet/char_map.txt')
    # char_map.print()
    # print("value = " + str(char_map.get_channel('-')))
    # print("value of " + (u'\u2014') + " = " + str(char_map.get_channel(u'\u2014')))
    # print("value of " + (u'\xe4') + " = " + str(char_map.get_channel(u'\xe4')))
    # print("#############################################")
    # char_map = get_cm_lp()
    # char_map.print()
    # print("char_map = " + str(char_map.dictFwd))
    # print(char_map.get_channels(u'012-Ö4'))

    # barlach=get_cm_barlach()
    # print(barlach.size())

    create_sm_txt("./private/data/bentham/train_and_val.txt", "bentham")
    # char_map = CharacterMapper()
    # char_map.load_mapping("./private/data/cm_esposalles.txt")
    # char_map.print()

# -*- coding: utf-8 -*- Creates and returns a StringMap. The mapping is loaded from the file given by `path`.      Args:         path: path to text file, should contain the mappings like 'character=key'.      Returns:         StringMap with loaded mapping. # self.unknown_id = 0 # print("unknown word: ", string, " returning ", self.unknown_id) # print("len = " + str(index)) # print("pos = " + str(index)) # self.unknown_id = len(self.id_to_word_map) # specific values which are escaped by '\': delete '\' # print("'" + key + "' ==> " + str(index)) # self.unknown_id = len(self.dictBwd) # specific values which are escaped by '\': delete '\' # print("'" + key + "' ==> " + str(index)) # self.unknown_id = len(self.dictBwd) # print("unknown id: ", self.unknown_id) # specific values which are escaped by '\': delete '\' # print("'" + key + "' ==> " + str(index)) # self.unknown_id = len(self.dictBwd) # file.write('NaC') # file.write('=') # file.write(str(len(self.dictBwd))) # for key in self.dictBwd.keys(): # print(key) # print(str(key)+" => "+(self.dictBwd.get(key))) # char_map = CharacterMapper() # char_map.load_mapping('./private/data/meganet/char_map.txt') # char_map.print() # print("value = " + str(char_map.get_channel('-'))) # print("value of " + (u'\u2014') + " = " + str(char_map.get_channel(u'\u2014'))) # print("value of " + (u'\xe4') + " = " + str(char_map.get_channel(u'\xe4'))) # print("#############################################") # char_map = get_cm_lp() # char_map.print() # print("char_map = " + str(char_map.dictFwd)) # print(char_map.get_channels(u'012-Ö4')) # barlach=get_cm_barlach() # print(barlach.size()) # char_map = CharacterMapper() # char_map.load_mapping("./private/data/cm_esposalles.txt") # char_map.print()