"""
@package mapdisp.toolbars

@brief Map display frame - toolbars

Classes:
 - toolbars::MapToolbar

(C) 2007-2015 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 Michael Barton
@author Jachym Cepicky
@author Martin Landa <landa.martin gmail.com>
"""

import wx

from gui_core.toolbars import BaseToolbar, BaseIcons
from nviz.main import haveNviz
from vdigit.main import haveVDigit
from icons.icon import MetaIcon

MapIcons = {
    "query": MetaIcon(
        img="info",
        label=_("Query raster/vector map(s)"),
        desc=_("Query selected raster/vector map(s)"),
    ),
    "select": MetaIcon(
        img="select",
        label=_("Select vector feature(s)"),
        desc=_("Select features interactively from vector map"),
    ),
    "addBarscale": MetaIcon(img="scalebar-add", label=_("Add scale bar")),
    "addRasterLegend": MetaIcon(img="legend-add", label=_("Add raster legend")),
    "addVectorLegend": MetaIcon(img="legend-add", label=_("Add vector legend")),
    "addNorthArrow": MetaIcon(img="north-arrow-add", label=_("Add north arrow")),
    "analyze": MetaIcon(
        img="layer-raster-analyze",
        label=_("Analyze map"),
        desc=_("Measuring, profiling, histogramming, ..."),
    ),
    "measureDistance": MetaIcon(img="measure-length", label=_("Measure distance")),
    "measureArea": MetaIcon(img="area-measure", label=_("Measure area")),
    "profile": MetaIcon(img="layer-raster-profile", label=_("Profile surface map")),
    "scatter": MetaIcon(
        img="layer-raster-profile",
        label=_("Create bivariate scatterplot of raster maps"),
    ),
    "addText": MetaIcon(img="text-add", label=_("Add text")),
    "histogram": MetaIcon(
        img="layer-raster-histogram", label=_("Create histogram of raster map")
    ),
    "vnet": MetaIcon(img="vector-tools", label=_("Vector network analysis tool")),
}

NvizIcons = {
    "rotate": MetaIcon(
        img="3d-rotate",
        label=_("Rotate 3D scene"),
        desc=_("Drag with mouse to rotate 3D scene"),
    ),
    "flyThrough": MetaIcon(
        img="flythrough",
        label=_("Fly-through mode"),
        desc=_(
            "Drag with mouse, hold Ctrl down for different mode"
            " or Shift to accelerate"
        ),
    ),
    "zoomIn": BaseIcons["zoomIn"].SetLabel(desc=_("Click mouse to zoom")),
    "zoomOut": BaseIcons["zoomOut"].SetLabel(desc=_("Click mouse to unzoom")),
}


