#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.

import inspect
import os
import re
import string

from fenrirscreenreader.core import debug

currentdir = os.path.dirname(
    os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe())))
)
fenrir_path = os.path.dirname(currentdir)


class PunctuationManager:
    def __init__(self):
        pass

    def initialize(self, environment):
        self.env = environment
        self.allPunctNone = dict.fromkeys(
            map(ord, string.punctuation + "§ "), " "
        )
        # replace with None:
        # dot, comma, grave, apostrophe
        # for char in [ord('`'),ord("'")]:
        #    self.allPunctNone[char] = None
        # dont restore the following (for announce correct pause)
        for char in [
            ord("'"),
            ord("."),
            ord(","),
            ord(";"),
            ord(":"),
            ord("?"),
            ord("!"),
            ord("-"),
        ]:
            self.allPunctNone[char] = chr(char)

    def shutdown(self):
        pass

    def remove_unused(self, text, curr_level=""):
        # dont translate dot and comma because they create a pause
        curr_all_punct_none = self.allPunctNone.copy()
        
        # Check if we should replace undefined punctuation with spaces
        replace_with_space = self.env["runtime"]["SettingsManager"].get_setting_as_bool(
            "general", "replaceUndefinedPunctuationWithSpace"
        )
        
        # If the setting is disabled, use the old behavior (remove completely)
        if not replace_with_space:
            # Create a map that removes undefined punctuation instead of replacing with spaces
            curr_all_punct_none = dict.fromkeys(
                map(ord, string.punctuation + "§ "), None
            )
            # Restore the pause-important characters
            for char in [
                ord("'"),
                ord("."),
                ord(","),
                ord(";"),
                ord(":"),
                ord("?"),
                ord("!"),
                ord("-"),
            ]:
                curr_all_punct_none[char] = chr(char)
        
        # Remove characters that are defined in the current punctuation level
        for char in curr_level:
            try:
                del curr_all_punct_none[ord(char)]
            except Exception as e:
                pass
        
        return text.translate(curr_all_punct_none)

    def use_custom_dict(self, text, customDict, seperator=""):
        result_text = str(text)
        if customDict:
            for key, item in customDict.items():
                try:
                    regex_lbl = "REGEX;"
                    if key.upper().startswith(regex_lbl) and (
                        len(key) > len(regex_lbl)
                    ):
                        result_text = re.sub(
                            str(key[len(regex_lbl) :]),
                            seperator + str(item) + seperator,
                            result_text,
                        )
                    else:
                        result_text = result_text.replace(
                            str(key), seperator + str(item) + seperator
                        )
                except Exception as e:
                    self.env["runtime"]["DebugManager"].write_debug_out(
                        "use_custom_dict replace:'"
                        + key
                        + "' with '"
                        + item
                        + "' failed:"
                        + str(e),
                        debug.DebugLevel.ERROR,
                        on_any_level=False,
                    )
        return result_text

    def use_punctuation_dict(self, text, punctuationDict, punctuation):
        result_text = str(text)

        if punctuationDict and punctuation and punctuation != "":
            if " " in punctuation:
                result_text = result_text.replace(
                    " ", " " + punctuationDict[" "] + " "
                )
            for key, item in punctuationDict.items():
                if (
                    punctuation != "" and key in punctuation
                ) and key not in " ":
                    if (
                        self.env["runtime"]["SettingsManager"].get_setting(
                            "general", "respectPunctuationPause"
                        )
                        and len(key) == 1
                        and key in "',.;:?!"
                    ):
                        result_text = result_text.replace(
                            str(key), " " + str(item) + str(key) + " "
                        )
                    else:
                        result_text = result_text.replace(
                            str(key), " " + str(item) + " "
                        )
        return result_text

    def is_puctuation(self, char):
        return char in self.env["punctuation"]["PUNCTDICT"]

    def proceed_punctuation(self, text, ignore_punctuation=False):
        if ignore_punctuation:
            return text
        result_text = text
        result_text = self.use_custom_dict(
            result_text, self.env["punctuation"]["CUSTOMDICT"]
        )
        if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
            "general", "emoticons"
        ):
            result_text = self.use_custom_dict(
                result_text, self.env["punctuation"]["EMOTICONDICT"], " "
            )
        curr_punct_level = ""
        if (
            self.env["runtime"]["SettingsManager"]
            .get_setting("general", "punctuationLevel")
            .lower()
            in self.env["punctuation"]["LEVELDICT"]
        ):
            curr_punct_level = self.env["punctuation"]["LEVELDICT"][
                self.env["runtime"]["SettingsManager"]
                .get_setting("general", "punctuationLevel")
                .lower()
            ]
        else:
            curr_punct_level = string.punctuation + " §"
        result_text = self.use_punctuation_dict(
            result_text, self.env["punctuation"]["PUNCTDICT"], curr_punct_level
        )
        result_text = self.remove_unused(result_text, curr_punct_level)
        return result_text

    def cycle_punctuation(self):
        punct_list = list(self.env["punctuation"]["LEVELDICT"].keys())
        try:
            curr_index = punct_list.index(
                self.env["runtime"]["SettingsManager"]
                .get_setting("general", "punctuationLevel")
                .lower()
            )  # curr punctuation
        except Exception as e:
            return False
        curr_index += 1
        if curr_index >= len(punct_list):
            curr_index = 0
        curr_level = punct_list[curr_index]
        self.env["runtime"]["SettingsManager"].set_setting(
            "general", "punctuationLevel", curr_level.lower()
        )
        return True

    def load_dicts(
        self,
        dictConfigPath=fenrir_path + "/../../config/punctuation/default.conf",
    ):
        dict_config = open(dictConfigPath, "r")
        curr_dict_name = ""
        while True:
            line = dict_config.readline()
            if not line:
                break
            line = line.replace("\n", "")
            if line.replace(" ", "") == "":
                continue
            if line.replace(" ", "").startswith("#"):
                if not line.replace(" ", "").startswith("#:===:"):
                    continue
            if line.replace(" ", "").upper().startswith("[") and line.replace(
                " ", ""
            ).upper().endswith("DICT]"):
                curr_dict_name = line[
                    line.find("[") + 1 : line.upper().find("DICT]") + 4
                ].upper()
            else:
                if curr_dict_name == "":
                    continue
                if ":===:" not in line:
                    continue
                sep_line = line.split(":===:")
                if len(sep_line) == 1:
                    sep_line.append("")
                elif len(sep_line) < 1:
                    continue
                elif len(sep_line) > 2:
                    sep_line[1] = ":===:"
                self.env["punctuation"][curr_dict_name][sep_line[0]] = (
                    sep_line[1]
                )
                self.env["runtime"]["DebugManager"].write_debug_out(
                    "Punctuation: "
                    + curr_dict_name
                    + "."
                    + str(sep_line[0])
                    + " :"
                    + sep_line[1],
                    debug.DebugLevel.INFO,
                    on_any_level=True,
                )
        dict_config.close()
