from typing import Sequence

import numpy
from ImageD11.grain import grain as Grain
from silx.gui import qt
from silx.gui.plot import Plot1D

from .common.utils import NoWheelSpinBox

_BINS_FOR_HISTOGRAM = 30
_HISTOGRAM_LEGEND = "histogram"


class GrainStatsPlot(qt.QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        layout = qt.QVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)

        self._plot = Plot1D(self)
        self._plot.setGraphXLabel("Number of peaks")
        self._plot.setGraphYLabel("Counts")
        layout.addWidget(self._plot)

        # Histogram controls
        controlsLayout = qt.QHBoxLayout()
        controlsLayout.addSpacing(10)
        controlsLayout.setSpacing(10)
        controlsLayout.addWidget(qt.QLabel("<b>Number of bins:</b>"))
        self._binsSpinBox = NoWheelSpinBox(self)
        self._binsSpinBox.setMinimum(2)
        self._binsSpinBox.setValue(_BINS_FOR_HISTOGRAM)
        self._binsSpinBox.valueChanged.connect(self._updateBins)
        controlsLayout.addWidget(self._binsSpinBox)
        self._warningText = qt.QLabel()
        self._warningText.setStyleSheet("color: #805200")
        controlsLayout.addWidget(self._warningText)
        controlsLayout.addStretch()

        layout.addLayout(controlsLayout)

        self._numberOfPeaksPerGrain: list[float] | None = None

    def plotStats(self, grains: Sequence[Grain]):
        self._numberOfPeaksPerGrain = [float(grain.npks) for grain in grains]
        self._updateHistogram()

    def _updateBins(self, bins: int):
        if not self._numberOfPeaksPerGrain:
            return
        if bins > len(self._numberOfPeaksPerGrain):
            self._warningText.setText(
                "⚠️ Number of bins is higher than number of grains"
            )
        else:
            self._warningText.setText("")
        self._updateHistogram()

    def _updateHistogram(self):
        if not self._numberOfPeaksPerGrain:
            return
        counts, binEdges = numpy.histogram(
            self._numberOfPeaksPerGrain, bins=self._binsSpinBox.value()
        )
        self._plot.addHistogram(
            counts, binEdges, fill=True, align="left", legend=_HISTOGRAM_LEGEND
        )
        self._plot.resetZoom()
