# -*- coding: utf-8 -*-
"""
/***************************************************************************
 AIAMAS
                                 A QGIS plugin
 This plugin sytlizes a number of layers for better distinguishability of the map.
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                              -------------------
        begin                : 2023-11-21
        git sha              : $Format:%H$
        copyright            : (C) 2023 by geometalab
        email                : geometalab@ost.ch
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
"""

import os
import os.path
import shutil
from functools import partial
from pathlib import Path
import webbrowser

from PyQt5.QtCore import pyqtSignal
from qgis.PyQt import uic
from qgis.PyQt.QtCore import QSettings, QTranslator, QCoreApplication, QThread
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import QAction, QPushButton, QLineEdit
from qgis.core import QgsSingleSymbolRenderer, QgsProject, QgsWkbTypes, QgsApplication, QgsSettings, Qgis, QgsSvgMarkerSymbolLayer
from qgis.gui import QgsOptionsWidgetFactory, QgsOptionsPageWidget

from .AIAMAS_dialog import AIAMASDialog
from .table_row import TableRow

OPTIONS_WIDGET, OPTIONS_BASE = uic.loadUiType(os.path.join(os.path.dirname(__file__), "ui/settings.ui"))
# LANG_NAME_LIST = ['English', 'German', 'French']
ICON_PATH = os.path.join(os.path.dirname(__file__), 'data/icon.png')


class AIAMASOptionsPage(OPTIONS_WIDGET, QgsOptionsPageWidget):
    apply_signal = pyqtSignal()  # Define a signal
    block = False

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi(self)
        self.setObjectName("AIAMAS")
        self.plugin = None

    def set_plugin(self, plugin):
        self.plugin = plugin
        self.api_key_line_edit.setText(plugin.api_key)
        self.checkBoxLogging.setChecked(plugin.log_enabled)
        self.api_key_line_edit.setPlaceholderText("00000000-0000-0000-0000-000000000000")
        self.api_key_line_edit.focused = False


    def apply(self):
        """
        Applies the new settings
        """
        if self.block:
            self.block = False
        else:
            self.plugin.set_api_key(self.api_key_line_edit.text())
            self.plugin.set_log_enabled(self.checkBoxLogging.isChecked())
            self.apply_signal.emit()  # Emit the signal
            self.block = True


class AIAMASOptionsFactory(QgsOptionsWidgetFactory):
    def __init__(self, plugin):
        super().__init__()
        self.plugin = plugin

    def icon(self):
        return QIcon(ICON_PATH)

    def createWidget(self, parent):
        page = AIAMASOptionsPage(parent)
        page.set_plugin(self.plugin)

        page.apply_signal.connect(self.plugin.handle_settings_changed)  # Connect the signal to the method
        return page


def get_qgis_language():
    return QgsSettings().value('locale/userLocale', 'English')


