import wx
import threading
from wx.richtext import RichTextCtrl
from grammar_checker import GrammarChecker


class StatisticalGrammarChecker(wx.App):
    """ Main Application """

    def OnInit(self):
        # create initial frame
        frame = Frame()
        frame.Show()
        return True


class Frame(wx.Frame):
    """
    Main Frame

    Holds the current panel according to selected Labeling Mode
    Handles mode change, mode persistence and quitting the application
    """
    def __init__(self):
        # init
        style = wx.SYSTEM_MENU | wx.CAPTION | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.CLOSE_BOX | wx.CLIP_CHILDREN | wx.RESIZE_BORDER
        super(Frame, self).__init__(parent=None, title="Statistical Grammar Checker", style=style, size=(600, 500))

        # create panels
        self.sizer = wx.BoxSizer()
        self.SetSizer(self.sizer)
        self.panel = Panel(self)
        self.sizer.Add(self.panel, proportion=1, flag=wx.EXPAND)

        # center frame
        self.Center()


class Panel(wx.Panel):
    def __init__(self, parent):
        super(Panel, self).__init__(parent)
        self.parent = parent
        min_x = 300
        min_y = 300
        self.parent.SetMinSize((min_x, min_y))

        # correct size
        cur_size = parent.GetSize()
        if cur_size[0] < min_x or cur_size[1] < min_y:
            parent.SetSize((min_x, min_y))

        # UI
        self.create_ui()

        # grammar checker
        self.grammar_checker = GrammarChecker()

    # FRONTEND
    def create_ui(self):
        """ create entirety of UI """
        # create sizer
        vboxsizer = wx.BoxSizer(wx.VERTICAL)

        example_text = ""
        self.text_input = RichTextCtrl(parent=self, value=example_text, style=wx.TE_MULTILINE)
        vboxsizer.Add(self.text_input, proportion=1, flag=wx.EXPAND | wx.ALL - wx.BOTTOM, border=5)

        self.button = wx.Button(parent=self, label="grammar check!", size=(0, 50))
        self.button.Bind(event=wx.EVT_BUTTON, handler=lambda _: threading.Thread(target=self.grammar_check_thread).start())
        vboxsizer.Add(self.button, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)

        self.text_output = RichTextCtrl(parent=self, value="", style=wx.TE_MULTILINE | wx.TE_READONLY)
        vboxsizer.Add(self.text_output, proportion=1, flag=wx.EXPAND | wx.ALL - wx.TOP, border=5)

        # set sizer
        self.SetSizerAndFit(vboxsizer)

    # THREADS
    def grammar_check_thread(self):
        # disable button
        wx.CallAfter(self.button.SetLabel, "checking..")
        wx.CallAfter(self.button.Enable, False)
        # variables
        output_text = ""
        # get input
        input_text = self.text_input.GetValue()
        # grammar check
        unigrams, i_corrections = self.grammar_checker.check(input_text)
        if i_corrections:
            # apply corrections
            before = 0
            highlights = {"red": [], "green": []}
            for i, unigram in enumerate(unigrams):
                after = before + len(unigram)
                if i in i_corrections and i_corrections[i] != unigram:
                    output_text += f"{unigram} {i_corrections[i]}"
                    highlights["red"].append((before, after))
                    highlights["green"].append((after+1, after+1+len(i_corrections[i])))
                    after += 1 + len(i_corrections[i])
                else:
                    output_text += unigram
                if i != len(unigrams):
                    output_text += " "
                    before = after + 1
            # set output text
            wx.CallAfter(self.text_output.SetStyle, 0, len(self.text_output.GetValue()), wx.TextAttr(colText=wx.BLACK, colBack=wx.WHITE))
            wx.CallAfter(self.text_output.SetValue, output_text)
            # highlight errors
            for color, highlights_list in highlights.items():
                for highlight in highlights_list:
                    wx.CallAfter(self.text_output.SetStyle, highlight[0], highlight[1], wx.TextAttr(colText=wx.WHITE, colBack=wx.Colour(150, 0, 0) if color=="red" else wx.Colour(0, 150, 0)))
        # re-enable button
        wx.CallAfter(self.button.SetLabel, "grammar check!")
        wx.CallAfter(self.button.Enable, True)


if __name__ == "__main__":
    app = StatisticalGrammarChecker()
    app.MainLoop()