# Copyright (C) 2006-2011, University of Maryland
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/ or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# Author: James Krycka

"""
This module implements the AppFrame class which creates the main frame of the
GUI for the Bumps application including a basic menu, tool bar, and status bar.
"""

# ==============================================================================

import sys

import wx

from .about import AboutDialog, APP_TITLE, APP_DESCRIPTION, APP_LICENSE, APP_CREDITS, APP_TUTORIAL
from .app_panel import AppPanel
from .console import NumpyConsole
from .utilities import resource, choose_fontsize, display_fontsize

# Resource files.
PROG_ICON = "bumps.ico"


# ==============================================================================
class ModelConsole(NumpyConsole):
    def OnChanged(self, added=(), changed=(), removed=()):
        pass

    def OnClose(self, event):
        self.Show(False)


class AppFrame(wx.Frame):
    """
    This class creates the top-level frame for the application and populates it
    with application specific panels and widgets.
    """

    def __init__(
        self, parent=None, id=wx.ID_ANY, title=APP_TITLE, pos=wx.DefaultPosition, size=wx.DefaultSize, name="AppFrame"
    ):
        wx.Frame.__init__(self, parent, id, title, pos, size, name=name)

        # Display the application's icon in the title bar.
        icon = wx.Icon(resource(PROG_ICON), wx.BITMAP_TYPE_ICO)
        self.SetIcon(icon)

        # Set the default font family and font size for the application.
        self.set_default_font()

        # Initialize the menu bar with common items.
        self.add_menubar()

        # Initialize the tool bar.
        self.add_toolbar()

        # Initialize the status bar.
        self.add_statusbar()

        # Build the application panels for the GUI on the frame.
        self.panel = AppPanel(self)
        self.panel.console = ModelConsole(self)
        self.panel.console["app"] = self

        # Note: Do not call self.Fit() as this will reduce the frame to its
        # bare minimum size; we want it to keep its default size.

    def set_default_font(self):
        """
        Sets the default font family and font size for the frame which will be
        inherited by all child windows subsequently created.
        """

        # Save the system default font information before we make any changes.
        default_fontname = self.GetFont().GetFaceName()
        default_fontsize = self.GetFont().GetPointSize()

        # If requested, override the font name to use.  Note that:
        # - the MS Windows default font appears to be the same as Tahoma
        # - Arial tends to be narrower and taller than Tahoma.
        # - Verdana tends to be wider and shorter than Tahoma.
        fontname = default_fontname
        if len(sys.argv) > 1:
            if "--tahoma" in sys.argv[1:]:
                fontname = "Tahoma"
            if "--arial" in sys.argv[1:]:
                fontname = "Arial"
            if "--verdana" in sys.argv[1:]:
                fontname = "Verdana"

        fontsize = choose_fontsize(fontname=fontname)

        # If requested, override the font point size to use.
        if len(sys.argv) > 1:
            if "--12pt" in sys.argv[1:]:
                fontsize = 12
            if "--11pt" in sys.argv[1:]:
                fontsize = 11
            if "--10pt" in sys.argv[1:]:
                fontsize = 10
            if "--9pt" in sys.argv[1:]:
                fontsize = 9
            if "--8pt" in sys.argv[1:]:
                fontsize = 8
            if "--7pt" in sys.argv[1:]:
                fontsize = 7
            if "--6pt" in sys.argv[1:]:
                fontsize = 6

        # Set the default font for this and all child windows.  The font of the
        # frame's title bar is not affected (which is a good thing).  However,
        # setting the default font does not affect the font used in the frame's
        # menu bar or menu items (which is not such a good thing because the
        # menu text size be different than the size used by the application's
        # other widgets).  The menu font cannot be changed by wxPython.
        self.SetFont(wx.Font(fontsize, wx.SWISS, wx.NORMAL, wx.NORMAL, False, fontname))

        # If requested, display font and miscellaneous platform information.
        if len(sys.argv) > 1 and "--platform" in sys.argv[1:]:
            print("*** Platform =", wx.PlatformInfo)
            print("*** Default font is %s  Chosen font is %s" % (default_fontname, self.GetFont().GetFaceName()))
            print(
                "*** Default point size = %d  Chosen point size = %d"
                % (default_fontsize, self.GetFont().GetPointSize())
            )
            display_fontsize(fontname=fontname)

    def add_menubar(self):
        """Creates a default menu bar, menus, and menu options."""

        # Create the menu bar.
        mb = wx.MenuBar()
        # wx.MenuBar.SetAutoWindowMenu(False)

        # Add a 'File' menu to the menu bar and define its options.
        file_menu = wx.Menu()

        _item = file_menu.Append(wx.ID_ANY, "&Exit", "Terminate application")
        self.Bind(wx.EVT_MENU, self.OnExit, _item)

        mb.Append(file_menu, "&File")

        # Add a 'Help' menu to the menu bar and define its options.
        help_menu = wx.Menu()

        _item = help_menu.Append(wx.ID_ANY, "&About", "Get description of application")
        self.Bind(wx.EVT_MENU, self.OnAbout, _item)
        _item = help_menu.Append(wx.ID_ANY, "&Documentation", "Get User's Guide and Reference Manual")
        self.Bind(wx.EVT_MENU, self.OnTutorial, _item)
        _item = help_menu.Append(wx.ID_ANY, "License", "Read license and copyright notice")
        self.Bind(wx.EVT_MENU, self.OnLicense, _item)
        _item = help_menu.Append(wx.ID_ANY, "Credits", "Get list of authors and sponsors")
        self.Bind(wx.EVT_MENU, self.OnCredits, _item)

        help_menu.AppendSeparator()
        _item = help_menu.Append(wx.ID_ANY, "&Console", "Interactive Python shell")
        self.Bind(wx.EVT_MENU, self.OnConsole, _item)

        mb.Append(help_menu, "&Help")

        # Attach the menu bar to the frame.
        self.SetMenuBar(mb)

    def add_toolbar(self):
        """Creates a default tool bar."""

        # tb = self.CreateToolBar()
        tb = wx.ToolBar(parent=self, style=wx.TB_HORIZONTAL | wx.NO_BORDER)
        tb.Realize()
        self.SetToolBar(tb)

    def add_statusbar(self):
        """Creates a default status bar."""

        sb = self.statusbar = self.CreateStatusBar()
        sb.SetFieldsCount(1)

    def OnAbout(self, evt):
        """Shows the About dialog box."""

        dlg = AboutDialog(
            parent=self,
            title="About",
            info=APP_DESCRIPTION,
            show_name=True,
            show_notice=True,
            show_link=True,
            show_link_docs=True,
        )
        dlg.ShowModal()
        dlg.Destroy()

    def OnCredits(self, evt):
        """Shows the Credits dialog box."""

        dlg = AboutDialog(
            parent=self,
            title="Credits",
            info=APP_CREDITS,
            show_name=True,
            show_notice=True,
            show_link=False,
            show_link_docs=False,
        )
        dlg.ShowModal()
        dlg.Destroy()

    def OnExit(self, event):
        """Terminates the program."""
        self.Close()

    def OnLicense(self, evt):
        """Shows the License dialog box."""

        dlg = AboutDialog(
            parent=self,
            title="License",
            info=APP_LICENSE,
            show_name=True,
            show_notice=True,
            show_link=False,
            show_link_docs=False,
        )
        dlg.ShowModal()
        dlg.Destroy()

    def OnTutorial(self, event):
        """Shows the Tutorial dialog box."""

        dlg = AboutDialog(
            parent=self,
            title="Tutorial",
            info=APP_TUTORIAL,
            show_name=False,
            show_notice=False,
            show_link=False,
            show_link_docs=True,
        )
        dlg.ShowModal()
        dlg.Destroy()

    def OnConsole(self, event):
        """Raise python console."""
        self.panel.console.Show(True)
