# Record mouse and keyboard actions and reproduce them identically at will
#
# Copyright (C) 2019 Mairo Rufus <akoudanilo@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""
This module contains all the classes needed to
create the GUI and handle non functionnal event
"""

import os
import sys
from pathlib import Path

import control

import settings

import wx
import wx.adv


class MainDialog(wx.Dialog, wx.MiniFrame):
    """Main Window, a dialog to display the app correctly even on tiling WMs."""

    app_text = ["Load Capture", "Save", "Start/Stop Capture", "Play", "Compile to executable",
                "Preferences", "Help"]
    settings_text = ["Play &Speed: Fast", "&Infinite Playback", "Set &Repeat Count", "Recording &Hotkey", 
                     "&Playback Hotkey", "Always on &Top", "&Language", "&About", "&Exit"]

    def on_settings_click(self, event):
        """Triggered when the popup menu is clicked."""
        self.settings_popup()
        event.GetEventObject().PopupMenu(self.settings_popup())
        event.Skip()

    def settings_popup(self):
        """Build the popup menu."""
        menu = wx.Menu()
        # Replay fast
        ps = menu.Append(wx.ID_ANY, self.settings_text[0])
        self.Bind(wx.EVT_MENU,
                  control.SettingsCtrl.playback_speed,
                  ps)
        ps.Enable(False)

        #  Infinite Playback
        cp = menu.AppendCheckItem(wx.ID_ANY, self.settings_text[1])
        status = settings.CONFIG.getboolean('DEFAULT', 'Infinite Playback')
        cp.Check(status)
        self.Bind(wx.EVT_MENU,
                  control.SettingsCtrl.infinite_playback,
                  cp)

        # Repeat count
        self.Bind(wx.EVT_MENU,
                  control.SettingsCtrl.repeat_count,
                  menu.Append(wx.ID_ANY, self.settings_text[2]))
        menu.AppendSeparator()

        # Recording hotkey
        self.Bind(wx.EVT_MENU,
                  control.SettingsCtrl.recording_hotkey,
                  menu.Append(wx.ID_ANY, self.settings_text[3]))

        # Playback hotkey
        self.Bind(wx.EVT_MENU,
                  control.SettingsCtrl.playback_hotkey,
                  menu.Append(wx.ID_ANY, self.settings_text[4]))
        menu.AppendSeparator()

        # Always on top
        aot = menu.AppendCheckItem(wx.ID_ANY, self.settings_text[5])
        status = settings.CONFIG.getboolean('DEFAULT', 'Always On Top')
        aot.Check(status)
        sc = control.SettingsCtrl(self)
        self.Bind(wx.EVT_MENU,
                  sc.always_on_top,
                  aot)

        # Language
        submenu = wx.Menu()
        # Workaround for users of the previous version
        current_lang = "en"
        try:
            current_lang = settings.CONFIG.get('DEFAULT', 'Language')
        except:
            pass

        for language in os.listdir(os.path.join(self.path, "lang")):
            lang_item = submenu.AppendRadioItem(wx.ID_ANY, l)
            self.Bind(wx.EVT_MENU,
                      sc.language,
                      lang_item)
            if language == current_lang:
                lang_item.Check(True)
        menu.AppendSubMenu(submenu, self.settings_text[6])

        # About
        self.Bind(wx.EVT_MENU,
                  self.on_about,
                  menu.Append(wx.ID_ABOUT, self.settings_text[7]))

        # Exit
        self.Bind(wx.EVT_MENU,
                  self.on_close_dialog,
                  menu.Append(wx.ID_ANY, self.settings_text[8]))
        return menu

    def __init__(self, *args, **kwds):
        """Build the interface."""
        if getattr(sys, 'frozen', False):
            self.path = sys._MEIPASS
        else:
            self.path = Path(__file__).parent.absolute()
        on_top = wx.DEFAULT_DIALOG_STYLE
        on_top = on_top if not settings.CONFIG.getboolean('DEFAULT', 'Always On Top') \
                        else on_top | wx.STAY_ON_TOP
        kwds["style"] = kwds.get("style", 0) | on_top
        wx.Dialog.__init__(self, *args, **kwds)
        self.panel = wx.Panel(self)
        self.icon = wx.Icon(os.path.join(self.path, "img", "icon.png"))
        self.SetIcon(self.icon)
        self.taskbar = TaskBarIcon(self)
        self.taskbar.SetIcon(self.icon, "atbswp")

        locale = self.__load_locale()
        self.app_text, self.settings_text = locale[:7], locale[7:]
        self.file_open_button = wx.BitmapButton(self,
                                                wx.ID_ANY,
                                                wx.Bitmap(os.path.join(self.path, "img", "file-upload.png"),
                                                          wx.BITMAP_TYPE_ANY))
        self.file_open_button.SetToolTip(self.app_text[0])
        self.save_button = wx.BitmapButton(self,
                                           wx.ID_ANY,
                                           wx.Bitmap(os.path.join(self.path, "img", "save.png"),
                                                     wx.BITMAP_TYPE_ANY))
        self.save_button.SetToolTip(self.app_text[1])
        self.record_button = wx.BitmapToggleButton(self,
                                                   wx.ID_ANY,
                                                   wx.Bitmap(os.path.join(self.path, "img", "video.png"),
                                                             wx.BITMAP_TYPE_ANY))
        self.record_button.SetToolTip(self.app_text[2])
        self.play_button = wx.BitmapToggleButton(self,
                                                 wx.ID_ANY,
                                                 wx.Bitmap(os.path.join(self.path, "img", "play-circle.png"),
                                                           wx.BITMAP_TYPE_ANY))
        self.play_button.SetToolTip(self.app_text[3])
        self.compile_button = wx.BitmapButton(self,
                                              wx.ID_ANY,
                                              wx.Bitmap(os.path.join(self.path, "img", "download.png"),
                                                        wx.BITMAP_TYPE_ANY))
        self.compile_button.SetToolTip(self.app_text[4])
        self.settings_button = wx.BitmapButton(self,
                                               wx.ID_ANY,
                                               wx.Bitmap(os.path.join(self.path, "img", "cog.png"),
                                                         wx.BITMAP_TYPE_ANY))
        self.settings_button.SetToolTip(self.app_text[5])

        self.help_button = wx.BitmapButton(self,
                                           wx.ID_ANY,
                                           wx.Bitmap(os.path.join(self.path, "img", "question-circle.png"),
                                                     wx.BITMAP_TYPE_ANY))
        self.help_button.SetToolTip(self.app_text[6])

        self.__add_bindings()
        self.__set_properties()
        self.__do_layout()

    def __load_locale(self):
        """Load the interface in user-defined language (default english)."""
        try:
            lang = settings.CONFIG.get('DEFAULT', 'Language')
            locale = open(os.path.join(self.path, "lang", lang)).read().splitlines()
        except:
            return
        if locale == []:
            return
        return locale

    def __add_bindings(self):
        # file_save_ctrl
        self.fsc = control.FileChooserCtrl(self)
        self.Bind(wx.EVT_BUTTON, self.fsc.load_file, self.file_open_button)
        self.Bind(wx.EVT_BUTTON, self.fsc.save_file, self.save_button)

        # record_button_ctrl
        self.rbc = control.RecordCtrl()
        self.Bind(wx.EVT_TOGGLEBUTTON, self.rbc.action, self.record_button)

        # play_button_ctrl
        pbc = control.PlayCtrl()
        self.Bind(wx.EVT_TOGGLEBUTTON, pbc.action, self.play_button)

        # compile_button_ctrl
        self.Bind(wx.EVT_BUTTON, control.CompileCtrl.compile, self.compile_button)

        # help_button_ctrl
        self.Bind(wx.EVT_BUTTON, control.HelpCtrl.action, self.help_button)

        # settings_button_ctrl
        self.Bind(wx.EVT_BUTTON, self.on_settings_click, self.settings_button)

        self.Bind(wx.EVT_CLOSE, self.on_close_dialog)

        self.panel.Bind(wx.EVT_KEY_UP, self.on_key_press)

    def __set_properties(self):
        self.file_open_button.SetSize(self.file_open_button.GetBestSize())
        self.save_button.SetSize(self.save_button.GetBestSize())
        self.record_button.SetSize(self.record_button.GetBestSize())
        self.play_button.SetSize(self.play_button.GetBestSize())
        self.compile_button.SetSize(self.compile_button.GetBestSize())
        self.settings_button.SetSize(self.settings_button.GetBestSize())
        self.help_button.SetSize(self.help_button.GetBestSize())

    def __do_layout(self):
        main_sizer = wx.BoxSizer(wx.HORIZONTAL)
        main_sizer.Add(self.panel)
        main_sizer.Add(self.file_open_button, 0, 0, 0)
        main_sizer.Add(self.save_button, 0, 0, 0)
        main_sizer.Add(self.record_button, 0, 0, 0)
        main_sizer.Add(self.play_button, 0, 0, 0)
        main_sizer.Add(self.compile_button, 0, 0, 0)
        main_sizer.Add(self.settings_button, 0, 0, 0)
        main_sizer.Add(self.help_button, 0, 0, 0)
        self.SetSizer(main_sizer)
        self.Centre()
        main_sizer.Fit(self)
        self.Layout()

    def on_key_press(self, event):
        """ Create manually the event when the correct key is pressed."""
        keycode = event.GetKeyCode()
        if keycode == wx.WXK_F1:
            control.HelpCtrl.action(wx.PyCommandEvent(wx.wxEVT_BUTTON))
        elif keycode == settings.CONFIG.getint('DEFAULT', 'Recording Hotkey'):
            btnEvent = wx.CommandEvent(wx.wxEVT_TOGGLEBUTTON)
            btnEvent.EventObject = self.record_button
            if not self.record_button.Value:
                self.record_button.Value = True
                self.rbc.action(btnEvent)
            else:
                self.record_button.Value = False
                self.rbc.action(btnEvent)
        elif keycode == settings.CONFIG.getint('DEFAULT', 'Playback Hotkey'):
            if not self.play_button.Value:
                self.play_button.Value = True
                btnEvent = wx.CommandEvent(wx.wxEVT_TOGGLEBUTTON)
                btnEvent.EventObject = self.play_button
                control.PlayCtrl().action(btnEvent)
        else:
            event.Skip()

    def on_exit_app(self, event):
        """Clean exit saving the settings."""
        settings.save_config()
        self.Destroy()
        self.taskbar.Destroy()

    def on_close_dialog(self, event):
        """Confirm exit."""
        dialog = wx.MessageDialog(self,
                                  message="Are you sure you want to quit?",
                                  caption="Confirm Exit",
                                  style=wx.YES_NO,
                                  pos=wx.DefaultPosition)
        response = dialog.ShowModal()

        if (response == wx.ID_YES):
            self.on_exit_app(event)
        else:
            event.StopPropagation()

    def on_about(self, event):
        """About dialog."""
        info = wx.adv.AboutDialogInfo()
        info.Name = "atbswp"
        info.Version = "v0.1"
        info.Copyright = ("(C) 2019 Mairo Paul Rufus <akoudanilo@gmail.com>\n")
        info.Description = "Record mouse and keyboard actions and reproduce them identically at will"
        info.WebSite = ("https://github.com/atbswp", "Project homepage")
        info.Developers = ["Mairo Paul Rufus"]
        info.License = "GNU General Public License V3"
        info.Icon = self.icon
        wx.adv.AboutBox(info)


class TaskBarIcon(wx.adv.TaskBarIcon):
    """Taskbar showing the state of the recording."""

    def __init__(self, parent):
        self.parent = parent
        super(TaskBarIcon, self).__init__()