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

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


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)
        self.main.visibilityChanged.connect(self._synchronize_visibility)

    @property
    def number_of_columns(self):
        """
        Return the number of visible columns.
        """
        return self.count()

    def clear_containers(self):

        for maker in self.diagram_makers:
            maker.clear_diagrams()

    def show_main(self, show: bool):
        """
        Show/hide main plot.
        """
        self.main.visibilityChanged.disconnect(self._synchronize_visibility)
        self.main.setVisible(show)
        self.main.visibilityChanged.connect(self._synchronize_visibility)

    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):
        """
        For now if main plot is not visible, all container is not visible.
        """

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

        for i in range(self.count()):
            # prevent infinite loop, since signal come from self.main
            if self.widget(i) == self.main:
                continue
            self.widget(i).setVisible(value)

        self.setVisible(value)

    def setParent(self, parent):
        """
        To avoid deletion of children when container is deleted.
        """
        if parent is None:
            try:
                for i in reversed(range(self.count())):
                    self.widget(i).setParent(None)
            except RuntimeError:
                pass
            super().setParent(parent)

    def are_diagrams_contained(self):
        """
        Check if additional widget are contained.
        """
        return self.count() > 1

    def getAxis(self, name: str):
        return self.main.getAxis(name)

    def showLabel(self, axis: str, show: bool):
        return self.main.showLabel(axis, show)

    def isHidden(self):
        return self.main.isHidden() and not self.are_diagrams_contained()

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

    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
