# 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/>.


from sys import version as python_version
import platform
import sys
import traceback

import wx

from timelinelib.meta.version import get_full_version
from timelinelib.wxgui.frames.mainframe.mainframe import MainFrame
from timelinelib.wxgui.dialogs.feedback.view import show_feedback_dialog
from timelinelib.wxgui.utils import display_warning_message


class TimelineApp(wx.App):

    def __init__(self):
        wx.App.__init__(self, False)

    def InitLocale(self):
        """
        A solution to the problem...
             wxPython4.1.1 Python3.8 locale wxAssertionError
        As suggested by Robin Dunn in this article...
        https://discuss.wxpython.org/t/wxpython4-1-1-python3-8-locale-wxassertionerror/35168/2

        Interestingly it also solves the same problem for Python version 3.6!

        Added the if statement with self._FindLanguageInfo() to detect if wx recognizes
        the current language setting. If wx does recognize the language, let wx handle InitLocale.
        """
        if self._FindLanguageInfo() is None:
            import sys
            if sys.platform.startswith('win') and sys.version_info > (3,8):
                import locale
                locale.setlocale(locale.LC_ALL, "C")
        else:
            super().InitLocale()

    def _FindLanguageInfo(self):
        import locale
        lang, enc = locale.getdefaultlocale()
        info = wx.Locale().FindLanguageInfo(lang)
        return info


def start_wx_application(before_main_loop_hook=None):
    """
    This function creates the wx.App object,
    the :doc:`MainFrame <timelinelib_wxgui_frames_mainframe_mainframe>`
    object and starts the application event loop.
    """
    app = TimelineApp()
    main_frame = MainFrame()
    main_frame.Show()
    sys.excepthook = _unhandled_exception_hook
    if before_main_loop_hook:
        before_main_loop_hook()
    app.MainLoop()


def setup_humblewx():
    """Initializes the humblewx module."""
    import timelinelib.wxgui.components
    import humblewx
    humblewx.COMPONENT_MODULES.insert(0, timelinelib.wxgui.components)


def _unhandled_exception_hook(exception_type, value, tb):
    """
    This function is called when an unhandled exception occurs and it
    displays a feedback dialog in which the user can send an error report
    to the Timeline team.
    """
    show_feedback_dialog(
        parent=None,
        info=_create_info_message(),
        subject=_create_subject(exception_type, value),
        body=_create_error_message(exception_type, value, tb))


def _create_info_message():
    return ("An unexpected error has occurred. Help us fix it by reporting "
            "the error through this form. ")


def _create_subject(exception_type, value):
    return "".join(traceback.format_exception_only(exception_type, value)).strip()


def _create_error_message(exception_type, value, tb):
    return "\n".join([
        "Stacktrace:",
        "",
        _indent(("".join(traceback.format_exception(exception_type, value, tb))).strip()),
        "",
        "Environment:",
        "",
        _indent(_create_versions_message()),
        _indent(_create_locale_message()),
    ])


def _create_versions_message():
    return "\n".join([
        "Timeline version: %s" % get_full_version(),
        "System version: %s" % ", ".join(platform.uname()),
        "Python version: %s" % python_version.replace("\n", ""),
        "wxPython version: %s" % wx.version(),
    ])


def _create_locale_message():
    loc = wx.Locale()
    language_name = loc.GetLanguageName(loc.GetSystemLanguage())
    encoding_name = loc.GetSystemEncodingName()
    locale_info = '%s %s' % (language_name, encoding_name)
    return "\n".join([
        "Locale setting: %s" % locale_info,
        "Locale sample date: 3333-11-22",
    ])


def _indent(text):
    return "\n".join("    " + x for x in text.split("\n"))
