import numpy as np
import pyqtgraph as pq
from pyqtgraph import mkBrush, mkPen

from openlog.gui.assay_visualization.item_tags import InspectorTag
from openlog.gui.pyqtgraph.ItemSwitcher import ExtendedItemSwitcher


class CustomBarGraphItem(pq.BarGraphItem, InspectorTag):
    def __init__(
        self,
        coordinates=None,
        planned_coordinates=None,
        altitude=None,
        planned_altitude=None,
        planned_eoh=None,
        is_categorical=True,
        text_items=[],
        **opts
    ):
        """
        Override pg.BarGraphItem to add setPen and setBrush methods

        Args:
            **opts:
        """
        pq.BarGraphItem.__init__(self, **opts)
        self.switcher = ExtendedItemSwitcher(
            self,
            coordinates,
            planned_coordinates,
            altitude,
            planned_altitude,
            planned_eoh,
        )
        self.is_categorical = is_categorical
        self.text_items = text_items

    def get_intersection_points(self, inspector):
        """
        Method to returns IntersectedPoint with inspector line.
        Args:
            - inspector : InspectorLine instance
        """

        # no need to duplicates, already created by CategoricalBarGraphItem
        if self.is_categorical:
            return []

        name = "Value"
        if len(self.opts["y0"]) == 0:
            return []
        min_value = self.opts["y0"].min()
        max_value = self.opts["y0"][-1] + self.opts["height"][-1]
        # get bar idx
        diff = inspector.value() - self.opts["y0"]
        idx = np.argmin(np.where(diff < 0, np.inf, diff))
        # altitude mode
        if self.switcher.mode != "length":
            max_value = self.opts["y0"].max()
            min_value = self.opts["y0"][-1] + self.opts["height"][-1]
            idx = idx - 1

        # search in assay values
        intersected_category = str(self.text_items[idx])

        # out of range must be nan
        if inspector.value() > max_value or inspector.value() < min_value:
            intersected_category = float("NaN")

        point = inspector.IntersectedPoint(
            item=self,
            x_value=intersected_category,
            y_value=inspector.value(),
            name=name,
        )
        return [point]

    def setPen(self, *args, **kargs):
        """
        Sets the pen used to draw graph line.
        The argument can be a :class:`QtGui.QPen` or any combination of arguments accepted by
        :func:`pyqtgraph.mkPen() <pyqtgraph.mkPen>`.
        """
        pen = mkPen(*args, **kargs)
        self.setOpts(pen=pen)
        self.picture = None

    def setBrush(self, *args, **kargs):
        """
        Sets the brush used to draw bar rect.
        The argument can be a :class:`QBrush` or argument to :func:`~pyqtgraph.mkBrush`
        """
        brush = mkBrush(*args, **kargs)
        self.setOpts(brush=brush)
        self.picture = None
