import pyqtgraph as pg
from qgis.PyQt.QtGui import QColor

from openlog.gui.assay_visualization.config.config_saver import ConfigSaver
from openlog.gui.assay_visualization.config.config_saver_utils import (
    deserialize_pen_param,
    serialize_pen_param,
)


class DiscreteNumericalSaver(ConfigSaver):
    def _serialize(
        self, config, serialize_metadata=True, serialize_extended=True
    ) -> dict:

        if serialize_metadata:
            d = super()._serialize(config)
        else:
            d = {}

        # line symbology
        discrete_dict = {}
        discrete_dict |= serialize_pen_param(config, "pen_params", "line")

        # point symbology
        discrete_dict["point_display"] = config.symbol_group.value()
        discrete_dict["point_symbol"] = config.symbol_parameter.value()
        discrete_dict["point_size"] = config.symbol_size_parameter.value()
        qcolor = config.symbol_color_parameter.value()
        discrete_dict["point_color"] = qcolor.name()

        # color ramp
        discrete_dict["line_shading"] = config.color_ramp_handler.get_parameters()
        discrete_dict["line_shading_enable"] = config.color_ramp_group.value()

        # area shading
        discrete_dict["area_shading"] = None
        discrete_dict["area_shading_enable"] = None
        if config.fill_curve_handler:
            discrete_dict["area_shading"] = config.fill_curve_handler.get_parameters()
            discrete_dict["area_shading_enable"] = config.fill_curve_param.value()

        d["discrete_config"] = discrete_dict
        # extended config if exists
        d["extended_config"] = None

        if config.extended_config is not None and serialize_extended:
            d["extended_config"] = (
                config.extended_config.saverClass()
                ._serialize(config.extended_config, False, False)
                .get("extended_config")
            )

        return d

    def _deserialize(self, config, dict: dict, deserialize_extended=True) -> None:

        discrete_dict = dict.get("discrete_config")
        deserialize_pen_param(config, discrete_dict, "pen_params", "line")
        # apply changes
        config._pen_updated()

        # points
        config.symbol_parameter.setValue(discrete_dict.get("point_symbol"))
        config.symbol_size_parameter.setValue(discrete_dict.get("point_size"))
        qcolor = QColor()
        qcolor.setNamedColor(discrete_dict.get("point_color"))
        config.symbol_color_parameter.setValue(qcolor)
        config.symbol_group.setValue(discrete_dict.get("point_display"))

        # color ramp
        config.color_ramp_handler.set_parameters(discrete_dict.get("line_shading"))
        config.color_ramp_group.setValue(discrete_dict.get("line_shading_enable"))

        # area shading
        if config.fill_curve_handler and discrete_dict.get("area_shading") is not None:
            config.fill_curve_handler.set_parameters(discrete_dict.get("area_shading"))
            config.fill_curve_param.setValue(discrete_dict.get("area_shading_enable"))

        # extended config if exists
        if (
            config.extended_config is not None
            and dict.get("extended_config") is not None
            and deserialize_extended
        ):
            config.extended_config.saverClass()._deserialize(
                config.extended_config, dict, False
            )


class ExtendedNumericalSaver(ConfigSaver):
    def _serialize(
        self, config, serialize_metadata=True, serialize_discrete=True
    ) -> dict:

        if serialize_metadata:
            d = super()._serialize(config)
        else:
            d = {}
        extended_dict = {}
        # bar pen
        extended_dict |= serialize_pen_param(config, "pen_params", "bar_pen")
        # bar fill
        extended_dict["bar_fill_color"] = config.bar_color_param.value().name()
        # color ramp
        extended_dict["bar_shading"] = config.color_ramp_handler.get_parameters()
        extended_dict["bar_shading_enable"] = config.color_ramp_group.value()

        # data binning
        extended_dict["is_aggregated"] = None
        if config.color_ramp_handler.is_binner_enabled:
            extended_dict[
                "is_aggregated"
            ] = config.color_ramp_handler.binning_param.value()

        d["extended_config"] = extended_dict
        # discrete config if exists
        d["discrete_config"] = None
        if config.discrete_configuration is not None and serialize_discrete:
            d["discrete_config"] = (
                config.discrete_configuration.saverClass()
                ._serialize(config.discrete_configuration, False, False)
                .get("discrete_config")
            )

        return d

    def _deserialize(self, config, dict: dict, deserialize_discrete=True) -> None:

        extended_dict = dict.get("extended_config")
        deserialize_pen_param(config, extended_dict, "pen_params", "bar_pen")
        # apply changes
        config._pen_updated()
        # bar fill
        qcolor = QColor()
        qcolor.setNamedColor(extended_dict.get("bar_fill_color"))
        config.bar_color_param.setValue(qcolor)
        # color ramp
        config.color_ramp_handler.set_parameters(extended_dict.get("bar_shading"))
        config.color_ramp_group.setValue(extended_dict.get("bar_shading_enable"))

        # data binning
        if (
            config.color_ramp_handler.is_binner_enabled
            and extended_dict.get("is_aggregated") is not None
        ):
            config.color_ramp_handler.binning_param.setValue(
                extended_dict.get("is_aggregated")
            )

        # discrete config if exists
        if (
            config.discrete_configuration is not None
            and dict.get("discrete_config") is not None
            and deserialize_discrete
        ):
            config.discrete_configuration.saverClass()._deserialize(
                config.discrete_configuration, dict, False
            )
