from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtWidgets import QSplitter, QWidget

from openlog.gui.assay_visualization.assay_plot_widget import (
    AssayDomainType,
    AssayPlotWidget,
)
from openlog.plugins.manager import get_plugin_manager

manager = get_plugin_manager()


class PlotWidgetContainer(QSplitter):
    def __init__(self, parent, main: AssayPlotWidget):
        """
        Generic plot container.
        It consists of 1 main splitter containing AssayPlotWidget, and an optionnal splitter to add various widgets.
        """
        super().__init__(parent)
        self._parent = parent
        self.main = main
        self.setOrientation(
            Qt.Horizontal if self.main.domain == AssayDomainType.DEPTH else Qt.Vertical
        )
        self.setChildrenCollapsible(False)

        self.diagram_list = []
        self.data = None
        self.splitter = None
        self.addWidget(main)

        # synchronize PlotWidget visibility with parent container
        self.main.visibilityChanged.connect(self._synchronize_visibility)
        self.setHidden(self.main.isHidden())

        # list of DiagramsMaker instance
        self.diagram_makers = []

        # set diagram makers
        for serie_hook in manager.get_serie_types():
            if callable(serie_hook.get_diagram_maker):
                diagram_maker = serie_hook.get_diagram_maker(self)
                self.diagram_makers += diagram_maker

    def set_diagrams(self, maker_id: str, options: dict):
        """
        Generic method to be called when displaying diagrams.
        Args:
            - maker : maker id
            - opts: options
        """
        for maker in self.diagram_makers:
            if maker.id == maker_id:
                maker.set_diagrams(**options)
                break

        self._resize_widgets()

    def _synchronize_visibility(self, value: bool):

        if self.splitter:
            self.splitter.setVisible(value)

    def setParent(self, parent):
        """
        To avoid deletion of AssayPlotWidget when container is deleted.
        """
        if parent is None:
            # self.clear_diagrams()
            try:
                self.main.setParent(None)
            except RuntimeError:
                pass
            super().setParent(parent)

    def isHidden(self):
        return self.main.isHidden()

    def isVisible(self):
        return self.main.isVisible()

    def setYRange(self, r, padding=0.05):
        return self.main.setYRange(r, padding)

    def setXRange(self, r, padding=0.05):
        return self.main.setXRange(r, padding)

    def setYLink(self, widget):
        return self.main.setYLink(widget.main)

    def setXLink(self, widget):
        return self.main.setXLink(widget.main)

    def showAxis(self, axis: str):
        return self.main.showAxis(axis)

    def hideAxis(self, axis: str):
        return self.main.hideAxis(axis)

    def getViewBox(self):
        return self.main.getViewBox()

    def get_data_bounds(self):
        return self.main.get_data_bounds()

    def set_limits(self, min_domain_axis: float, max_domain_axis: float):

        return self.main.set_limits(min_domain_axis, max_domain_axis)

    def update_displayed_unit(self):
        return self.main.update_displayed_unit()

    def clear(self):
        return self.main.clear()

    def removeItem(self, item):
        return self.main.removeItem(item)

    def addItem(self, *args, **kargs):
        return self.main.addItem(*args, **kargs)

    def enable_inspector_sync(self, sync_inspector, enable):
        return self.main.enable_inspector_sync(sync_inspector, enable)

    def enable_inspector_line(self, enable: bool):
        return self.main.enable_inspector_line(enable)

    def _resize_widgets(self):
        """
        Expand main splitter to equal spaces.
        """

        width = self.width()
        n = self.count()
        self.setSizes([int(width / n) for i in range(n)])

    @property
    def inspector(self):
        return self.main.inspector

    @property
    def plotItem(self):
        return self.main.plotItem
