# 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 timelinelib.wxgui.frames.mainframe.menus as mid
from timelinelib.wxgui.frames.mainframe.menus.menubase import MenuBase
from timelinelib.config.menuiteminfo import MenuItemInfo
from timelinelib.config.shortcut import LABEL_NAVIGATE
from timelinelib.config.shortcut import extract_parts_from_menu_label


REQUIRING_TIMELINE = (mid.ID_FIND_FIRST, mid.ID_FIND_LAST, mid.ID_FIT_ALL, mid.ID_RESTORE_TIME_PERIOD)
MENU_LABELS = {
    mid.ID_FIND_FIRST: _("Find &First Event"),
    mid.ID_FIND_LAST: _("Find &Last Event"),
    mid.ID_FIT_ALL: _("Fit &All Events"),
    mid.ID_RESTORE_TIME_PERIOD: _("Go to previous time period"),
}

class NavigateMenu(MenuBase):
    """
    The Navigate menu (a wx.Menu).
    It's content (menu items) is different for different types of timelines.
    """

    def __init__(self, main_frame):
        MenuBase.__init__(self, main_frame, REQUIRING_TIMELINE)
        self._menu_items_info = self._create_menu_items_info(main_frame)
        self._navigation_menu_items = []
        self._navigation_functions_by_menu_item_id = {}
        self._create_menu()
        self._register_menus_requiring_timeline()

    def UpdateMenuItems(self):
        """
        Updates the naivigation menu when a timeline with another timetype than
        the current timeline is opened.
        """
        self._clear_menu_items()
        if self._main_frame.timeline:
            self._create_menu_items()
            self._bind_event_handlers()
            self._register_shortcuts()

    def OnItemClick(self, evt):
        """
        An event handler that occurs when a navigation menu item is selected.
        Execute the function associated with the selected menu item.
        """
        self._main_frame.canvas.SaveTimePeriod()
        time_period = self._main_frame.canvas.GetTimePeriod()
        fn = self._get_navigation_item_function(evt.GetId())
        fn(self._main_frame, time_period, self._main_frame.canvas.NavigateWithFunction)

    def _create_menu_items_info(self, main_frame):
        return [
            MenuItemInfo(wxid=mid.ID_FIND_FIRST,
                         event_handler=lambda evt: main_frame.canvas.NavigateToFirstEvent(),
                         config_key="shortcut_find_first_event",
                         config_display_name=LABEL_NAVIGATE % MENU_LABELS[mid.ID_FIND_FIRST],
                         sort_order=101),
            MenuItemInfo(wxid=mid.ID_FIND_LAST,
                         event_handler=lambda evt: main_frame.canvas.NavigateToLastEvent(),
                         config_key="shortcut_find_last_event",
                         config_display_name=LABEL_NAVIGATE % MENU_LABELS[mid.ID_FIND_LAST],
                         sort_order=102),
            MenuItemInfo(wxid=mid.ID_FIT_ALL,
                         event_handler=lambda evt: main_frame.canvas.FitAllEvents(),
                         config_key="shortcut_fit_all_events",
                         config_display_name=LABEL_NAVIGATE % MENU_LABELS[mid.ID_FIT_ALL],
                         sort_order=103),
            MenuItemInfo(wxid=mid.ID_RESTORE_TIME_PERIOD,
                         event_handler=lambda evt: main_frame.canvas.RestoreTimePeriod(),
                         config_key="shortcut_restore_time_period",
                         config_display_name=LABEL_NAVIGATE % MENU_LABELS[mid.ID_RESTORE_TIME_PERIOD],
                         sort_order=104),
        ]

    def _create_menu(self):
        self.AppendSeparator()
        self._append_menu_item(mid.ID_FIND_FIRST)
        self._append_menu_item(mid.ID_FIND_LAST)
        self._append_menu_item(mid.ID_FIT_ALL)
        self.AppendSeparator()
        self._append_menu_item(mid.ID_RESTORE_TIME_PERIOD)

    def _clear_menu_items(self):
        while self._navigation_menu_items:
            item = self._navigation_menu_items.pop()
            if item in self.MenuItems:
                self.Remove(item)
            self._remove_menu_item_info(item)
        self._main_frame.shortcut_controller.remove_menu_item_infos(LABEL_NAVIGATE % '')
        self._navigation_functions_by_menu_item_id.clear()

    def _remove_menu_item_info(self, menu_item):
        for menu_item_info in self._menu_items_info:
            if menu_item_info.wxid == menu_item.Id:
                self._menu_items_info.remove(menu_item_info)
                return

    def _create_menu_items(self):
        item_data = self._main_frame.timeline.get_time_type().get_navigation_functions()
        pos = 0
        id_offset = self._get_navigation_id_offset()
        for (itemstr, fn) in item_data:
            if itemstr == "SEP":
                item = self.InsertSeparator(pos)
            else:
                label, _, shortcut_modifiers, shortcut_key = extract_parts_from_menu_label(itemstr)
                wxid = mid.ID_NAVIGATE + id_offset
                item = self.Insert(pos, wxid, itemstr)
                self._navigation_functions_by_menu_item_id[item.GetId()] = fn
                id_offset += 1
                menu_item_info = MenuItemInfo(wxid=wxid,
                                              menu_item=item,
                                              event_handler=self.OnItemClick,
                                              config_key=f"shortcut_navigate_{wxid}",
                                              config_display_name=LABEL_NAVIGATE % label,
                                              shortcut_key=shortcut_key,
                                              shortcut_modifier=shortcut_modifiers,
                                              sort_order=pos)
                self._menu_items_info.append(menu_item_info)
            self._navigation_menu_items.append(item)
            pos += 1

    def _get_navigation_item_function(self, menu_id):
        return self._navigation_functions_by_menu_item_id[menu_id]

    def _get_navigation_id_offset(self):
        id_offset = 0
        if self._main_frame.timeline.get_time_type().name == "numtime":
            id_offset = 100
        return id_offset

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