"""
@package mapswipe.dialogs

@brief Dialogs used in Map Swipe

Classes:
 - dialogs::SwipeMapDialog

(C) 2013 by the GRASS Development Team

This program is free software under the GNU General Public License
(>=v2). Read the file COPYING that comes with GRASS for details.

@author Anna Petrasova <kratochanna gmail.com>
"""

import copy
import wx
import wx.lib.scrolledpanel as SP
import wx.lib.colourselect as csel

from core import globalvar
from gui_core import gselect
from gui_core.widgets import SimpleValidator
from gui_core.preferences import PreferencesBaseDialog
from core.gcmd import GMessage
from core.layerlist import LayerList
from core.settings import UserSettings
from gui_core.wrap import SpinCtrl, Button, StaticText, StaticBox
from gui_core.simplelmgr import (
    SimpleLayerManager,
    SIMPLE_LMGR_RASTER,
    SIMPLE_LMGR_VECTOR,
    SIMPLE_LMGR_RGB,
    SIMPLE_LMGR_TB_LEFT,
    SIMPLE_LMGR_TB_RIGHT,
)

from grass.pydispatch.signal import Signal


class SwipeMapDialog(wx.Dialog):
    """Dialog used to select maps.

    There are two modes - simple (only two raster maps),
    or two layer lists.
    """

    def __init__(
        self,
        parent,
        title=_("Select raster maps"),
        first=None,
        second=None,
        firstLayerList=None,
        secondLayerList=None,
    ):
        wx.Dialog.__init__(
            self,
            parent=parent,
            title=title,
            style=wx.RESIZE_BORDER | wx.DEFAULT_DIALOG_STYLE,
        )

        if firstLayerList is None:
            self._firstLayerList = LayerList()
        else:
            self._firstLayerList = copy.deepcopy(firstLayerList)
        if secondLayerList is None:
            self._secondLayerList = LayerList()
        else:
            self._secondLayerList = copy.deepcopy(secondLayerList)

        self._firstPanel = self._createSimplePanel()
        self._secondPanel = self._createAdvancedPanel()

        self.btnSwitch = Button(self)
        self.btnCancel = Button(self, id=wx.ID_CANCEL)
        self.btnApply = Button(self, id=wx.ID_APPLY)
        self.btnOK = Button(self, id=wx.ID_OK)
        self.btnOK.SetDefault()

        self.btnSwitch.Bind(wx.EVT_BUTTON, self.OnSwitchMode)
        self.btnApply.Bind(wx.EVT_BUTTON, lambda evt: self._apply())
        self.btnOK.Bind(wx.EVT_BUTTON, lambda evt: self._ok())
        self.btnCancel.Bind(wx.EVT_BUTTON, lambda evt: self.Close())
        self.Bind(wx.EVT_CLOSE, lambda evt: self.Hide())

        self.applyChanges = Signal("SwipeMapDialog.applyChanges")

        if first:
            self._firstRaster.SetValue(first)
        if second:
            self._secondRaster.SetValue(second)

        self._layout()

    def UnInit(self):
        self._firstLmgr.UnInit()
        self._secondLmgr.UnInit()

    def _layout(self):
        """Do layout"""
        mainSizer = wx.BoxSizer(wx.VERTICAL)
        self._switchSizer = wx.BoxSizer()
        self._switchSizer.Add(
            self._firstPanel, proportion=1, flag=wx.EXPAND | wx.ALL, border=5
        )
        self._switchSizer.Add(
            self._secondPanel, proportion=1, flag=wx.EXPAND | wx.ALL, border=5
        )
        mainSizer.Add(self._switchSizer, proportion=1, flag=wx.EXPAND | wx.ALL)

        self.btnSizer = wx.StdDialogButtonSizer()
        self.btnSizer.AddButton(self.btnCancel)
        self.btnSizer.AddButton(self.btnOK)
        self.btnSizer.AddButton(self.btnApply)
        self.btnSizer.Realize()

        mainSizer.Add(
            self.btnSwitch, proportion=0, flag=wx.ALL | wx.ALIGN_LEFT, border=5
        )
        mainSizer.Add(self.btnSizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
        self.mainSizer = mainSizer
        self._switchMode(simple=True)
        self.SetSizer(mainSizer)
        mainSizer.Fit(self)

    def _createSimplePanel(self):
        panel = wx.Panel(self)
        sizer = wx.BoxSizer(wx.VERTICAL)

        self._firstRaster = gselect.Select(
            parent=panel,
            type="raster",
            size=globalvar.DIALOG_GSELECT_SIZE,
            validator=SimpleValidator(callback=self.ValidatorCallback),
        )

        self._secondRaster = gselect.Select(
            parent=panel,
            type="raster",
            size=globalvar.DIALOG_GSELECT_SIZE,
            validator=SimpleValidator(callback=self.ValidatorCallback),
        )
        sizer.Add(
            StaticText(panel, label=_("Name of top/left raster map:")),
            proportion=0,
            flag=wx.EXPAND | wx.ALL,
            border=5,
        )
        sizer.Add(self._firstRaster, proportion=0, flag=wx.EXPAND | wx.ALL, border=1)
        sizer.Add(
            StaticText(panel, label=_("Name of bottom/right raster map:")),
            proportion=0,
            flag=wx.EXPAND | wx.ALL,
            border=1,
        )
        sizer.Add(self._secondRaster, proportion=0, flag=wx.EXPAND | wx.ALL, border=1)

        self._firstRaster.SetFocus()

        panel.SetSizer(sizer)
        sizer.Fit(panel)

        return panel

    def _createAdvancedPanel(self):
        panel = wx.Panel(self)
        sizer = wx.BoxSizer(wx.HORIZONTAL)

        self._firstLmgr = SimpleLayerManager(
            parent=panel,
            layerList=self._firstLayerList,
            lmgrStyle=SIMPLE_LMGR_RASTER
            | SIMPLE_LMGR_RGB
            | SIMPLE_LMGR_VECTOR
            | SIMPLE_LMGR_TB_LEFT,
        )
        self._secondLmgr = SimpleLayerManager(
            parent=panel,
            layerList=self._secondLayerList,
            lmgrStyle=SIMPLE_LMGR_RASTER
            | SIMPLE_LMGR_RGB
            | SIMPLE_LMGR_VECTOR
            | SIMPLE_LMGR_TB_RIGHT,
        )
        sizer.Add(self._firstLmgr, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
        sizer.Add(self._secondLmgr, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
        panel.SetSizer(sizer)
        sizer.Fit(panel)

        return panel

    def _switchMode(self, simple):
        if simple:
            self._switchSizer.Show(self._firstPanel, show=True, recursive=True)
            self._switchSizer.Show(self._secondPanel, show=False, recursive=True)
            self.btnSwitch.SetLabel(_("Switch to advanced mode"))
            self.btnCancel.SetLabel(_("Cancel"))
        else:
            self._switchSizer.Show(self._firstPanel, show=False, recursive=True)
            self._switchSizer.Show(self._secondPanel, show=True, recursive=True)
            self.btnSwitch.SetLabel(_("Switch to simple mode"))
            self.btnCancel.SetLabel(_("Close"))

        self.Freeze()  # doesn't do anything (at least on Ubuntu)
        self.btnSizer.Show(self.btnApply, simple)
        self.btnSizer.Show(self.btnOK, simple)
        self.btnSizer.Layout()
        self._switchSizer.Layout()
        self.Fit()
        self.Thaw()

        self.applyChanges.emit()

    def OnSwitchMode(self, event):
        if self._switchSizer.IsShown(self._secondPanel):
            self._switchMode(simple=True)
        else:
            self._switchMode(simple=False)

    def ValidatorCallback(self, win):
        if self._switchSizer.IsShown(self._secondPanel):
            return

        if win == self._firstRaster.GetTextCtrl():
            GMessage(parent=self, message=_("Name of the first map is missing."))
        else:
            GMessage(parent=self, message=_("Name of the second map is missing."))

    def _ok(self):
        self._apply()
        self.Close()

    def _apply(self):
        # TODO check if not empty
        self.applyChanges.emit()

    def GetValues(self):
        """Get raster maps"""
        if self.IsSimpleMode():
            return (self._firstRaster.GetValue(), self._secondRaster.GetValue())
        return (self._firstLayerList, self._secondLayerList)

    def IsSimpleMode(self) -> bool:
        return bool(self._switchSizer.IsShown(self._firstPanel))

    def GetFirstSimpleLmgr(self):
        return self._firstLmgr

    def GetSecondSimpleLmgr(self):
        return self._secondLmgr


class PreferencesDialog(PreferencesBaseDialog):
    """Mapswipe preferences dialog"""

    def __init__(
        self, parent, giface, title=_("Map Swipe settings"), settings=UserSettings
    ):
        PreferencesBaseDialog.__init__(
            self,
            parent=parent,
            giface=giface,
            title=title,
            settings=settings,
            size=(-1, 300),
        )

        # create notebook pages
        self._createMirrorModePage(self.notebook)

        self.SetMinSize(self.GetBestSize())
        self.SetSize(self.size)

    def _createMirrorModePage(self, notebook):
        """Create notebook page for general settings"""
        panel = SP.ScrolledPanel(parent=notebook)
        panel.SetupScrolling(scroll_x=False, scroll_y=True)
        notebook.AddPage(page=panel, text=_("Mirror mode"))

        border = wx.BoxSizer(wx.VERTICAL)
        box = StaticBox(parent=panel, label=" %s " % _("Mirrored cursor"))
        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
        gridSizer = wx.GridBagSizer(hgap=3, vgap=3)

        row = 0
        gridSizer.Add(
            StaticText(parent=panel, label=_("Color:")),
            flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL,
            pos=(row, 0),
        )
        color = csel.ColourSelect(
            parent=panel,
            colour=UserSettings.Get(group="mapswipe", key="cursor", subkey="color"),
            size=globalvar.DIALOG_COLOR_SIZE,
        )
        color.SetName("GetColour")
        self.winId["mapswipe:cursor:color"] = color.GetId()

        gridSizer.Add(color, pos=(row, 1), flag=wx.ALIGN_RIGHT)

        row += 1
        gridSizer.Add(
            StaticText(parent=panel, label=_("Shape:")),
            flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL,
            pos=(row, 0),
        )
        cursors = wx.Choice(
            parent=panel,
            choices=self.settings.Get(
                group="mapswipe",
                key="cursor",
                subkey=["type", "choices"],
                settings_type="internal",
            ),
            name="GetSelection",
        )
        cursors.SetSelection(
            self.settings.Get(
                group="mapswipe", key="cursor", subkey=["type", "selection"]
            )
        )
        self.winId["mapswipe:cursor:type:selection"] = cursors.GetId()

        gridSizer.Add(
            cursors,
            flag=wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
            pos=(row, 1),
        )

        row += 1
        gridSizer.Add(
            StaticText(parent=panel, label=_("Line width:")),
            flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL,
            pos=(row, 0),
        )
        width = SpinCtrl(
            parent=panel,
            min=1,
            max=10,
            initial=self.settings.Get(group="mapswipe", key="cursor", subkey="width"),
            name="GetValue",
        )
        self.winId["mapswipe:cursor:width"] = width.GetId()

        gridSizer.Add(
            width,
            flag=wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
            pos=(row, 1),
        )

        row += 1
        gridSizer.Add(
            StaticText(parent=panel, label=_("Size:")),
            flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL,
            pos=(row, 0),
        )
        size = SpinCtrl(
            parent=panel,
            min=4,
            max=50,
            initial=self.settings.Get(group="mapswipe", key="cursor", subkey="size"),
            name="GetValue",
        )
        self.winId["mapswipe:cursor:size"] = size.GetId()

        gridSizer.Add(
            size,
            flag=wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
            pos=(row, 1),
        )

        gridSizer.AddGrowableCol(1)
        sizer.Add(gridSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=3)
        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=3)
        panel.SetSizer(border)

        return panel
