import numpy as np
import pyqtgraph as pg
from qgis.PyQt.QtCore import QRectF, Qt
from qgis.PyQt.QtGui import QFont, QPainter, QPicture

from openlog.gui.pyqtgraph.ItemSwitcher import ItemSwitcher


class TechLogSwitcher(ItemSwitcher):
    def __init__(
        self,
        item,
        coordinates: np.ndarray,
        planned_coordinates: np.ndarray,
        altitude: np.ndarray = None,
        planned_altitude: np.ndarray = None,
        planned_eoh=None,
    ) -> None:
        super().__init__(item, coordinates, planned_coordinates, planned_eoh)
        # TODO : for now item is considered empty to avoid any error with switch
        self.is_empty = True


class TechLogGraphicItem(pg.GraphicsObject):
    def __init__(self, data, pen):
        pg.GraphicsObject.__init__(self)

        # TODO : for now no information about coordinated and planned coordinates are used
        self.switcher = TechLogSwitcher(
            self,
            coordinates=None,
            planned_coordinates=None,
            planned_eoh=None,
        )

        self.data = data
        if pen:
            self.pen = pen
        else:
            self.pen = pg.mkPen("#000000")
        self.generatePicture()

    def generatePicture(self):
        self.picture = QPicture()
        p = QPainter(self.picture)
        p.setPen(self.pen)

        # On trie les données par colonnes
        num = 0
        max_to = None
        column_data = {}
        for row in sorted(self.data, key=lambda d: float(d["diameter"]), reverse=True):
            if row["depth_from"] != row["depth_to"]:
                if not max_to or row["depth_from"] < max_to:
                    num += 1
                    column_data[str(num)] = []
                column_data[str(num)].append(row)
                max_to = row["depth_to"]

        # On affiche les colonnes
        for id in column_data:
            for item in sorted(column_data[id], key=lambda d: float(d["depth_from"])):
                p.drawRect(
                    QRectF(
                        (int(id) - 1) * 10,
                        float(item["depth_from"]) * 1000,
                        10,
                        float(item["depth_to"]) * 1000
                        - float(item["depth_from"]) * 1000,
                    )
                )
                p.save()
                p.setFont(QFont("Calibri", 2))
                p.rotate(-90)
                if self.getViewBox():
                    sc = self.getViewBox().getAspectRatio()
                    p.scale(sc, 1)
                    rect = QRectF(
                        -float(item["depth_to"]) * 1000 / sc,
                        (int(id) - 1) * 10,
                        (
                            float(item["depth_to"]) * 1000
                            - float(item["depth_from"]) * 1000
                        )
                        / sc,
                        10,
                    )
                    p.drawText(
                        rect, Qt.AlignCenter | Qt.TextWordWrap, self.getLabel(item)
                    )
                p.restore()

        # On affiche les informations ponctuelles (accessoires)
        ponctual_data = [
            row for row in self.data if row["depth_from"] == row["depth_to"]
        ]
        p.save()
        if self.getViewBox():
            sc = self.getViewBox().getAspectRatio()
            p.scale(1, sc)
        else:
            sc = 1
        for item in ponctual_data:
            rect = QRectF(
                len(column_data.keys()) * 10,
                item["depth_from"] * 1000 / sc - 5,
                20,
                10,
            )
            # On dessine le rectangle invisible pour que le calcul du viewrange soit correct
            p.setPen(pg.mkPen(None))
            p.drawRect(rect)

            p.setPen(self.pen)
            p.setFont(QFont("Calibri", 2))
            p.drawText(rect, Qt.AlignVCenter | Qt.TextWordWrap, self.getLabel(item))
        p.restore()
        p.end()

    def paint(self, p, *args):
        self.generatePicture()
        p.drawPicture(0, 0, self.picture)

    def boundingRect(self):
        return QRectF(self.picture.boundingRect())

    def getLabel(self, item):
        return f"{item}"


class ForageItem(TechLogGraphicItem):
    def __init__(self, data):
        super().__init__(data, pg.mkPen("#0070c0"))

    def getLabel(self, item):
        return f"{item['type']} ({item['tool']} {item['diameter']} mm - {item['fluid']} + {item['additive']})"


class TubageItem(TechLogGraphicItem):
    def __init__(self, data):
        super().__init__(data, pg.mkPen("#c00000"))

    def getLabel(self, item):
        return f"{item['type']} ({item['material']} {item['diameter']} mm)"


class RemplissageItem(TechLogGraphicItem):
    def __init__(self, data):
        super().__init__(data, pg.mkPen("#548235"))

    def getLabel(self, item):
        return f"{item['material']} ({item['diameter']} mm)"


class AccessoireItem(TechLogGraphicItem):
    def __init__(self, data):
        super().__init__(data, pg.mkPen("#44546a"))

    def getLabel(self, item):
        if item["depth_from"] != item["depth_to"]:
            return f"{item['type']} ({item['diameter']} mm)"
        else:
            return f"{item['type']}"
