# Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018  Rickard Lindberg, Roger Lindberg
#
# This file is part of Timeline.
#
# Timeline 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.
#
# Timeline 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 Timeline.  If not, see <http://www.gnu.org/licenses/>.


import os

import wx
import timelinelib.wxgui.frames.mainframe.menus as mid
from timelinelib.wxgui.frames.mainframe.menus.menubase import MenuBase
from timelinelib.plugin.factory import EXPORTER
from timelinelib.plugin import factory
from timelinelib.wxgui.dialogs.filenew.view import open_file_new_dialog
from timelinelib.wxgui.dialogs.importevents.view import open_import_events_dialog
from timelinelib.wxgui.dialogs.getfilepath.view import open_get_file_path_dialog, FUNC_SAVE_AS, FUNC_OPEN
from timelinelib.dataexport.timelinexml import export_db_to_timeline_xml
from timelinelib.config.menuiteminfo import MenuItemInfo
from timelinelib.config.shortcut import CTRL_MODIFIER, LABEL_FILE


REQUIRING_TIMELINE = (mid.ID_IMPORT, mid.ID_SAVEAS)
MENU_LABELS = {
    mid.ID_NEW: _("New") + "...",
    mid.ID_OPEN: _("Open") + "...",
    mid.ID_RECENT: _("Open &Recent"),
    mid.ID_SAVEAS: _("Save As") + "...",
    mid.ID_EXPORT: _("Export"),
    mid.ID_IMPORT: _("Import events") + "...",
    mid.ID_EXIT: _("Exit"),
}


class FileMenu(MenuBase):
    """The File menu (a wx.Menu)."""

    def __init__(self, main_frame):
        MenuBase.__init__(self, main_frame, REQUIRING_TIMELINE)
        self._mnu_open_recent_submenu = wx.Menu()
        self._menu_items_info = self._create_menu_items_info(main_frame)
        self._open_recent_map = {}
        self._create_menu()
        self._bind_event_handlers()
        self._register_shortcuts()
        self._register_menus_requiring_timeline()

    def UpdateRecentSubmenu(self):
        """
        Update the submenu that has a list of recent opened timeline files.
        Used when a new file is opened or created.
        """
        self._clear_recent_menu_items()
        self._create_recent_menu_items()

    def _create_menu_items_info(self, main_frame):
        return [
            MenuItemInfo(wxid=mid.ID_NEW,
                         event_handler=lambda evt: open_file_new_dialog(main_frame),
                         config_key="shortcut_file_new",
                         config_display_name=LABEL_FILE % MENU_LABELS[mid.ID_NEW],
                         shortcut_key="N",
                         shortcut_modifier=CTRL_MODIFIER,
                         sort_order=1),
            MenuItemInfo(wxid=mid.ID_OPEN,
                         event_handler=lambda evt: self._open_existing_timeline(),
                         config_key="shortcut_file_open",
                         config_display_name=LABEL_FILE % MENU_LABELS[mid.ID_OPEN],
                         shortcut_key="O",
                         shortcut_modifier=CTRL_MODIFIER,
                         sort_order=2),
            MenuItemInfo(wxid=mid.ID_SAVEAS,
                         event_handler=lambda evt: self._save_as(),
                         config_key="shortcut_save_as",
                         config_display_name=LABEL_FILE % MENU_LABELS[mid.ID_SAVEAS],
                         sort_order=3),
            MenuItemInfo(wxid=mid.ID_IMPORT,
                         event_handler=lambda evt: open_import_events_dialog(main_frame),
                         config_key="shortcut_import",
                         config_display_name=LABEL_FILE % MENU_LABELS[mid.ID_IMPORT],
                         sort_order=4),
            MenuItemInfo(wxid=mid.ID_EXIT,
                         event_handler=lambda evt: main_frame.Close(),
                         config_key="shortcut_exit",
                         config_display_name=LABEL_FILE % MENU_LABELS[mid.ID_EXIT],
                         shortcut_key="X",
                         shortcut_modifier=CTRL_MODIFIER,
                         sort_order=100),
        ]

    def _create_menu(self):
        self._append_menu_item(mid.ID_NEW, _("Create a new timeline"))
        self._append_menu_item(mid.ID_OPEN, _("Open an existing timeline"))
        self._append_sub_menu(mid.ID_RECENT, self._mnu_open_recent_submenu)
        self.AppendSeparator()
        self._append_menu_item(mid.ID_SAVEAS)
        self.AppendSeparator()
        self._append_menu_item(mid.ID_IMPORT)
        self.AppendSeparator()
        self._append_sub_menu(mid.ID_EXPORT, self._create_export_menues())
        self.AppendSeparator()
        self._append_menu_item(mid.ID_EXIT, _("Exit the program"))

    def _clear_recent_menu_items(self):
        for item in self._mnu_open_recent_submenu.GetMenuItems():
            self._mnu_open_recent_submenu.Delete(item)

    def _create_recent_menu_items(self):
        for path in self._main_frame.config.get_recently_opened():
            self._map_path_to_recent_menu_item(path)

    def _map_path_to_recent_menu_item(self, path):
        name = "%s (%s)" % (
            os.path.basename(path),
            os.path.dirname(os.path.abspath(path)))
        item = self._mnu_open_recent_submenu.Append(wx.ID_ANY, name)
        self._open_recent_map[item.GetId()] = path
        self.Bind(wx.EVT_MENU, self._on_open_recent_timeline, item)

    def _on_open_recent_timeline(self, evt):
        path = self._open_recent_map[evt.GetId()]
        self._main_frame.controller.open_timeline_if_exists(path)

    def _create_export_menues(self):
        submenu = wx.Menu()
        for inx, plugin in enumerate(factory.get_plugins(EXPORTER)):
            self._create_submenu(inx, plugin, submenu)
        return submenu

    def _create_submenu(self, inx, plugin, submenu):
        wxid = plugin.wxid()
        submenu.Append(wxid, plugin.display_name(), plugin.display_name())
        self._main_frame.menu_controller.add_menu_requiring_timeline(submenu.FindItemById(wxid))
        menu_item_info = MenuItemInfo(wxid=wxid,
                                      menu_item=submenu.FindItemById(wxid),
                                      event_handler=lambda evt: plugin.run(self._main_frame),
                                      config_key = f"shortcut_file_plugin_{wxid}",
                                      config_display_name = LABEL_FILE % plugin.display_name(),
                                      sort_order = 10 + inx)
        self._menu_items_info.append(menu_item_info)

    def _open_existing_timeline(self):
        path = self._main_frame.GetTimelinePath()
        self._main_frame.controller.open_or_create_a_timeline(open_get_file_path_dialog(FUNC_OPEN, path))

    def _save_as(self):
        """File menu SaveAs-action handler to save the current timeline with a different name."""
        path = open_get_file_path_dialog(FUNC_SAVE_AS, self._main_frame.timeline.path)
        if path is not None:
            self._main_frame.timeline.save_view_properties(self._main_frame.view_properties)
            assert path.endswith(".timeline")
            export_db_to_timeline_xml(self._main_frame.timeline, path)
            self._main_frame.controller.open_or_create_a_timeline(path, save_current_data=False)

    def _append_sub_menu(self, wxid, submenu):
        self.AppendSubMenu(submenu, MENU_LABELS[wxid])

    def _append_menu_item(self, wxid, help=""):
        self.Append(wxid, MENU_LABELS[wxid], help)
