import os
import sys

from qgis.core import QgsApplication
from qgis.PyQt import QtCore, QtGui, uic
from qgis.PyQt.QtGui import QColor, QIcon
from qgis.PyQt.QtWidgets import (
    QAbstractItemView,
    QDoubleSpinBox,
    QHeaderView,
    QStyledItemDelegate,
    QStyleOptionViewItem,
    QWidget,
)
from xplordb.datamodel.collar import Collar
from xplordb.datamodel.survey import Survey

from openlog.gui.survey_creation.survey_creation_model import SurveyCreationLayerModel


class NoValueItemDelegate(QStyledItemDelegate):
    def __init__(self, parent) -> None:
        """
        QStyledItemDelegate to display rect if no value dfine

        Args:
            parent:
        """
        super().__init__(parent)

    def paint(
        self,
        painter: QtGui.QPainter,
        option: QStyleOptionViewItem,
        index: QtCore.QModelIndex,
    ) -> None:
        if index.model().data(index, QtCore.Qt.DisplayRole) is None:
            painter.save()
            pen = painter.pen()
            pen.setColor(QColor("red"))
            pen.setWidth(2)
            painter.setPen(pen)
            painter.drawRect(option.rect)
            painter.restore()

        super().paint(painter, option, index)


class DipItemDelegate(NoValueItemDelegate):
    def __init__(self, parent) -> None:
        """
        QStyledItemDelegate for dip definition

        Args:
            parent:
        """
        super().__init__(parent)

    def createEditor(self, parent, option, index) -> QWidget:
        """
        Create a QDoubleSpinBox for dip definition

        Args:
            parent: QWidget
            option: QStyleOptionViewItem
            index: QModelIndex

        Returns: QDoubleSpinBox

        """
        editor = QDoubleSpinBox(parent)
        editor.setMaximum(180)
        editor.setMinimum(-180)
        return editor


class AzimuthItemDelegate(NoValueItemDelegate):
    def __init__(self, parent) -> None:
        """
        QStyledItemDelegate for azimuth definition

        Args:
            parent:
        """
        super().__init__(parent)

    def createEditor(self, parent, option, index) -> QWidget:
        """
        Create a QDoubleSpinBox for azimuth definition

        Args:
            parent: QWidget
            option: QStyleOptionViewItem
            index: QModelIndex

        Returns: QDoubleSpinBox

        """
        editor = QDoubleSpinBox(parent)
        editor.setMaximum(360.0)
        editor.setMinimum(0.0)
        return editor


class DepthItemDelegate(NoValueItemDelegate):
    def __init__(self, parent, read_only: bool = False) -> None:
        """
        QStyledItemDelegate for depth definition

        Args:
            parent:
        """
        super().__init__(parent)
        self.read_only = read_only

    def createEditor(self, parent, option, index) -> QWidget:
        """
        Create a QDoubleSpinBox for depth definition

        Args:
            parent: QWidget
            option: QStyleOptionViewItem
            index: QModelIndex

        Returns: QDoubleSpinBox

        """
        editor = QDoubleSpinBox(parent)
        editor.setMaximum(sys.float_info.max)
        editor.setMinimum(0.0)
        if self.read_only:
            editor.setReadOnly(True)
            editor.setDisabled(True)

        return editor


