import pymoku
from contextlib import suppress
from pymoku.applets.registers import RegisterTree

from . import SlotFrameSettings

from qtconsole import inprocess

from PySide6.QtCore import Qt, QKeyCombination, Signal
from PySide6.QtWidgets import QMainWindow, QDockWidget


class JupyterConsoleWidget(inprocess.QtInProcessRichJupyterWidget):
    def __init__(self):
        super().__init__()

        self.kernel_manager = inprocess.QtInProcessKernelManager()
        self.kernel_manager.start_kernel()
        self.kernel_client = self.kernel_manager.client()
        self.kernel_client.start_channels()

    def shutdown_kernel(self):
        self.kernel_client.stop_channels()
        self.kernel_manager.shutdown_kernel()


class DefaultFrame(QMainWindow, SlotFrameSettings):
    RELOAD_COMBO = QKeyCombination(Qt.ControlModifier | Qt.ShiftModifier, Qt.Key_R)

    request_reload = Signal(object)

    def __init__(self, moku, slot_inst, name):
        assert isinstance(slot_inst, pymoku.Slot)
        self.moku = moku
        self.slot_inst = slot_inst
        super().__init__()
        self.setWindowTitle(f'{moku.name} - {name}')

        with slot_inst.cached_registers():
            self.add_widgets(moku, slot_inst)

        self.setDockOptions(QMainWindow.AnimatedDocks
                            | QMainWindow.AllowTabbedDocks
                            | QMainWindow.VerticalTabs)

        self.restore_state()

    def add_widgets(self, moku, slot_inst):
        console = JupyterConsoleWidget()
        console_dock = QDockWidget('Console')
        console_dock.setWidget(console)
        console_dock.setObjectName('dock-console')
        self.addDockWidget(Qt.LeftDockWidgetArea, console_dock)
        self.console_dock = console_dock

        reg_tree = RegisterTree(moku, slot_inst)
        regs_dock = QDockWidget('Registers')
        regs_dock.setWidget(reg_tree)
        regs_dock.setObjectName('dock-regs')
        self.addDockWidget(Qt.LeftDockWidgetArea, regs_dock)
        self.regs_dock = regs_dock

        self.tabifyDockWidget(regs_dock, console_dock)

        namespace = dict(moku=moku, slot=slot_inst, pymoku=pymoku, frame=self)
        console.kernel_manager.kernel.shell.push(dict(**namespace))
        self.console = console
        console.set_default_style("linux")

    def close(self):
        with suppress(AttributeError, Exception):
            self.console.shutdown_kernel()
        self.save_state()
        super().close()

    def keyPressEvent(self, event):
        if event.keyCombination() == self.RELOAD_COMBO:
            self.request_reload.emit(self)
            event.accept()
