import pyqtgraph as pg
import pyqtgraph.parametertree as ptree
import pyqtgraph.parametertree.parameterTypes as pTypes

from openlog.datamodel.assay.generic_assay import AssayColumn
from openlog.gui.assay_visualization.config.assay_column_visualization_config import (
    AssayColumnVisualizationConfig,
)
from openlog.plugins.visualization.structural.saver import DiscreteStructuralSaver


class DiscreteStructuralAssayColumnVisualizationConfig(AssayColumnVisualizationConfig):
    """
    Store visualization configuration for a discrete catgerical assay column.
        Can also access plot item if configuration created from visualization widget

        Configuration supported :

        Args:
            column: (str) assay column name
    """

    DEFAULT_SIZE = 50

    def __init__(self, column: AssayColumn):
        super().__init__(column)

        self.is_splittable = False
        self.is_discrete = True
        self.is_minmax_registered = False
        self.is_switchable_config = False
        self.is_categorical = False

        self.as_extended = False
        self.pen_params = None
        self.symbol_group = ptree.Parameter.create(name="Symbol", type="group")
        self.symbol_group.setOpts(expanded=False)

        self.symbol_size_parameter = pTypes.SimpleParameter(
            name="Size",
            type="int",
            value=self.DEFAULT_SIZE,
            default=self.DEFAULT_SIZE,
            min=20,
            max=3000,
        )
        self.symbol_group.addChild(self.symbol_size_parameter)

        self.symbol_size_parameter.sigValueChanged.connect(self.update_symbol)

        # add grids
        self.grid_x_param = ptree.Parameter.create(
            name="X grid",
            type="bool",
            value=False,
            default=False,
        )
        self.transformation_group.addChild(self.grid_x_param)
        self.grid_y_param = ptree.Parameter.create(
            name="Y grid",
            type="bool",
            value=False,
            default=False,
        )
        self.transformation_group.addChild(self.grid_y_param)
        self.grid_x_param.sigValueChanged.connect(self._display_axis_grid)
        self.grid_y_param.sigValueChanged.connect(self._display_axis_grid)

    def _display_axis_grid(self) -> None:
        """
        Enable/disable x and/or y grid on pyqtgraph plot.
        """
        x = self.grid_x_param.value()
        y = self.grid_y_param.value()
        plot_widget = self.get_current_plot_widget()

        if plot_widget:
            plot_widget.plotItem.display_grids(x, y)

    def update_symbol(self):
        if self.plot_item and self.symbol_group:
            self.plot_item.setSize(self.symbol_size_parameter.value())

    def set_plot_item(self, plot_item: pg.ScatterPlotItem) -> None:
        """
        Define plot item containing current assay data

        Args:
            plot_item: pg.PlotDataItem
        """
        super().set_plot_item(plot_item)

        self.update_symbol()

    def add_children_to_root_param(self, params: ptree.Parameter):

        params.addChild(self.symbol_group)
        super().add_children_to_root_param(params)

    def copy_from_config(self, other) -> None:
        """
        Copy configuration from another configuration.
        If a plot item is associated it will be updated

        Args:
            other: configuration to be copy
        """
        super().copy_from_config(other)

        self.symbol_size_parameter.setValue(other.symbol_size_parameter.value())
        if self.plot_item:
            self.update_symbol()


class DiscretePolarAssayColumnVisualizationConfig(
    DiscreteStructuralAssayColumnVisualizationConfig
):
    saverClass = DiscreteStructuralSaver
    DEFAULT_SIZE = 100

    def __init__(self, column: AssayColumn):
        """
        Store visualization configuration for a discrete polar assay column.
        """
        super().__init__(column)


class DiscreteSphericalAssayColumnVisualizationConfig(
    DiscreteStructuralAssayColumnVisualizationConfig
):
    saverClass = DiscreteStructuralSaver

    def __init__(self, column: AssayColumn):
        """
        Store visualization configuration for a discrete spherical assay column.
        Add of stereonets parameters.
        """
        super().__init__(column)
