# Copyright (C) 2016-2019 Damon Lynch <damonlynch@gmail.com>

# This file is part of Rapid Photo Downloader.
#
# Rapid Photo Downloader 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.
#
# Rapid Photo Downloader 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 Rapid Photo Downloader. If not,
# see <http://www.gnu.org/licenses/>.


__author__ = 'Damon Lynch'
__copyright__ = "Copyright 2016-2019, Damon Lynch"


import logging
import traceback
import io
import os
from urllib.request import pathname2url
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QMessageBox, QApplication
from PyQt5.QtGui import QPixmap
try:
    from easygui import codebox
    have_easygui = True
except:
    # if import failed for any reason, ignore it
    have_easygui = False

from gettext import gettext as _
import raphodo.qrc_resources as qrc_resources

from raphodo.iplogging import full_log_file_path
from raphodo.storage import get_uri
from raphodo.preferences import Preferences

message_box_displayed = False
exceptions_notified = set()


def excepthook(exception_type, exception_value, traceback_object) -> None:
    """
    Global function to catch unhandled exceptions.

    Inspired by function of the same name in the Eric project.
    """

    if traceback_object is not None:
        frame = traceback_object.tb_frame
        filename = frame.f_code.co_filename
        lineno = traceback_object.tb_lineno
    else:
        lineno = -1
        filename = 'unknown'
    key = '{}{}'.format(filename, lineno)

    global message_box_displayed

    tb_file = io.StringIO()
    traceback.print_exception(exception_type, exception_value, traceback_object,
                              limit=None, file=tb_file)
    tb_file.seek(0)
    traceback_info = tb_file.read()

    logging.error("An unhandled exception occurred")
    logging.error(traceback_info)

    if not message_box_displayed and key not in exceptions_notified:
        message_box_displayed = True
        exceptions_notified.add(key)

        log_path, log_file = os.path.split(full_log_file_path())
        log_uri = get_uri(log_path)

        prefs = Preferences()

        config_path, config_file = os.path.split(prefs.settings_path())
        config_uri = get_uri(path=config_path)

        title = _("Problem in Rapid Photo Downloader")

        if QApplication.instance():

            message = _(r"""<b>A problem occurred in Rapid Photo Downloader</b><br><br>
            Please report the problem at <a href="{website}">{website}</a>.<br><br>
            Include in your bug report the program's log files. The bug report must include 
            <i>{log_file}</i>, but attaching the other log files is often helpful.<br><br> 
            If possible, please also include the program's configuration file
            <i>{config_file}</i>.<br><br> 
            Click <a href="{log_path}">here</a> to open the log directory, and 
            <a href="{config_path}">here</a> to open the configuration directory.<br><br>
            If the same problem occurs again before the program exits, this is the only notification 
            about it.
            """).format(
                website='https://bugs.launchpad.net/rapid', log_path=log_uri, log_file=log_file,
                config_path=config_uri, config_file=config_file
            )

            icon = QPixmap(':/rapid-photo-downloader.svg')

            errorbox = QMessageBox()
            errorbox.setTextFormat(Qt.RichText)
            errorbox.setIconPixmap(icon)
            errorbox.setWindowTitle(title)
            errorbox.setText(message)
            errorbox.setDetailedText(traceback_info)
            errorbox.exec_()
        elif have_easygui:
            message = _('A problem occurred in Rapid Photo Downloader\n')
            prefix = _("""Please report the problem at {website}\n
    Attach the log file to your bug report, found at {log_path}\n\n""").format(
                website='https://bugs.launchpad.net/rapid', log_path=full_log_file_path())
            text = prefix + traceback_info
            codebox(msg=message, title=title, text=text)
        message_box_displayed = False