class MapToolbar(BaseToolbar):
    """Map Display toolbar"""

    def __init__(self, parent, toolSwitcher, giface):
        """Map Display constructor

        :param parent: reference to MapFrame
        """
        BaseToolbar.__init__(self, parent=parent, toolSwitcher=toolSwitcher)  # MapFrame

        self.InitToolbar(self._toolbarData())
        self._default = self.pointer
        self._giface = giface

        # optional tools
        toolNum = 0
        choices = [
            _("2D view"),
        ]
        self.toolId = {"2d": toolNum}
        toolNum += 1
        if haveNviz:
            choices.append(_("3D view"))
            self.toolId["3d"] = toolNum
            toolNum += 1
        else:
            from nviz.main import errorMsg

            self._giface.WriteCmdLog(_("3D view mode not available"))
            self._giface.WriteWarning(_("Reason: %s") % str(errorMsg))

            self.toolId["3d"] = -1

        if haveVDigit:
            choices.append(_("Vector digitizer"))
            self.toolId["vdigit"] = toolNum
            toolNum += 1
        else:
            from vdigit.main import errorMsg

            self._giface.WriteCmdLog(_("Vector digitizer not available"))
            self._giface.WriteWarning(_("Reason: %s") % errorMsg)
            self._giface.WriteLog(
                _(
                    "Note that the wxGUI's vector digitizer is disabled in this installation. "
                    "Please keep an eye out for updated versions of GRASS. "
                    'In the meantime you can use "v.edit" for non-interactive editing '
                    "from the Develop vector map menu."
                ),
                wrap=60,
            )

            self.toolId["vdigit"] = -1
        choices.append(_("Raster digitizer"))
        self.toolId["rdigit"] = toolNum

        self.combo = wx.ComboBox(
            parent=self,
            id=wx.ID_ANY,
            choices=choices,
            style=wx.CB_READONLY,
            size=(110, -1),
        )
        self.combo.SetSelection(0)

        self.comboid = self.AddControl(self.combo)
        self.parent.Bind(wx.EVT_COMBOBOX, self.OnSelectTool, self.comboid)

        # realize the toolbar
        self.Realize()

        # workaround for Mac bug. May be fixed by 2.8.8, but not before then.
        self.combo.Hide()
        self.combo.Show()

        for tool in (
            self.pointer,
            self.select,
            self.query,
            self.pan,
            self.zoomIn,
            self.zoomOut,
        ):
            self.toolSwitcher.AddToolToGroup(group="mouseUse", toolbar=self, tool=tool)

        self.EnableTool(self.zoomBack, False)

        self.FixSize(width=90)

    def _toolbarData(self):
        """Toolbar data"""
        data = (
            (
                ("renderMap", BaseIcons["render"].label),
                BaseIcons["render"],
                self.parent.OnRender,
            ),
            (
                ("pointer", BaseIcons["pointer"].label),
                BaseIcons["pointer"],
                self.parent.OnPointer,
                wx.ITEM_CHECK,
            ),
            (
                ("select", MapIcons["select"].label),
                MapIcons["select"],
                self.parent.OnSelect,
                wx.ITEM_CHECK,
            ),
            (
                ("query", MapIcons["query"].label),
                MapIcons["query"],
                self.parent.OnQuery,
                wx.ITEM_CHECK,
            ),
            (
                ("pan", BaseIcons["pan"].label),
                BaseIcons["pan"],
                self.parent.OnPan,
                wx.ITEM_CHECK,
            ),
            (
                ("zoomIn", BaseIcons["zoomIn"].label),
                BaseIcons["zoomIn"],
                self.parent.OnZoomIn,
                wx.ITEM_CHECK,
            ),
            (
                ("zoomOut", BaseIcons["zoomOut"].label),
                BaseIcons["zoomOut"],
                self.parent.OnZoomOut,
                wx.ITEM_CHECK,
            ),
            (
                ("zoomExtent", BaseIcons["zoomExtent"].label),
                BaseIcons["zoomExtent"],
                self.parent.OnZoomToMap,
            ),
            (
                ("zoomRegion", BaseIcons["zoomRegion"].label),
                BaseIcons["zoomRegion"],
                self.parent.OnZoomToWind,
            ),
            (
                ("zoomBack", BaseIcons["zoomBack"].label),
                BaseIcons["zoomBack"],
                self.parent.OnZoomBack,
            ),
            (
                ("zoomMenu", BaseIcons["zoomMenu"].label),
                BaseIcons["zoomMenu"],
                self.parent.OnZoomMenu,
            ),
            (
                ("analyze", MapIcons["analyze"].label),
                MapIcons["analyze"],
                self.OnAnalyze,
            ),
            (
                ("overlay", BaseIcons["overlay"].label),
                BaseIcons["overlay"],
                self.OnDecoration,
            ),
            (
                ("saveFile", BaseIcons["saveFile"].label),
                BaseIcons["saveFile"],
                self.parent.SaveToFile,
            ),
            (
                ("mapDispSettings", BaseIcons["mapDispSettings"].label),
                BaseIcons["mapDispSettings"],
                self.parent.OnMapDisplayProperties,
            ),
        )
        if self.parent.IsDockable():
            data = data + (
                (
                    ("mapDispDocking", BaseIcons["mapDispDocking"].label),
                    BaseIcons["mapDispDocking"],
                    self.parent.OnDockUndock,
                    wx.ITEM_CHECK,
                ),
            )
        return self._getToolbarData(data)

    def InsertTool(self, data):
        """Insert tool to toolbar

        :param data: toolbar data"""
        data = self._getToolbarData(data)
        for tool in data:
            self.CreateTool(*tool)
        self.Realize()

        self.parent._mgr.GetPane("mapToolbar").BestSize(self.GetBestSize())
        self.parent._mgr.Update()

    def RemoveTool(self, tool):
        """Remove tool from toolbar

        :param tool: tool id"""
        self.DeleteTool(tool)

        self.parent._mgr.GetPane("mapToolbar").BestSize(self.GetBestSize())
        self.parent._mgr.Update()

    def ChangeToolsDesc(self, mode2d):
        """Change description of zoom tools for 2D/3D view"""
        if mode2d:
            icons = BaseIcons
        else:
            icons = NvizIcons
        for i, data in enumerate(self.controller.data):
            for tool in ("zoomIn", "zoomOut"):
                if data[0] == tool:
                    tmp = list(data)
                    tmp[4] = icons[tool].GetDesc()
                    self.controller.data[i] = tuple(tmp)

    def OnSelectTool(self, event):
        """Select / enable tool available in tools list"""
        tool = event.GetSelection()

        if tool == self.toolId["2d"]:
            self.ExitToolbars()
            self.Enable2D(True)
            self.parent.MapWindow.SetFocus()

        elif tool == self.toolId["3d"] and not (
            self.parent.MapWindow3D and self.parent.IsPaneShown("3d")
        ):
            self.ExitToolbars()
            self.parent.AddToolbar("nviz")
            self.parent.MapWindow.SetFocus()

        elif tool == self.toolId["vdigit"] and not self.parent.GetToolbar("vdigit"):
            self.ExitToolbars()
            self.parent.AddToolbar("vdigit")
            self.parent.MapWindow.SetFocus()

        elif tool == self.toolId["rdigit"]:
            self.ExitToolbars()
            self.parent.AddToolbar("rdigit")
            self.parent.MapWindow.SetFocus()

    def OnAnalyze(self, event):
        """Analysis tools menu"""
        self._onMenu(
            (
                (MapIcons["measureDistance"], self.parent.OnMeasureDistance),
                (MapIcons["measureArea"], self.parent.OnMeasureArea),
                (MapIcons["profile"], self.parent.OnProfile),
                (MapIcons["scatter"], self.parent.OnScatterplot),
                (MapIcons["histogram"], self.parent.OnHistogramPyPlot),
                (BaseIcons["histogram"], self.parent.OnHistogram),
                (MapIcons["vnet"], self.parent.OnVNet),
            )
        )

    def OnDecoration(self, event):
        """Decorations overlay menu"""
        self._onMenu(
            (
                (MapIcons["addRasterLegend"], lambda evt: self.parent.AddLegendRast()),
                (MapIcons["addVectorLegend"], lambda evt: self.parent.AddLegendVect()),
                (MapIcons["addBarscale"], lambda evt: self.parent.AddBarscale()),
                (MapIcons["addNorthArrow"], lambda evt: self.parent.AddArrow()),
                (MapIcons["addText"], lambda evt: self.parent.AddDtext()),
            )
        )

    def ExitToolbars(self):
        if self.parent.GetToolbar("vdigit"):
            self.parent.toolbars["vdigit"].OnExit()
        self.parent.RemoveNviz()
        if self.parent.GetToolbar("rdigit"):
            self.parent.QuitRDigit()

    def Enable2D(self, enabled):
        """Enable/Disable 2D display mode specific tools"""
        for tool in (self.zoomRegion, self.zoomMenu, self.analyze, self.select):
            self.EnableTool(tool, enabled)
        self.ChangeToolsDesc(enabled)
        if enabled:
            self.combo.SetValue(_("2D view"))
