from collections import OrderedDict
from itertools import chain

# noinspection PyPackageRequirements
import wx

import gui.globalEvents as GE
import gui.mainFrame
from gui.contextMenu import ContextMenuUnconditional
from gui.utils.sorter import smartSort
from service.fit import Fit
from service.targetProfile import TargetProfile as svc_TargetProfile


class TargetProfileSwitcher(ContextMenuUnconditional):

    def __init__(self):
        self.mainFrame = gui.mainFrame.MainFrame.getInstance()

    def display(self, callingWindow, srcContext):
        if srcContext != 'firepowerViewFull':
            return False
        if self.mainFrame.getActiveFit() is None:
            return False
        # We always show "No Profile" anyway
        return True

    def getText(self, callingWindow, itmContext):
        # We take into consideration just target resists, so call menu item accordingly
        return 'Target Resists'

    def handleResistSwitch(self, event):
        profile = self.profileEventMap.get(event.Id, False)
        if profile is False:
            event.Skip()
            return

        sFit = Fit.getInstance()
        fitID = self.mainFrame.getActiveFit()
        sFit.setTargetProfile(fitID, profile)
        wx.PostEvent(self.mainFrame, GE.FitChanged(fitIDs=(fitID,)))

    def _addProfile(self, parentMenu, profile, name):
        id = ContextMenuUnconditional.nextID()
        self.profileEventMap[id] = profile
        menuItem = wx.MenuItem(parentMenu, id, name, kind=wx.ITEM_CHECK)
        parentMenu.Bind(wx.EVT_MENU, self.handleResistSwitch, menuItem)

        # determine active profile
        sFit = Fit.getInstance()
        fitID = self.mainFrame.getActiveFit()
        checked = sFit.getFit(fitID).targetProfile is profile
        return menuItem, checked

    def _addCategory(self, parentMenu, name):
        id = ContextMenuUnconditional.nextID()
        menuItem = wx.MenuItem(parentMenu, id, name)
        parentMenu.Bind(wx.EVT_MENU, self.handleResistSwitch, menuItem)
        return menuItem

    def getSubMenu(self, callingWindow, context, rootMenu, i, pitem):
        sTR = svc_TargetProfile.getInstance()
        profiles = list(chain(sTR.getBuiltinTargetProfileList(), sTR.getUserTargetProfileList()))
        profiles.sort(key=lambda p: smartSort(p.fullName))

        self.profileEventMap = {}
        items = (OrderedDict(), OrderedDict())
        for profile in profiles:
            container = items
            for categoryName in profile.hierarchy:
                container = container[1].setdefault(categoryName, (OrderedDict(), OrderedDict()))
            container[0][profile.shortName] = profile

        # Category as menu item - expands further
        msw = "wxMSW" in wx.PlatformInfo

        def makeMenu(container, parentMenu, first=False):
            menu = wx.Menu()
            if first:
                mitem, checked = self._addProfile(rootMenu if msw else parentMenu, None, 'No Profile')
                menu.Append(mitem)
                mitem.Check(checked)
                if len(container[0]) > 0 or len(container[1]) > 0:
                    menu.AppendSeparator()
            for name, pattern in container[0].items():
                menuItem, checked = self._addProfile(rootMenu if msw else parentMenu, pattern, name)
                menu.Append(menuItem)
                menuItem.Check(checked)
            for name, subcontainer in container[1].items():
                menuItem = self._addCategory(rootMenu if msw else parentMenu, name)
                subMenu = makeMenu(subcontainer, menu)
                menuItem.SetSubMenu(subMenu)
                menu.Append(menuItem)
            menu.Bind(wx.EVT_MENU, self.handleResistSwitch)
            return menu

        subMenu = makeMenu(items, rootMenu, first=True)
        return subMenu


TargetProfileSwitcher.register()