class AIAMAS:
    """QGIS Plugin Implementation."""

    def __init__(self, iface):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        self.options_factory = None
        self.dlg = None
        self.action = None
        self.layers_to_be_added = []
        self.changed_settings = False
        self.table_rows = []
        settings = QSettings()

        self.api_key = settings.value("/plugins/AIAMAS/api_key", "", str)
        self.log_enabled = settings.value("/plugins/AIAMAS/log_enabled", False, bool)

        # Save reference to the QGIS interface
        self.iface = iface
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        # initialize locale
        locale = str(QSettings().value('locale/userLocale'))[0:2]
        locale_path = os.path.join(
            self.plugin_dir,
            'i18n',
            'AIAMAS_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)
            QCoreApplication.installTranslator(self.translator)

        # Check if plugin was started the first time in current QGIS session
        # Must be set in initGui() to survive plugin reloads
        self.first_start = None

    def handle_layers_addition(self, layers):
        # ensure that the loading process is only done once
        if self.dlg is not None:
            self.dlg.close()
        
        if self.action is not None:
            self.action.setEnabled(True)
    
        QgsApplication.processEvents()
    
        self.layers_to_be_added += layers
    
        if self.action is not None and not self.action.isEnabled():
            self.handle_addition()

    def handle_addition(self):
        if self.action.isEnabled() is False:
            if self.layers_to_be_added:
                if len(self.layers_to_be_added) > 0:
                    new_table_rows = TableRow.create_table_rows_after_loading(self.layers_to_be_added)
                    self.table_rows += new_table_rows
                    if self.dlg:
                        self.dlg.handle_layers_addition(new_table_rows)

        self.layers_to_be_added.clear()

    def set_api_key(self, api_key):
        settings = QgsSettings()
        settings.setValue('/plugins/AIAMAS/api_key', api_key)
        self.api_key = api_key
        self.check_api_key()

    def set_log_enabled(self, log_enabled: bool):
        settings = QgsSettings()
        settings.setValue('/plugins/AIAMAS/log_enabled', log_enabled)
        self.log_enabled = log_enabled

    # noinspection PyMethodMayBeStatic
    def tr(self, message):
        """Get the translation for a string using Qt translation API.

        We implement this ourselves since we do not inherit QObject.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString
        """
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate('AIAMAS', message)

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""

        self.action = QAction(
            QIcon(ICON_PATH),
            self.tr(u'AIAMAS'),
            self.iface.mainWindow(),
        )
        self.action.setEnabled(True)

        # connect to signals for button behavior
        self.action.triggered.connect(self.run)

        # Add toolbar button and menu item
        self.iface.pluginToolBar().addAction(self.action)
        self.iface.pluginMenu().addAction(self.action)

        self.options_factory = AIAMASOptionsFactory(self)
        self.options_factory.setTitle(self.tr('AIAMAS'))
        self.iface.registerOptionsWidgetFactory(self.options_factory)

        self.check_api_key()

        # will be set False in run()
        self.first_start = True

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        self.iface.pluginMenu().removeAction(self.action)
        self.iface.pluginToolBar().removeAction(self.action)
        self.iface.unregisterOptionsWidgetFactory(self.options_factory)

    def check_api_key(self):
        """
        Checks if an API key has been entered, and warns if not.
        """
        if not self.api_key.strip():
            if QCoreApplication.instance().thread() == QThread.currentThread():
                bar = self.iface.messageBar()
                widget = bar.createMessage(self.tr('AIAMAS'), self.tr("No API token entered, please configure API token in AIAMAS settings in the QGIS Options dialog"))
                settings_button = QPushButton("Enter API token…",
                                              pressed=partial(self.open_settings, message_bar_widget=widget))
                layout = widget.layout()
                layout.addWidget(settings_button)
                bar.pushWidget(widget, Qgis.Warning, 7)
            return False
        return True

    def open_settings(self, message_bar_widget=None):
        """
        Opens the settings dialog at the Google Maps page
        """
        self.iface.showOptionsDialog(self.iface.mainWindow(), currentPage='AIAMAS')
        if message_bar_widget:
            self.iface.messageBar().popWidget(message_bar_widget)

    def handle_settings_changed(self):
        self.changed_settings = True
        # Inform the dialog about new settings if it exists.
        # (dlg is None if the plugin is not running yet.)
        if self.action.isEnabled() is False:
            self.settings_changed()

    def settings_changed(self):
        if self.changed_settings and self.action.isEnabled() is False:
            if self.dlg:
                new_table_rows = TableRow.create_table_rows_from_qgis_project()
                self.table_rows = new_table_rows
                self.dlg.settings_changed(new_table_rows)

        self.changed_settings = False

    def handle_name_changes(self):
        TableRow.update_table_rows(self.table_rows)

    def run(self):
        add_cache_folder()
        add_svg_folder()

        # Disable the plugin button
        self.action.setEnabled(False)

        if self.first_start:
            self.action.changed.connect(self.handle_addition)
            self.action.changed.connect(self.settings_changed)
            self.action.changed.connect(self.handle_name_changes)
            QgsProject.instance().legendLayersAdded.connect(self.handle_layers_addition)
            new_table_rows = TableRow.create_table_rows_from_qgis_project()
            self.table_rows = new_table_rows
            self.dlg = AIAMASDialog(new_table_rows)
            self.first_start = False
        # show the dialog
        self.dlg.show()

        # Run the dialog event loop
        result = self.dlg.exec_()

        # See if OK was pressed
        if result:
            layers_to_change = self.dlg.get_checked_rows()
            for l in layers_to_change:
                new_symbol = l.suggested_symbol.clone()
                try:
                    if l.is_default_symbol is True:
                        new_symbol.setSize(2)
                    else:
                        new_symbol.setSize(6)
                except:
                    pass
                renderer = QgsSingleSymbolRenderer(new_symbol)
                l.qgs_layer.setRenderer(renderer)
                l.qgs_layer.triggerRepaint()

            # if self.dlg.sortCheckBox.isChecked():
            # self.sort_layers_by_geom()

        self.action.setEnabled(True)

    def sort_layers_by_geom(self):
        # Get the root of the layer tree
        root = QgsProject.instance().layerTreeRoot()

        # Get the default layer order
        order = root.layerOrder()

        # Separate layers by geometry type
        point_list = []
        line_list = []
        poly_list = []
        no_geom_list = []
        rest_list = []

        for layer in order:
            try:
                geom_type = layer.geometryType()
                if geom_type is Qgis.GeometryType.PointGeometry:
                    point_list.append(layer)
                elif geom_type is Qgis.GeometryType.LineGeometry:
                    line_list.append(layer)
                elif geom_type is Qgis.GeometryType.PolygonGeometry:
                    poly_list.append(layer)
                elif geom_type is Qgis.GeometryType.NullGeometry:
                    no_geom_list.append(layer)
                else:
                    rest_list.append(layer)
            except Exception as e:
                rest_list.append(layer)

        # Combine the lists in the order: point, line, polygon, raster
        sorted_order = point_list + line_list + poly_list + no_geom_list + rest_list


def add_svg_folder():
    surce = Path(os.path.dirname(os.path.abspath(__file__))) / "data/svgs"
    destination = Path(QgsApplication.qgisSettingsDirPath()) / "svg"

    if not os.path.isdir(destination):
        os.makedirs(destination)

    for dir in os.listdir(surce):
        if not os.path.isdir(destination / dir):
            shutil.copytree(surce / dir, destination / dir)


def add_cache_folder():
    destination = Path(QgsApplication.qgisSettingsDirPath()) / "aiamas_cache"

    if not os.path.isdir(destination):
        os.makedirs(destination)
