import os

from qgis.PyQt import QtCore, uic
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import QAbstractItemView, QWidget

from openlog.__about__ import DIR_PLUGIN_ROOT
from openlog.datamodel.assay.generic_assay import AssayDataExtent, AssaySeriesType
from openlog.gui.assay_visualization.stacked.stacked_config import StackedConfiguration
from openlog.gui.assay_visualization.stacked.stacked_config_table_model import (
    StackConfigTableModel,
)
from openlog.gui.assay_visualization.stacked.stacked_utils import invalid_series_type
from openlog.plugins.manager import get_plugin_manager


class StackedConfigCreationWidget(QWidget):
    add_stacked_config = QtCore.pyqtSignal()
    create_cross_plot = QtCore.pyqtSignal()

    def __init__(self, parent=None) -> None:
        """
        QWidget to display stacked configuration creation.

        Use StackConfigTableModel for table definition

        Args:
            parent: QWidget parent
        """
        super().__init__(parent)

        uic.loadUi(
            os.path.dirname(os.path.realpath(__file__))
            + "/stacked_config_creation_widget.ui",
            self,
        )

        self.stacked_config_table_model = StackConfigTableModel(self)
        self.tableView.setModel(self.stacked_config_table_model)
        self.tableView.setEditTriggers(QAbstractItemView.NoEditTriggers)

        # Check configuration for creation button enable
        self.create_push_button.setEnabled(False)
        self.create_push_button.setIcon(
            QIcon(str(DIR_PLUGIN_ROOT / "resources" / "images" / "stacked_curves.svg"))
        )
        self.create_push_button.setIconSize(QtCore.QSize(40, 40))
        self.create_push_button.setToolTip("Create multiplot")
        self.stacked_config_table_model.dataChanged.connect(self._check_stacked_config)
        self.create_push_button.clicked.connect(lambda: self.add_stacked_config.emit())

        # cross plot button
        self.crossplot_enabled = get_plugin_manager().get_crossplots_plugin().enable
        self.create_crossplot_btn.setIcon(
            QIcon(str(DIR_PLUGIN_ROOT / "resources" / "images" / "scatterplot.svg"))
        )
        self.create_crossplot_btn.setIconSize(QtCore.QSize(40, 40))
        self.create_crossplot_btn.setToolTip("Create crossplot")
        self.create_crossplot_btn.setVisible(True)
        if not self.crossplot_enabled:
            self.create_crossplot_btn.setEnabled(False)
            self.create_crossplot_btn.setToolTip("Create crossplot (Premium only)")

        self.create_crossplot_btn.clicked.connect(lambda: self.create_cross_plot.emit())

    def set_stacked_configuration(self, config: StackedConfiguration) -> None:
        """
        Define displayed StackedConfiguration

        Args:
            config: StackedConfiguration
        """
        self.stacked_config_table_model.dataChanged.disconnect(
            self._check_stacked_config
        )
        self.stacked_config_table_model.set_stacked_config(config)
        self.stacked_config_table_model.dataChanged.connect(self._check_stacked_config)
        self._check_stacked_config()

    def get_stacked_configuration(self) -> StackedConfiguration:
        """
        Returns display StackedConfiguration

        Returns: StackedConfiguration

        """
        return self.stacked_config_table_model.get_stacked_config()

    def _check_stacked_config(self) -> None:
        """
        Check if StackedConfiguration is valid and enable/disable create button

        """

        # enable/disable crossplot button
        self._enable_crossplot_btn()

        stacked_config = self.get_stacked_configuration()
        self.create_push_button.setEnabled(stacked_config.is_valid())
        if not stacked_config.is_valid():
            invalid_series_name = ",".join([s.name for s in invalid_series_type()])
            self.create_push_button.setToolTip(
                f"Invalid stacked. Check if multiple unit or series type are used. ({invalid_series_name}) series types are not supported"
            )
        else:
            self.create_push_button.setToolTip("Create multiplot")

    def _enable_crossplot_btn(self) -> None:
        """
        Check if a crossplot is possible.
        """
        if not self.crossplot_enabled:
            return

        s = self.get_stacked_configuration()
        variables = list(
            set([config.assay.assay_definition.variable for config in s.config_list])
        )
        columns = list(set([config.column.name for config in s.config_list]))
        extents = list(
            set([config.assay.assay_definition.data_extent for config in s.config_list])
        )
        serie_type = list(set([config.column.series_type for config in s.config_list]))
        only_numeric = len(extents) == 1 and extents[0] == AssayDataExtent.DISCRETE
        only_discrete = (
            len(serie_type) == 1 and serie_type[0] == AssaySeriesType.NUMERICAL
        )
        valid = (
            len(s.config_list) > 1
            and len(variables) == 1
            and len(columns) == 2
            and only_numeric
            and only_discrete
        )
        self.create_crossplot_btn.setEnabled(valid)
