#!/usr/bin/env python

__license__   = 'GPL v3'
__copyright__ = '2022, Thiago Oliveira <thiago.eec@gmail.com>'
__docformat__ = 'restructuredtext en'

# Load translation files (.mo) on the folder 'translations'
load_translations()

# Standard libraries
from functools import partial

# PyQt libraries
try:
    from qt.core import Qt, QMenu, QIcon, QVBoxLayout, QDialogButtonBox, QApplication
except ImportError:
    from PyQt5.Qt import Qt, QMenu, QIcon, QVBoxLayout, QDialogButtonBox, QApplication

# Calibre libraries
from calibre.gui2.actions import InterfaceAction
from calibre.gui2.actions import menu_action_unique_name
from calibre.gui2.keyboard import finalize
from calibre_plugins.Check_Books.utils import get_icon, prefs
from calibre_plugins.Check_Books.main import CheckBooksTools
from calibre_plugins.Check_Books.__init__ import PLUGIN_NAME, PLUGIN_DESCRIPTION


class InterfacePlugin(InterfaceAction):

    name = PLUGIN_NAME

    # Declare the main action associated with this plugin
    # The keyboard shortcut can be None if you don't want to use a keyboard shortcut.

    action_spec = (PLUGIN_NAME, None, PLUGIN_DESCRIPTION, 'Ctrl+Shift+B')

    def genesis(self):
        # This method is called once per plugin, do initial setup here

        # Set the icon for this interface action
        # The get_icons function is a builtin function defined for all your
        # plugin code. It loads icons from the plugin zip file. It returns
        # QIcon objects, if you want the actual data, use the analogous
        # get_resources builtin function.
        #
        # Note that if you are loading more than one icon, for performance, you
        # should pass a list of names to get_icons. In this case, get_icons
        # will return a dictionary mapping names to QIcons. Names that
        # are not found in the zip file will result in null QIcons.

        self.main_button_icon = get_icon('images/icon.png')

        # Menu creation
        # Only the toolbar menu is created here. All the others are created after the main GUI initialization
        # This allows us to change menus on the fly
        self.tools = CheckBooksTools(self.gui)
        self.m = QMenu(self.gui)
        self.qaction.setMenu(self.m)
        self.qaction.setIcon(self.main_button_icon)

        # This action is configurable by the user. It is actioned by clicking on the main plugin button
        self.main_button_action = self.qaction
        self.main_button_action.triggered.connect(self.set_main_action)

        # First build of menus
        self.rebuild_menus()

        # Set up a listener to catch a system theme change
        QApplication.instance().palette_changed.connect(self.rebuild_menus)

    def initialization_complete(self):
        # This method is called once per action, after the initialization of the main GUI
        # This is the right place to create changing menus
        self.m.aboutToShow.connect(self.about_to_show_menu)

    def do_config(self):
        from calibre.gui2.widgets2 import Dialog
        from calibre_plugins.Check_Books.config import ConfigWidget

        tool = self

        class ConfigDialog(Dialog):

            def __init__(self, gui):
                self.gui = gui
                Dialog.__init__(self, _('Options'), 'plugin-book-report-config-dialog', parent=tool.gui)
                self.setWindowIcon(get_icon('images/icon.png'))

            def setup_ui(self):
                self.box = QVBoxLayout(self)
                self.widget = ConfigWidget(self, self.gui)
                self.box.addWidget(self.widget)
                self.button = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
                self.box.addWidget(self.button)
                self.button.accepted.connect(self.accept)
                self.button.rejected.connect(self.reject)

            def accept(self):
                self.widget.save_settings()
                Dialog.accept(self)

        d = ConfigDialog(self)
        d.exec_()

    def show_configuration(self):
        restart_message = _('Calibre must be restarted before the plugin can be configured.')
        # Check if a restart is needed. If the restart is needed, but the user does not
        # trigger it, the result is true and we do not do the configuration.
        if self.check_if_restart_needed(restart_message=restart_message):
            return

        self.do_config()
        # self.interface_action_base_plugin.do_user_config(self.gui)

        finalize(self.gui.keyboard.shortcuts)
        self.rebuild_menus()

        restart_message = _('New custom columns have been created. You will need'
                            '\nto restart calibre for this change to be applied.'
                            )
        self.check_if_restart_needed(restart_message=restart_message)

    def check_if_restart_needed(self, restart_message=None, restart_needed=False):
        if self.gui.must_restart_before_config or restart_needed:
            if restart_message is None:
                restart_message = _('Calibre must be restarted before the plugin can be configured.')
            from calibre.gui2 import show_restart_warning
            do_restart = show_restart_warning(restart_message)
            if do_restart:
                self.gui.quit(restart=True)
            else:
                return True
        return False

    def apply_settings(self):
        from calibre_plugins.Check_Books.config import prefs
        # In an actual non trivial plugin, you would probably need to
        # do something based on the settings in prefs
        prefs

    def about_to_show_menu(self):
        finalize(self.gui.keyboard.shortcuts)
        self.rebuild_menus()

        # Get preferences
        prefs_custom_columns = {
            'ace_report_column': prefs['ace_report_column'],
            'ace_result_column': prefs['ace_result_column'],
            'epubcheck_report_column': prefs['epubcheck_report_column'],
            'epubcheck_result_column': prefs['epubcheck_result_column']
        }

        # Check if custom columns are set. If not, disable menu items.
        if all(hasattr(self, attr) for attr in ['check_with_ace_item', 'check_with_epubcheck_item']):
            for key, column in prefs_custom_columns.items():
                if key in ('ace_report_column', 'ace_result_column'):
                    if column == '':
                        _enabled = False
                    else:
                        _enabled = True
                    self.check_with_ace_item.setEnabled(_enabled)
                if key in ('epubcheck_report_column', 'epubcheck_result_column'):
                    if column == '':
                        _enabled = False
                    else:
                        _enabled = True
                    self.check_with_epubcheck_item.setEnabled(_enabled)

    def rebuild_menus(self):
        # Set main button icon based on current theme
        self.main_button_icon = get_icon('images/icon.png')
        self.main_button_action.setIcon(self.main_button_icon)

        # Clear all menu actions. This way we can rebuild them, with different icons.
        self.m.clear()

        # Main menu items - Created here, so icons may change on the fly.
        # Before, they were created at initialization_complete().
        cm = partial(self.create_menu_action_unique)

        # Check options
        self.check_with_ace_item = cm(self.m, _('Check with &ACE'),
           image='images/ace.png',
           tooltip=_('Check your books with ACE'),
           triggered=partial(self.tools.check_book, self.tools.check_with_ace),
           unique_name='CheckBooks_ACE')

        self.check_with_epubcheck_item = cm(self.m, _('Check with &EPUBCheck'),
           image='images/epubcheck.png',
           tooltip=_('Check your books with EPUBCheck'),
           triggered=partial(self.tools.check_book, self.tools.check_with_epubcheck),
           unique_name='CheckBooks_EPUBCheck')

        # Config
        self.config_item = cm(self.m, _('&Customize plugin'),
                              image='images/config.png',
                              tooltip=_('Open configuration dialog'),
                              shortcut=False,
                              triggered=self.show_configuration)

        self.gui.keyboard.finalize()

    def set_main_action(self):
        # Define main action based on the user choice
        self.key_main_button = prefs['main_action_idx']
        if self.key_main_button == 0:
            self.tools.check_book(self.tools.check_with_ace)
        else:
            self.tools.check_book(self.tools.check_with_epubcheck)

    def create_menu_action_unique(ia, parent_menu, menu_text, image=None, tooltip=None,
                                  shortcut=None, triggered=None, is_checked=None, shortcut_name=None,
                                  unique_name=None):
        '''
        Create a menu action with the specified criteria and action, using the new
        InterfaceAction.create_menu_action() function which ensures that regardless of
        whether a shortcut is specified it will appear in Preferences->Keyboard
        '''
        orig_shortcut = shortcut
        kb = ia.gui.keyboard
        if unique_name is None:
            unique_name = menu_text
        if not shortcut == False:
            full_unique_name = menu_action_unique_name(ia, unique_name)
            if full_unique_name in kb.shortcuts:
                shortcut = False
            else:
                if shortcut is not None and not shortcut == False:
                    if len(shortcut) == 0:
                        shortcut = None
                    else:
                        shortcut = _(shortcut)

        if shortcut_name is None:
            shortcut_name = menu_text.replace('&', '')

        ac = ia.create_menu_action(parent_menu, unique_name, menu_text, icon=None, shortcut=shortcut,
                                   description=tooltip, triggered=triggered, shortcut_name=shortcut_name)
        if shortcut == False and not orig_shortcut == False:
            if ac.calibre_shortcut_unique_name in ia.gui.keyboard.shortcuts:
                kb.replace_action(ac.calibre_shortcut_unique_name, ac)
        if image:
            ac.setIcon(get_icon(image))
        if is_checked is not None:
            ac.setCheckable(True)
            if is_checked:
                ac.setChecked(True)
        return ac
