''' cpdctrl_gui/init.py '''
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import QApplication
from .ui.main_window import MainWindow
from .utility.config import AppConfig

from . import resources
# This is necessary to set the taskbar icon
import ctypes
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(u'n203.cpdctrl-gui.1')

def run() -> int:
    """
    Initializes the application and runs it.

    Returns:
        int: The exit status code.
    """
    log.debug("Starting app")
    app: QApplication = QApplication(sys.argv)
    icon_path = resources.get_resource_path("icons/icon.png")
    app.setWindowIcon(QIcon(icon_path))

    window: MainWindow = MainWindow()
    window.show()
    exitcode = app.exec()
    log.info("Saving configuration")
    AppConfig.finalize()
    return sys.exit(exitcode)


import sys
import traceback
import logging
from PyQt6 import QtCore, QtWidgets
from os import path, makedirs

AppConfig.initialize()
log_path = path.expanduser(AppConfig.MAIN_CFG.get_or("path_log", "~/.cache/cpdctrl-gui.log"))
makedirs(path.dirname(log_path), exist_ok=True)
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] [%(name)s] %(message)s",
    handlers=[
        logging.FileHandler(log_path),
        logging.StreamHandler()
    ]
)
log = logging.getLogger(__name__)

# This is taken from:
# https://timlehr.com/2018/01/python-exception-hooks-with-qt-message-box/index.html
handler = logging.StreamHandler(stream=sys.stdout)
log.addHandler(handler)

def show_exception_box(log_msg):
    """Checks if a QApplication instance is available and shows a messagebox with the exception message.
    If unavailable (non-console application), log an additional notice.
    """
    if QtWidgets.QApplication.instance() is not None:
            errorbox = QtWidgets.QMessageBox()
            errorbox.setText("Oops. An unexpected error occured:\n{0}".format(log_msg))
            errorbox.exec()
    else:
        log.debug("No QApplication instance available.")

class UncaughtHook(QtCore.QObject):
    _exception_caught = QtCore.pyqtSignal(object)

    def __init__(self, *args, **kwargs):
        super(UncaughtHook, self).__init__(*args, **kwargs)

        # this registers the exception_hook() function as hook with the Python interpreter
        sys.excepthook = self.exception_hook

        # connect signal to execute the message box function always on main thread
        self._exception_caught.connect(show_exception_box)

    def exception_hook(self, exc_type, exc_value, exc_traceback):
        """Function handling uncaught exceptions.
        It is triggered each time an uncaught exception occurs.
        """
        if issubclass(exc_type, KeyboardInterrupt):
            # ignore keyboard interrupt to support console applications
            sys.__excepthook__(exc_type, exc_value, exc_traceback)
        else:
            exc_info = (exc_type, exc_value, exc_traceback)
            log_msg = '\n'.join([''.join(traceback.format_tb(exc_traceback)),
                                 '{0}: {1}'.format(exc_type.__name__, exc_value)])
            log.critical(f"Uncaught exception:\n {log_msg}", exc_info=exc_info)

            # trigger message box show
            self._exception_caught.emit(log_msg)

# create a global instance of our class to register the hook
# qt_exception_hook = UncaughtHook()