import os
from datetime import datetime, timedelta, timezone

from qgis.PyQt import QtCore, uic
from qgis.PyQt.QtWidgets import QCompleter, QWidget


class DatetimeFormatSelectionWidget(QWidget):
    DATE_FORMAT_LIST = ["auto", "%Y-%m-%d", "%d-%m-%Y", "%Y/%m/%d", "%d/%m/%Y"]
    TIME_FORMAT_LIST = ["", "%Hh%Mm%Ss"]

    def __init__(self, parent=None) -> None:
        """
        Widget to define date and time format

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

        # translation

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

        # case sensitive for auto completion (date format)
        completer = QCompleter()
        completer.setCaseSensitivity(QtCore.Qt.CaseSensitivity.CaseSensitive)

        for date_format in self.DATE_FORMAT_LIST:
            self.date_format_cb.addItem(date_format)
        self.date_format_cb.setEditable(True)
        self.date_format_cb.setCompleter(completer)
        self.date_format_cb.currentTextChanged.connect(self._update_preview)
        self.date_format_cb.currentTextChanged.connect(
            lambda text: self.format_changed.emit()
        )

        for time_format in self.TIME_FORMAT_LIST:
            self.time_format_cb.addItem(time_format)
        self.time_format_cb.setEditable(True)
        self.time_format_cb.currentTextChanged.connect(self._update_preview)
        self.time_format_cb.currentTextChanged.connect(
            lambda text: self.format_changed.emit()
        )

        self.spaceseparator_checkbox.clicked.connect(self._update_preview)
        self.spaceseparator_checkbox.clicked.connect(
            lambda clicked: self.format_changed.emit()
        )

        self.tz_spinbox.valueChanged.connect(self._update_preview)
        self.tz_spinbox.valueChanged.connect(lambda clicked: self.format_changed.emit())

        self._update_preview()

    # Signal emitted when format is changed.
    format_changed = QtCore.pyqtSignal()

    def get_date_format(self) -> str:
        """
        Get date format selected

        Returns: (str) selected date format

        """
        return self.date_format_cb.currentText()

    def set_date_format(self, date_format: str) -> None:
        """
        Define date format : if date format not in list date format is added

        Args:
            date_format: wanted date format
        """
        index = self.date_format_cb.findText(date_format)
        if index == -1:
            self.date_format_cb.addItem(date_format)
            index = self.date_format_cb.count()
        self.date_format_cb.setCurrentIndex(index)

    def get_time_format(self) -> str:
        """
        Get time format selected

        Returns: (str) selected time format

        """
        return self.time_format_cb.currentText()

    def get_time_offset(self) -> float:
        """
        Get time offset selected

        Returns: (float) time offset

        """
        return self.tz_spinbox.value()

    def set_time_format(self, time_format: str) -> None:
        """
        Define time format : if time format not in list time format is added

        Args:
            time_format: wanted time format
        """
        index = self.time_format_cb.findText(time_format)
        if index == -1:
            self.time_format_cb.addItem(time_format)
            index = self.time_format_cb.count()
        self.time_format_cb.setCurrentIndex(index)

    def get_datetime_format(self) -> str:
        """
        Get full datetime format with date and time formats.

        Returns: (str) full datetime format

        """
        dateformat = self.date_format_cb.currentText()
        timeformat = self.time_format_cb.currentText()
        space = " " if self.spaceseparator_checkbox.isChecked() else ""
        return f"{dateformat}{space}{timeformat}"

    def _update_preview(self) -> None:
        """
        Update preview with current datetime

        """
        tz = timezone(timedelta(hours=self.tz_spinbox.value()))
        now = datetime.now(tz=tz)
        _format = self.get_datetime_format()
        if _format == "auto":
            res = ""
        else:
            res = now.strftime(_format + " UTC(%z)")
        self.preview_line_edit.setText(res)

    def get_parameters(self) -> dict:
        """
        Return widget parameters in a dictionnary.
        """
        res = {}
        res["date_format"] = self.date_format_cb.currentText()
        res["date_separator"] = self.spaceseparator_checkbox.isChecked()
        res["time_format"] = self.time_format_cb.currentText()
        res["time_zone"] = self.tz_spinbox.value()
        return res

    def set_parameters(self, params: dict) -> None:
        """
        Set parameters stored in a dictionnary.
        """
        self.date_format_cb.setCurrentText(params.get("date_format"))
        self.spaceseparator_checkbox.setChecked(params.get("date_separator"))
        self.time_format_cb.setCurrentText(params.get("time_format"))
        self.tz_spinbox.setValue(params.get("time_zone"))
