# -*- coding: utf-8 -*-
"""
search_download_s2Dialog — Vietnam administrative boundary search dialog.
"""

import os

from qgis.PyQt import uic
from qgis.PyQt.QtCore import QDate, pyqtSignal
from qgis.PyQt.QtWidgets import QDialog, QDialogButtonBox, QMessageBox

from .services.administrative_service import (
    get_communes_by_province,
    get_provinces,
)
from .services.boundary_loader import BoundaryLoadWorker
from .ui.dialog_theme import apply_dialog_theme
from .ui.widgets import make_date_picker_only, make_searchable_combo

FORM_CLASS, _ = uic.loadUiType(os.path.join(
    os.path.dirname(__file__), 'Search_Download_S2_dialog_base.ui'))


class search_download_s2Dialog(QDialog, FORM_CLASS):
    preview_requested = pyqtSignal()

    def __init__(self, parent=None):
        super(search_download_s2Dialog, self).__init__(parent)
        self.setupUi(self)
        apply_dialog_theme(self)

        self._boundaries_ready = False
        self._loader = None

        self.time1.setDate(QDate.currentDate())
        self.time0.setDate(QDate.currentDate().addDays(-15))
        self.spin_cloud_threshold.setValue(20)

        make_date_picker_only(self.time0)
        make_date_picker_only(self.time1)

        make_searchable_combo(
            self.slt_province,
            u'Search province / Tìm tỉnh, thành phố',
        )
        # An empty commune box means the whole province, so the placeholder is
        # what tells the user that leaving it alone is a valid choice.
        make_searchable_combo(
            self.slt_commune,
            u'Whole province / Toàn tỉnh',
        )

        self._ok_button = self.button_box.button(QDialogButtonBox.StandardButton.Ok)
        self.slt_province.setEnabled(False)
        self.slt_commune.setEnabled(False)
        self.btn_preview.clicked.connect(self.preview_requested.emit)

        self.progress_boundary.setRange(0, 100)
        self.progress_boundary.setValue(0)
        self._set_loading_state(
            True,
            u'Loading administrative boundaries... / Đang tải ranh giới hành chính...',
        )

        self.slt_province.currentIndexChanged.connect(self._on_province_changed)
        self.time0.dateChanged.connect(self._update_validation)
        self.time1.dateChanged.connect(self._update_validation)
        self._update_validation()
        self._start_boundary_loader()

    def _set_loading_state(self, loading, message=''):
        self.progress_boundary.setVisible(loading)
        if message:
            self.loadStatusLabel.setText(message)

    def _start_boundary_loader(self):
        self._loader = BoundaryLoadWorker(self)
        self._loader.progress_changed.connect(self._on_load_progress)
        self._loader.load_finished.connect(self._on_load_finished)
        self._loader.start()

    def _on_load_progress(self, value, message):
        self.progress_boundary.setValue(value)
        if message:
            self.loadStatusLabel.setText(message)

    def _on_load_finished(self, success, error_message):
        self._set_loading_state(False)
        if not success:
            QMessageBox.critical(
                self,
                u'Boundary load error / Lỗi tải ranh giới',
                error_message
                or u'Could not read boundary data. / Không thể đọc dữ liệu ranh giới.',
            )
            self.reject()
            return

        self._boundaries_ready = True
        self._populate_provinces()
        self.slt_province.setEnabled(True)
        self.slt_province.setFocus()
        self.loadStatusLabel.setVisible(False)
        self._update_validation()

    def _populate_provinces(self):
        self.slt_province.blockSignals(True)
        self.slt_province.clear()
        for province in get_provinces():
            self.slt_province.addItem(province['tenTinh'], province['maTinh'])
        # Nothing is picked for the user: the area has to be a deliberate choice,
        # so the buttons stay disabled until a province is selected.
        self.slt_province.setCurrentIndex(-1)
        self.slt_province.setEditText(u'')
        self.slt_province.blockSignals(False)
        self._populate_communes()

    def _on_province_changed(self):
        self._populate_communes()
        self._update_validation()
        if self.slt_commune.isEnabled():
            # The province is settled, so the user can go straight on to typing
            # a commune name.
            self.slt_commune.setFocus()

    def _populate_communes(self):
        self.slt_commune.blockSignals(True)
        self.slt_commune.clear()
        province_index = self.slt_province.currentIndex()
        if province_index >= 0:
            ma_tinh = self.slt_province.itemData(province_index)
            for commune in get_communes_by_province(ma_tinh):
                self.slt_commune.addItem(commune['tenXa'], commune['maXa'])
            # Nothing selected: an empty box is how the whole province is asked
            # for, so there is no entry standing for it in the list.
            self.slt_commune.setCurrentIndex(-1)
            self.slt_commune.setEditText(u'')
        self.slt_commune.blockSignals(False)
        self.slt_commune.setEnabled(province_index >= 0)

    def is_ready(self):
        """Whether the dialog has everything it needs to run."""
        return (self._boundaries_ready
                and self.slt_province.currentIndex() >= 0
                and self.time0.date() <= self.time1.date())

    def validation_message(self):
        """A problem worth spelling out, empty when there is none."""
        if self._boundaries_ready and self.time0.date() > self.time1.date():
            return u'The end date is before the start date / ' \
                   u'Ngày kết thúc trước ngày bắt đầu'
        return u''

    def _update_validation(self):
        message = self.validation_message()
        self.validationLabel.setText(message)
        self.validationLabel.setVisible(bool(message))
        ready = self.is_ready()
        self._ok_button.setEnabled(ready)
        self.btn_preview.setEnabled(ready)

    def cloud_threshold(self):
        return self.spin_cloud_threshold.value()

    def set_date_range(self, start_date, end_date):
        self.time0.setDate(start_date)
        self.time1.setDate(end_date)

    def is_boundaries_ready(self):
        return self._boundaries_ready

    def closeEvent(self, event):
        if self._loader is not None and self._loader.isRunning():
            self._loader.requestInterruption()
            self._loader.wait(3000)
        super(search_download_s2Dialog, self).closeEvent(event)
