# -*- coding: utf-8 -*-
import traceback
import sys

from datetime import datetime
from io import StringIO
from time import sleep
from threading import Thread

try:
    from PyQt5.QtGui import *
    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import *

    QT = 5

except ImportError:
    from PyQt4.QtCore import *
    from PyQt4.QtGui import *

    QT = 4

from ..mdf import MDF, MDF2, MDF3, MDF4

PYVERSION = sys.version_info[0]

COLORS = [
    "#1f77b4",
    "#ff7f0e",
    "#2ca02c",
    "#d62728",
    "#9467bd",
    "#8c564b",
    "#e377c2",
    "#7f7f7f",
    "#bcbd22",
    "#17becf",
]

TERMINATED = object()


def excepthook(exc_type, exc_value, tracebackobj):
    """
    Global function to catch unhandled exceptions.

    Parameters
    ----------
    exc_type : str
        exception type
    exc_value : int
        exception value
    tracebackobj : traceback
        traceback object
    """
    separator = "-" * 80
    notice = "The following error was triggered:"

    now = datetime.now().strftime("%Y-%m-%d, %H:%M:%S")

    info = StringIO()
    traceback.print_tb(tracebackobj, None, info)
    info.seek(0)
    info = info.read()

    errmsg = "{}\t \n{}".format(exc_type, exc_value)
    sections = [now, separator, errmsg, separator, info]
    msg = "\n".join(sections)

    print(msg)

    QMessageBox.warning(None, notice, msg)


def run_thread_with_progress(widget, target, kwargs, factor, offset, progress):
    termination_request = False

    thr = WorkerThread(target=target, kwargs=kwargs)

    thr.start()

    while widget.progress is None:
        sleep(0.1)

    while thr.is_alive():
        QApplication.processEvents()
        termination_request = progress.wasCanceled()
        if termination_request:
            MDF._terminate = True
            MDF2._terminate = True
            MDF3._terminate = True
            MDF4._terminate = True
        else:
            progress.setValue(
                int(widget.progress[0] / widget.progress[1] * factor) + offset
            )
        sleep(0.1)

    if termination_request:
        MDF._terminate = False
        MDF2._terminate = False
        MDF3._terminate = False
        MDF4._terminate = False

    progress.setValue(factor + offset)

    if thr.error:
        widget.progress = None
        progress.cancel()
        raise Exception(thr.error)

    widget.progress = None

    if termination_request:
        return TERMINATED
    else:
        return thr.output


def setup_progress(parent, title, message, icon_name):
    progress = QProgressDialog(message, "", 0, 100, parent)

    progress.setWindowModality(Qt.ApplicationModal)
    progress.setCancelButton(None)
    progress.setAutoClose(True)
    progress.setWindowTitle(title)
    icon = QIcon()
    icon.addPixmap(QPixmap(":/{}.png".format(icon_name)), QIcon.Normal, QIcon.Off)
    progress.setWindowIcon(icon)
    progress.show()

    return progress


class WorkerThread(Thread):
    def __init__(self, *args, **kargs):
        super(WorkerThread, self).__init__(*args, **kargs)
        self.output = None
        self.error = ""

    def run(self):
        if PYVERSION < 3:
            try:
                self.output = self._Thread__target(
                    *self._Thread__args, **self._Thread__kwargs
                )
            except Exception as err:
                self.error = err
        else:
            try:
                self.output = self._target(*self._args, **self._kwargs)
            except Exception as err:
                self.error = err
