import os

import pyqtgraph.parametertree as ptree
from qgis.core import QgsApplication
from qgis.PyQt import uic
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import QHeaderView, QWidget

from openlog.__about__ import DIR_PLUGIN_ROOT
from openlog.gui.assay_visualization.multiplot.multiplot_config import (
    MultiplotConfiguration,
)


class CompositionConfigWidget(QWidget):
    def __init__(self, parent: QWidget = None):
        """
        Widget for MultiplotConfiguration display and edition.
        User can change assay columns configuration.

        Args:
            parent: parent object
        """
        super().__init__(parent)
        self.setMinimumWidth(300)

        uic.loadUi(
            os.path.join(os.path.dirname(__file__), "composition_config_widget.ui"),
            self,
        )

        self.multiplot_config = None
        self.crossplot_config = None

        # Add parameter tree
        self.parameter_tree = ptree.ParameterTree(self)
        self.parameter_tree.header().setSectionResizeMode(QHeaderView.Interactive)
        self.param_layout.addWidget(self.parameter_tree)

        self.check_all_button.clicked.connect(self.check_all)
        self.uncheck_all_button.clicked.connect(self.uncheck_all)
        self.collapse_button.setIcon(QIcon(QgsApplication.iconPath("mIconExpand.svg")))
        self.collapse_button.setText("")
        self.collapse_button.setToolTip("Collapse all")
        self.collapse_button.clicked.connect(self.collapse)

        self.uncheck_all_button.setText("")
        self.uncheck_all_button.setToolTip("Uncheck all")
        self.uncheck_all_button.setIcon(
            QIcon(
                str(DIR_PLUGIN_ROOT / "resources" / "images" / "icon_uncheck_all.svg")
            )
        )

        self.check_all_button.setText("")
        self.check_all_button.setToolTip("Check all")
        self.check_all_button.setIcon(
            QIcon(str(DIR_PLUGIN_ROOT / "resources" / "images" / "icon_check_all.svg"))
        )

    def _hide_buttons(self):

        self.check_all_button.setVisible(False)
        self.uncheck_all_button.setVisible(False)
        self.collapse_button.setVisible(False)

    def _show_buttons(self):

        self.check_all_button.setVisible(True)
        self.uncheck_all_button.setVisible(True)
        self.collapse_button.setVisible(True)

    def set_crossplot_config(self, crossplot_config) -> None:
        """
        Define parameter for a crossplot configuration

        Args:
            crossplot_config: (CrossPlotConfig)
        """
        self.parameter_tree.header().setSectionResizeMode(QHeaderView.ResizeToContents)
        # hide buttons
        self._hide_buttons()
        self.crossplot_config = crossplot_config
        self.multiplot_label_values.setText(crossplot_config.name)
        self.parameter_tree.clear()
        # Define params for all assay column
        all_params = ptree.Parameter.create(name="Columns", type="group")
        all_params.addChild(crossplot_config.get_pyqtgraph_params())

        # disconnect all signals for speed
        crossplot_config.disconnect_all_signals()
        self.parameter_tree.setParameters(all_params, showTop=False)
        crossplot_config.connect_all_signals()

    def set_stacked_plot_config(self, stacked_plot_config) -> None:
        """
        Define parameter for a stacked plot configuration

        Args:
            stacked_plot_config: (StackedPlotConfig)
        """
        self.parameter_tree.header().setSectionResizeMode(QHeaderView.ResizeToContents)
        # hide buttons
        self._hide_buttons()
        self.stacked_plot_config = stacked_plot_config
        self.multiplot_label_values.setText(stacked_plot_config.name)
        self.parameter_tree.clear()
        # Define params for all assay column
        all_params = ptree.Parameter.create(name="Columns", type="group")
        all_params.addChild(stacked_plot_config.get_pyqtgraph_params())

        self.parameter_tree.setParameters(all_params, showTop=False)

    def set_multiplot_config(self, multiplot_config: MultiplotConfiguration) -> None:
        """
        Define parameter for a multiplot configuration

        Args:
            multiplot_config: (MultiplotConfiguration)
        """
        self.parameter_tree.header().setSectionResizeMode(QHeaderView.Interactive)
        self._show_buttons()
        self.multiplot_config = multiplot_config

        self.multiplot_label_values.setText(multiplot_config.name)

        self.parameter_tree.clear()

        # Define params for all assay column
        all_params = ptree.Parameter.create(name="Columns", type="group")

        for param in multiplot_config.get_pyqtgraph_params():
            all_params.addChild(param)

        for config in multiplot_config.config_list:

            all_params.addChild(config.get_pyqtgraph_param())

        # set one transformation group to control global plot options
        if multiplot_config.global_param is None:
            multiplot_config.set_global_param()
            multiplot_config.update_global_param()
        global_param = multiplot_config.global_param

        all_params.insertChild(0, global_param)

        self.parameter_tree.setParameters(all_params, showTop=False)

        for config in multiplot_config.config_list:
            for w in config.create_configuration_widgets(self):
                self.param_layout.addWidget(w)

    def check_all(self) -> None:
        """
        Check all visibility parameters for displayed configuration

        """
        self._check_all(True)

    def uncheck_all(self) -> None:
        """
        Uncheck all visibility parameters for displayed configuration

        """
        self._check_all(False)

    def _check_all(self, checked: bool) -> None:
        """
        Check or uncheck all visibility parameters for displayed configuration

        Args:
            checked: (bool) visibility parameter value
        """
        for assay_column_config in self.multiplot_config.config_list:
            assay_column_config.visibility_param.setValue(checked)

    def collapse(self) -> None:
        """
        Collapse all visibility parameters

        """
        if self.multiplot_config is None:
            return

        for assay_column_config in self.multiplot_config.config_list:
            assay_column_config.visibility_param.setOpts(syncExpanded=True)
            assay_column_config.visibility_param.setOpts(expanded=False)

        # apply to global plot options
        if self.multiplot_config.global_param:
            self.multiplot_config.global_param.setOpts(syncExpanded=True)
            self.multiplot_config.global_param.setOpts(expanded=False)