class SurveyCreationWidget(QWidget):
    def __init__(self, parent=None) -> None:
        """
        QWidget to display survey for creation.

        Add the multi-selection option

        Use SurveyCreationLayerModel for table definition

        Args:
            parent: QWidget parent
        """
        super().__init__(parent)

        uic.loadUi(
            os.path.dirname(os.path.realpath(__file__)) + "/survey_creation_widget.ui",
            self,
        )

        self._model = SurveyCreationLayerModel(self)
        self.survey_table_view.setModel(self._model)

        self.survey_table_view.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch
        )
        self.survey_table_view.setItemDelegateForColumn(
            self._model.AZIMUTH_COL, AzimuthItemDelegate(self)
        )
        self.survey_table_view.setItemDelegateForColumn(
            self._model.DIP_COL, DipItemDelegate(self)
        )
        self.survey_table_view.setItemDelegateForColumn(
            self._model.DEPTH_COL, DepthItemDelegate(self)
        )

        self.add_survey_button.setIcon(QIcon(QgsApplication.iconPath("mActionAdd.svg")))
        self.add_survey_button.clicked.connect(self._model.add_survey)

        self.remove_survey_button.setIcon(
            QIcon(QgsApplication.iconPath("mActionRemove.svg"))
        )
        self.remove_survey_button.clicked.connect(lambda clicked: self._remove_survey())

        self.survey_table_view.setSelectionMode(QAbstractItemView.ExtendedSelection)

        # planned
        self._model_planned = SurveyCreationLayerModel(self)
        self._model_planned.setHorizontalHeaderLabels(["EOH", "Dip", "Azimuth"])
        self.survey_table_view_planned.setModel(self._model_planned)
        self.survey_table_view_planned.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch
        )

        self.survey_table_view_planned.setItemDelegateForColumn(
            self._model_planned.AZIMUTH_COL, AzimuthItemDelegate(self)
        )
        self.survey_table_view_planned.setItemDelegateForColumn(
            self._model_planned.DIP_COL, DipItemDelegate(self)
        )
        self.survey_table_view_planned.setItemDelegateForColumn(
            self._model_planned.DEPTH_COL, DepthItemDelegate(self, read_only=False)
        )
        self.survey_table_view_planned.hideColumn(self._model_planned.DEPTH_COL)

        self.add_planned_survey_button.setIcon(
            QIcon(QgsApplication.iconPath("mActionAdd.svg"))
        )
        self.add_planned_survey_button.clicked.connect(self._add_planned_row)

        self.remove_planned_survey_button.setIcon(
            QIcon(QgsApplication.iconPath("mActionRemove.svg"))
        )
        self.remove_planned_survey_button.clicked.connect(
            lambda clicked: self._remove_planned_survey()
        )

    def add_surveys(self, surveys: [Survey]) -> None:
        """
        Add surveys in survey table

        Args:
            surveys: survey list
        """
        for survey in surveys:
            self._model.add_survey(survey)

    def add_planned_surveys(self, surveys: [Survey], collar: Collar = None) -> None:
        """
        Add planned surveys in planned survey table

        Args:
            surveys: survey list
        """
        for survey in surveys:
            self._model_planned.add_survey(survey, collar)

    def get_survey_list(self) -> [Survey]:
        """
        Get survey list from SurveyCreationLayerModel

        Returns: survey list defined in SurveyCreationLayerModel (warning no person and dataset are defined)

        """
        return self._model.get_survey_list()

    def get_planned_survey_list(self) -> [Survey]:
        """
        Get planned survey list from SurveyCreationLayerModel

        Returns: survey list defined in SurveyCreationLayerModel (warning no person and dataset are defined)

        """
        return self._model_planned.get_survey_list()

    def _add_planned_row(self):
        self._model_planned.add_survey()

        if self._model_planned.rowCount() == 1:
            self.add_planned_survey_button.setEnabled(False)

    def _remove_survey(self) -> None:
        """
        Remove selected survey from survey table

        """

        while self.survey_table_view.selectionModel().selectedIndexes():
            self._model.removeRow(
                self.survey_table_view.selectionModel().selectedIndexes()[0].row()
            )

    def _remove_planned_survey(self) -> None:
        """
        Remove selected survey from survey table

        """

        while self.survey_table_view_planned.selectionModel().selectedIndexes():
            self._model_planned.removeRow(
                self.survey_table_view_planned.selectionModel()
                .selectedIndexes()[0]
                .row()
            )

        if self._model_planned.rowCount() < 1:
            self.add_planned_survey_button.setEnabled(True)
