#! python3  # noqa: E265

"""
/***************************************************************************
 FoliosWizard
                                 A QGIS plugin
 Folios wizard
                              -------------------
        begin                : 2023-08-20
        git sha              : $Format:%H$
        copyright            : (C) 2023 by Jean-Marie ARSAC
        email                : jmarsac@azimut.fr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 tempfile

# standard
from functools import partial
from pathlib import Path

# PyQGIS
from qgis.core import (
    Qgis,
    QgsApplication,
    QgsExpressionContextUtils,
    QgsFeature,
    QgsLayoutExporter,
    QgsLayoutItemMap,
    QgsProject,
    QgsSettings,
    edit,
)
from qgis.gui import QgisInterface
from qgis.PyQt import QtWidgets
from qgis.PyQt.QtCore import QCoreApplication, QDir, QLocale, Qt, QTranslator, QUrl
from qgis.PyQt.QtGui import QDesktopServices, QIcon
from qgis.PyQt.QtWidgets import QAction, QProgressBar

# project
from .__about__ import DIR_PLUGIN_ROOT, __icon_path__, __title__, __uri_homepage__
from .folio_geometry import FolioGeometry
from .folio_map_tool import FolioMapTool
from .gui.dlg_about import DlgAbout
from .gui.dlg_folios_wizard import DlgFoliosWizard
from .gui.dlg_settings import PlgOptionsFactory
from .gui.splash.read_show_metadata import (
    clear_project_metadata_variables,
    read_show_metadata,
)
from .layout import Layout
from .qt_utils import tr
from .toolbelt import PlgLogger
from .toolbelt.preferences import PlgOptionsManager
from .utils import Utils

# ############################################################################
# ########## Classes ###############
# ##################################


class FoliosWizardPlugin:
    def __init__(self, iface: QgisInterface):
        """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
        """
        # user login
        self._login = os.getlogin()

        self.iface = iface
        self.log = PlgLogger().log
        self._settings = PlgOptionsManager.get_plg_settings()
        # default settings
        if self._settings.maps_templates_folder == "":
            profile_dir = QgsApplication.qgisSettingsDirPath()
            templates_dir = os.path.join(profile_dir, "composer_templates")
            self._settings.maps_templates_folder = templates_dir
            PlgOptionsManager.save_from_object(self._settings)
        if self._settings.maps_output_folder == "":
            self._settings.maps_output_folder = tempfile.gettempdir()
            PlgOptionsManager.save_from_object(self._settings)

        # translation
        # initialize the locale
        self.locale: str = QgsSettings().value("locale/userLocale", QLocale().name())[
            0:2
        ]
        locale_path: Path = (
            DIR_PLUGIN_ROOT / f"resources/i18n/{__title__.lower()}_{self.locale}.qm"
        )
        self.log(message=f"Translation: {self.locale}, {locale_path}", log_level=4)
        if locale_path.exists():
            self.translator = QTranslator()
            self.translator.load(str(locale_path.resolve()))
            QCoreApplication.installTranslator(self.translator)
        self.dlg = DlgFoliosWizard()
        self.point_tool = None

        # scale setting
        self._print_scale = 1

        # map format setting
        self._map_format = "PDF"

        # Layouts
        self._layout = Layout()
        self._layout.loadTemplates(self.dlg.comboBoxLayout)

        # geo PDF ?
        self.create_geo_pdf = False

        # index map ?
        self.create_always_index_map = False

        self.apply_layout_changes_to_existing_folios = False

        self._excluded_layers_names = ["Folios"]

    def initGui(self):
        """Set up plugin UI elements."""

        # settings page within the QGIS preferences menu
        self.options_factory = PlgOptionsFactory()
        self.iface.registerOptionsWidgetFactory(self.options_factory)

        self.toolbar = self.iface.addToolBar(__title__)
        self.toolbar.setObjectName(__title__)

        # -- Actions
        self.actions = []
        icon = QIcon(os.path.join(DIR_PLUGIN_ROOT, "icon.png"))
        self.action_folios_wizard = QAction(
            icon,
            tr("Folios wizard"),
            self.iface.mainWindow(),
        )
        self.actions.append(self.action_folios_wizard)
        self.action_folios_wizard.triggered.connect(self.run)
        self.toolbar.addAction(self.action_folios_wizard)

        self.action_help = QAction(
            QgsApplication.getThemeIcon("mActionHelpContents.svg"),
            tr("Help"),
            self.iface.mainWindow(),
        )
        self.actions.append(self.action_help)
        self.action_help.triggered.connect(
            partial(QDesktopServices.openUrl, QUrl(__uri_homepage__))
        )

        self.action_settings = QAction(
            QgsApplication.getThemeIcon("mIconProperties.svg"),
            tr("Settings"),
            self.iface.mainWindow(),
        )
        self.actions.append(self.action_settings)
        self.action_settings.triggered.connect(
            lambda: self.iface.showOptionsDialog(
                currentPage="mOptionsPage{}".format(__title__)
            )
        )

        self.action_about = QAction(
            QgsApplication.getThemeIcon("mIconInfo.svg"),
            tr("About"),
            self.iface.mainWindow(),
        )
        self.actions.append(self.action_about)
        self.action_about.triggered.connect(self.run_about)

        self.action_show_metadata = QAction(
            QIcon(":/images/themes/default/mIconListView.svg"),
            tr("Show project details"),
            self.iface.mainWindow(),
        )
        self.actions.append(self.action_show_metadata)
        self.action_show_metadata.triggered.connect(self.show_metadata)

        # -- Menu
        self.iface.addPluginToMenu(__title__, self.action_folios_wizard)
        self.iface.addPluginToMenu(__title__, self.action_settings)
        self.iface.addPluginToMenu(__title__, self.action_help)
        self.iface.addPluginToMenu(__title__, self.action_about)
        self.iface.addPluginToMenu(__title__, self.action_show_metadata)

        # -- Help menu

        # documentation
        self.iface.pluginHelpMenu().addSeparator()
        self.action_help_plugin_menu_documentation = QAction(
            QIcon(str(__icon_path__)),
            f"{__title__} - Documentation",
            self.iface.mainWindow(),
        )
        self.actions.append(self.action_help_plugin_menu_documentation)
        self.action_help_plugin_menu_documentation.triggered.connect(
            partial(QDesktopServices.openUrl, QUrl(__uri_homepage__))
        )

        self.iface.pluginHelpMenu().addAction(
            self.action_help_plugin_menu_documentation
        )
        # connect signal to its slot
        # wizard
        self.dlg.pushButton_quit.clicked.connect(self.on_pushbuttonquit_clicked)
        self.dlg.toolButtonPlaceFolio.clicked.connect(self.place_folio_tool)
        self.dlg.toolButtonCleanFolios.clicked.connect(self.clean_folios)
        self.dlg.toolButtonCreateMaps.clicked.connect(self.create_maps)
        self.dlg.comboBoxMapFormat.setEnabled(False)
        # self.dlg.comboBoxMapFormat.currentTextChanged.connect(
        #    self.on_comboboxmapformat_text_changed
        # )
        self.dlg.comboBoxLayout.currentTextChanged.connect(
            self.on_comboboxlayout_text_changed
        )
        self.dlg.checkBox_always_index_map.stateChanged.connect(
            self.on_checkboxalwaysindexmap_state_changed
        )
        self.dlg.checkBox_apply_to_existing_folios.stateChanged.connect(
            self.on_checkboxapplytoexistingfolios_state_changed
        )
        # load scales available for print_scale
        map_scales = self._settings.maps_scales
        if not map_scales:
            self.__map_scales = [
                "50",
                "100",
                "200",
                "500",
                "750",
                "1000",
                "1250",
                "1500",
                "2000",
            ]
        else:
            self.__map_scales = map_scales.split(",")

        self.dlg.comboBoxPrintScale.clear()
        for map_scale in self.__map_scales:
            self.dlg.comboBoxPrintScale.addItem("1 / {}".format(map_scale))

        if "200" in self.__map_scales:
            self.dlg.comboBoxPrintScale.setCurrentText("1 / 200")
        else:
            self.dlg.comboBoxPrintScale.setCurrentIndex(0)
        self.dlg.comboBoxPrintScale.currentTextChanged.connect(
            self.on_comboboxprintscale_text_changed
        )

        self.dlg.lineEdit_title.textChanged.connect(self.on_lineedittitle_text_changed)
        self.dlg.lineEdit_subtitle.textChanged.connect(
            self.on_lineeditsubtitle_text_changed
        )
        self.dlg.lineEdit_description.textChanged.connect(
            self.on_lineeditdescription_text_changed
        )
        self.dlg.lineEdit_field1.textChanged.connect(
            self.on_lineeditfield1_text_changed
        )
        self.dlg.lineEdit_field2.textChanged.connect(
            self.on_lineeditfield2_text_changed
        )
        self.dlg.lineEdit_field3.textChanged.connect(
            self.on_lineeditfield3_text_changed
        )
        self.dlg.lineEdit_field4.textChanged.connect(
            self.on_lineeditfield4_text_changed
        )
        is_first_use = self._settings.is_first_use
        templates_dir = self._settings.maps_templates_folder

        if is_first_use or not QDir(templates_dir).exists():
            PlgOptionsManager.save_from_object(self._settings)
            Layout.init_templates(True)
        if is_first_use:
            self._settings.is_first_use = False
            PlgOptionsManager.save_from_object(self._settings)
            self.run_about()
        self._layout.loadTemplates(self.dlg.comboBoxLayout)

    def unload(self):
        # print("unload")
        """Cleans up when plugin is disabled/uninstalled."""
        for action in self.actions:
            self.iface.removePluginMenu(__title__, action)
            self.iface.removeToolBarIcon(action)
        # remove the toolbar
        try:
            del self.toolbar
        except Exception:
            ...

    def run(self):
        """Main process.

        :raises Exception: if there is no item in the feed
        """
        try:
            self.dlg.show_dialog()
            self.log(
                message=tr("Everything ran OK."),
                log_level=3,
                push=False,
            )
        except Exception as err:
            self.log(
                message=tr("Houston, we've got a problem: {}".format(err)),
                log_level=2,
                push=True,
            )

    def run_about(self):
        """Run about dialog"""
        dialog = DlgAbout()
        dialog.exec_()

    def clean_folios(self):
        FolioGeometry.removeExistingFolios()
        self._layout.removeProjectLayouts(True)
        self.iface.mapCanvas().refresh()
        if self.dlg:
            self.dlg.comboBoxPrintScale.setEnabled(True)
            self.dlg.comboBoxLayout.setEnabled(True)
        self.iface.actionIdentify().trigger()

    def place_folio_tool(self):
        # print('place_folio_tool')
        if len(self.dlg.comboBoxLayout.currentText()) > 0:
            layout_name = self.dlg.comboBoxLayout.currentText()
            if Layout.layoutExists(layout_name):
                self._layout.removeLayoutByName(layout_name)
            full_filename = f"{self._settings.maps_templates_folder}/{layout_name}.qpt"
            self._layout.loadLayout(full_filename, layout_name, layout_name)
            self._layout.setCurrentLayoutByName(layout_name)
        self.on_comboboxprintscale_text_changed()
        size = self._layout.folioPrintSize()
        # Create the map tool using the canvas reference
        self.point_tool = FolioMapTool(
            self.iface.mapCanvas(), size.x(), size.y(), self._print_scale
        )
        self.point_tool.setLayoutName(self._layout.currentLayout().name())
        self.iface.mapCanvas().setMapTool(self.point_tool)

    def clean_canvas(self):
        self.clean_xfdf()
        self.clean_folios()
        self.clean_works_footprint()
        self.clean_variables()
        self.dlg.lineEdit.setText("")

    def create_maps(self):
        # print("create_maps ({})".format(self._map_format))
        self.init_map_name()
        if self._map_format == "PDF":
            self.create_pdf_maps()

    def create_pdf_maps(self):
        # print("create_pdf_maps ({})".format(self._map_format))
        self.iface.actionIdentify().trigger()
        if FolioGeometry.existsFoliosLayer():
            try:
                folios_layer = FolioGeometry.foliosLayer()
                if folios_layer:
                    # create folios
                    iterator = folios_layer.getFeatures()
                    feature = QgsFeature()
                    if iterator.nextFeature(feature):
                        layout_name = feature.attribute("layout")

                    self.map_filename = QgsExpressionContextUtils.projectScope(
                        QgsProject.instance()
                    ).variable("folio_map_name")
                    self.map_filename = Utils.expandVariablesInString(self.map_filename)

                    self._layout.setCurrentLayoutByName(layout_name)
                    """
                    #print("current layout", self._layout.currentLayout())

                    #print("custom properties", self._layout.currentLayout().customProperties())
                    #print('atlasRasterFormat', self._layout.currentLayout().customProperty('atlasRasterFormat'))
                    #print('exportWorldFile', self._layout.currentLayout().customProperty('exportWorldFile'))
                    #print('forceVector', self._layout.currentLayout().customProperty('forceVector'))
                    #print('pdfAppendGeoreference',
                          self._layout.currentLayout().customProperty('pdfAppendGeoreference'))
                    #print('pdfCreateGeoPdf', self._layout.currentLayout().customProperty('pdfCreateGeoPdf'))
                    #print('pdfDisableRasterTiles',
                          self._layout.currentLayout().customProperty('pdfDisableRasterTiles'))
                    #print('pdfExportThemes', self._layout.currentLayout().customProperty('pdfExportThemes'))
                    #print('pdfIncludeMetadata', self._layout.currentLayout().customProperty('pdfIncludeMetadata'))
                    #print('pdfLayerOrder', self._layout.currentLayout().customProperty('pdfLayerOrder'))
                    #print('pdfOgcBestPracticeFormat', self._layout.currentLayout().customProperty('pdfOgcBestPracticeFormat'))
                    #print('pdfTextFormat', self._layout.currentLayout().customProperty('pdfTextFormat'))
                    #print('pdfSimplify', self._layout.currentLayout().customProperty('pdfSimplify'))
                    #print('singleFile', self._layout.currentLayout().customProperty('singleFile'))
                    #print('variableNames', self._layout.currentLayout().customProperty('variableNames'))
                    #print('variableValues', self._layout.currentLayout().customProperty('variableValues'))
                    #print('pdfOgcBestPracticeFormat', self._layout.currentLayout().customProperty('pdfOgcBestPracticeFormat'))
                    """
                    atlas = self._layout.currentLayout().atlas()
                    atlas.setCoverageLayer(folios_layer)
                    atlas.setSortFeatures(True)
                    atlas.setSortAscending(True)
                    atlas.setEnabled(True)
                    atlas.setFilenameExpression(
                        "@folio_map_name || '-' || @atlas_featurenumber"
                    )
                    atlas.setHideCoverage(True)
                    # print("hide coverage ", atlas.hideCoverage())
                    """
                    #print("enabled", atlas.enabled())
                    #print("coverageLayer()",atlas.coverageLayer())
                    #print("count", atlas.count())
                    #print("filenameExpression()", atlas.filenameExpression())
                    #print("filterFeatures()", atlas.filterFeatures())
                    #print("filterExpression()", atlas.filterExpression())
                    #print("nameForPage()", atlas.nameForPage(1))
                    #print("pageNameExpression()", atlas.pageNameExpression())
                    atlas.setFilenameExpression("folio_map_name || '-' || @atlas_featureid")
                    #print("filenameExpression()", atlas.filenameExpression())
                    """

                    atlas.updateFeatures()

                    export_settings = QgsLayoutExporter.PdfExportSettings()

                    atlas.layout().setCustomProperty("pdfSimplify", True)
                    atlas.layout().setCustomProperty("pdfIncludeMetadata", True)
                    atlas.layout().setCustomProperty("forceVector", True)
                    atlas.layout().setCustomProperty("singleFile", False)
                    atlas.layout().setCustomProperty("pdfTextFormat", True)

                    atlas.layout().referenceMap().setAtlasDriven(True)
                    atlas.layout().referenceMap().setAtlasScalingMode(
                        QgsLayoutItemMap.Fixed
                    )

                    # disable grids if map is rotated
                    rotated = False
                    for folio in folios_layer.getFeatures():
                        if folio.attributes()[1] != 0:
                            rotated = True
                            break

                    exporter = QgsLayoutExporter(atlas.layout())
                    grid = atlas.layout().referenceMap().grid()

                    if rotated:
                        if grid:
                            grid.setEnabled(False)
                        atlas.layout().setCustomProperty("pdfCreateGeoPdf", False)
                    else:
                        atlas.layout().referenceMap().setMapRotation(0.0)
                        if grid:
                            grid.setEnabled(True)
                        if self.create_geo_pdf:
                            atlas.layout().setCustomProperty("pdfCreateGeoPdf", True)

                    my_folio_title = QgsExpressionContextUtils.projectScope(
                        QgsProject.instance()
                    ).variable("project_basename")
                    target_path = Utils.expandVariablesInString(
                        self._settings.maps_output_folder
                    )
                    os.makedirs(target_path, exist_ok=True)
                    full_filename = Utils.resolve(
                        self.map_filename + ".pdf", target_path
                    )

                    layer = FolioGeometry.foliosLayer()
                    if layer:
                        layer.setLabelsEnabled(False)
                        layer.setOpacity(0)

                    # Create a list to merge them if needed
                    plans = []
                    if atlas.layout().customProperty("singleFile"):
                        # create only one file
                        result = exporter.exportToPdf(
                            atlas, full_filename, QgsLayoutExporter.PdfExportSettings()
                        )
                        if result[0] == QgsLayoutExporter.Success:
                            msg1 = tr("Create PDF map(s) :")
                            msg2 = (
                                tr("Map(s) for ")
                                + self._map_name
                                + tr(' created in <a href="{}">{}</a>').format(
                                    QUrl.fromLocalFile(full_filename).toString(),
                                    QDir.toNativeSeparators(full_filename),
                                )
                            )
                            self.iface.messageBar().pushMessage(
                                msg1, msg2, Qgis.Success, 10
                            )
                            plans.append(full_filename)
                        else:
                            msg1 = tr("Create PDF maps :")
                            msg2 = (
                                tr("Error ")
                                + str(result[0])
                                + tr("  on creating maps in {}").format(self._map_name)
                            )
                            self.iface.messageBar().pushMessage(
                                msg1, msg2, Qgis.Critical, 10
                            )
                    else:
                        # create one file by folio
                        msg1 = tr("PDF maps in {}").format(self._map_name)
                        message_bar = self.iface.messageBar()
                        progressMessageBar = message_bar.createMessage(msg1)
                        progress = QProgressBar(progressMessageBar)
                        progress.setRange(0, atlas.count())
                        progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
                        progressMessageBar.layout().addWidget(progress)
                        message_bar.pushWidget(progressMessageBar, Qgis.Info)
                        QCoreApplication.processEvents()
                        """
                        # Create and exporter Layout for each layout generate with Atlas
                        exporter = QgsLayoutExporter(atlas.layout())
                        export_settings = QgsLayoutExporter.PdfExportSettings()
                        # For 0 to Number of features in Atlas Selection
                        """
                        atlas.beginRender()
                        atlas.first()
                        nb_errors = 0
                        for i in range(0, atlas.count()):
                            msg2 = tr("Map #{}/{} in {}").format(
                                i + 1, atlas.count(), self._map_name
                            )
                            progress.setValue(i)
                            progressMessageBar.setText(msg2)
                            QCoreApplication.processEvents()
                            self.iface.statusBarIface().showMessage(msg2)
                            exporter = QgsLayoutExporter(atlas.layout())

                            # create PDF's File
                            full_filename = Utils.resolve(
                                atlas.currentFilename() + ".pdf", target_path
                            )
                            # print("---- hide coverage ", atlas.hideCoverage())
                            result = exporter.exportToPdf(
                                full_filename, QgsLayoutExporter.PdfExportSettings()
                            )
                            if result == QgsLayoutExporter.Success:
                                self.iface.statusBarIface().showMessage(
                                    tr("Map #{} created in {}").format(
                                        i + 1, self._map_name
                                    ),
                                )
                                plans.append(full_filename)
                            else:
                                nb_errors += 1
                                self.iface.statusBarIface().showMessage(
                                    tr(
                                        "Error on creating map #{} from {} in {}"
                                    ).format(i + 1, atlas.count(), self._map_name),
                                )
                            progress.setValue(i + 1)
                            QCoreApplication.processEvents()
                            atlas.next()
                        atlas.endRender()
                        self.iface.messageBar().clearWidgets()
                        self.iface.statusBarIface().clearMessage()

                    layer = FolioGeometry.foliosLayer()
                    if layer:
                        layer.setOpacity(1)
                        layer.setLabelsEnabled(True)

                    # create an index map
                    if atlas.count() > 1 or self.create_always_index_map:
                        # create maps index map
                        # print("create maps index map")
                        # fit canvas to Folios layer
                        folios_layer.selectAll()
                        self.iface.mapCanvas().zoomToSelected()
                        # create layout
                        ta_layout_name = Layout.TA_LAYOUT_PREFIX
                        if Layout.layoutExists(ta_layout_name):
                            self._layout.removeLayoutByName(ta_layout_name)
                        full_filename = "{}/{}.qpt".format(
                            self._settings.maps_templates_folder,
                            ta_layout_name,
                        )
                        self._layout.loadLayout(
                            full_filename, ta_layout_name, ta_layout_name
                        )
                        # export layout to PDF
                        self._layout.setCurrentLayoutByName(ta_layout_name)
                        export_settings = QgsLayoutExporter.PdfExportSettings()
                        self._layout.currentLayout().setCustomProperty(
                            "pdfSimplify", True
                        )
                        self._layout.currentLayout().setCustomProperty(
                            "pdfIncludeMetadata", True
                        )
                        self._layout.currentLayout().setCustomProperty(
                            "forceVector", True
                        )
                        self._layout.currentLayout().setCustomProperty(
                            "singleFile", False
                        )
                        self._layout.currentLayout().setCustomProperty(
                            "pdfTextFormat", True
                        )

                        # set zoom for folios
                        self._layout.currentLayout().referenceMap().zoomToExtent(
                            self.iface.mapCanvas().extent()
                        )

                        # print(QgsApplication.layoutItemRegistry().itemTypes())
                        # set north
                        for li in (
                            self._layout.currentLayout().pageCollection().itemsOnPage(0)
                        ):
                            if li.type() == 65640:
                                # print("name:", li.displayName())
                                if li.displayName().startswith("North Arrow"):
                                    li.setItemRotation(0)
                                    # print("rotation:", li.itemRotation())
                        self._layout.currentLayout().refresh()

                        exporter = QgsLayoutExporter(self._layout.currentLayout())
                        # create PDF's File
                        full_filename = Utils.resolve(
                            "{}-{}{}".format("TA", self._map_name, ".pdf"),
                            target_path,
                        )
                        # print("---- hide coverage ", atlas.hideCoverage())
                        result = exporter.exportToPdf(
                            full_filename, QgsLayoutExporter.PdfExportSettings()
                        )
                        if result == QgsLayoutExporter.Success:
                            msg2 = (
                                tr("Assembly map for pour ")
                                + self._map_name
                                + tr(' created in <a href="{}">{}</a>').format(
                                    QUrl.fromLocalFile(target_path).toString(),
                                    QDir.toNativeSeparators(target_path),
                                )
                            )
                            self.iface.messageBar().pushMessage(
                                msg1, msg2, Qgis.Success, 10
                            )
                            plans.insert(0, full_filename)
                        else:
                            nb_errors += 1
                            self.iface.statusBarIface().showMessage(
                                tr("Errors on creating assembly map for {}").format(
                                    self._map_name
                                ),
                            )

                    if nb_errors == 0:
                        msg1 = tr("Create PDF map(s):")
                        msg2 = (
                            tr("Maps for ")
                            + self._map_name
                            + tr(' created in <a href="{}">{}</a>').format(
                                QUrl.fromLocalFile(target_path).toString(),
                                QDir.toNativeSeparators(target_path),
                            )
                        )
                        self.iface.messageBar().pushMessage(
                            msg1, msg2, Qgis.Success, 10
                        )
                    else:
                        msg1 = tr("Create PDF map(s):")
                        msg2 = tr("Errors  on creating maps for {}").format(
                            self._map_name
                        )
                        self.iface.messageBar().pushMessage(
                            msg1, msg2, Qgis.Critical, 10
                        )

                    """
                    pdftk_path = QSettings().value(
                        "FoliosWizard/configPDFTK", "", type=str
                    )
                    if QSettings().value(
                        "FoliosWizard/fusionPDF", False, type=bool
                    ) and (
                        QSettings().value("FoliosWizard/usePDFTK", False, type=bool)
                        and self.__checkPdftk(pdftk_path)
                    ):
                        subprocess.call(
                            [pdftk_path]
                            + plans
                            + ["output", target_path + os.sep + self._map_name + ".pdf"]
                        )
                        # Suppression des plans
                        for p in plans:
                            Path(p).unlink()
                    """
            except Exception as e:
                msg1 = tr("Unable to find folios : ")
                msg2 = str(e)
                self.iface.messageBar().pushMessage(msg1, msg2, Qgis.Critical, 10)

    def on_checkboxalwaysindexmap_state_changed(self, state):
        if state == Qt.Checked:
            self.create_always_index_map = True
        else:
            self.create_always_index_map = False

    def on_checkboxapplytoexistingfolios_state_changed(self, state):
        if state == Qt.Checked:
            self.apply_layout_changes_to_existing_folios = True
        else:
            self.apply_layout_changes_to_existing_folios = False

    def on_comboboxlayout_text_changed(self):
        # print("on_comboboxlayout_text_changed")
        if len(self.dlg.comboBoxLayout.currentText()) > 0:
            layout_name = self.dlg.comboBoxLayout.currentText()
            if self.apply_layout_changes_to_existing_folios:
                m1: str = tr("Applying layout changes to existing folios.")
                m2: str = tr(
                    "Sizes of reference map must be the same in old and new layout."
                )
                m3: str = tr("Do you actually want to do it ?")
                msg = m1 + "\n" + m2 + "\n\n" + m3
                ok = self.show_alert(self.dlg, tr("ALERT"), msg)
                if ok:
                    self.change_layout_on_existing_folios(layout_name)
            if Layout.layoutExists(layout_name):
                self._layout.removeLayoutByName(layout_name)
            full_filename = "{}/{}.qpt".format(
                self._settings.maps_templates_folder,
                layout_name,
            )
            self._layout.loadLayout(full_filename, layout_name, layout_name)
            self._layout.setCurrentLayoutByName(layout_name)
            self._layout.setPrintScale(self._print_scale)
            if self.point_tool is not None:
                point_size = self._layout.folioPrintSize()
                self.point_tool.setSize(point_size.x(), point_size.y())

    def on_comboboxmapformat_text_changed(self):
        # print("on_comboboxmapformat_text_changed")
        if len(self.dlg.comboBoxMapFormat.currentText()) > 0:
            self._map_format = self.dlg.comboBoxMapFormat.currentText()

    def on_comboboxprintscale_text_changed(self):
        # print("on_comboboxprintscale_text_changed")
        if len(self.dlg.comboBoxPrintScale.currentText()) > 0:
            self._text_scale = self.dlg.comboBoxPrintScale.currentText()
            self._print_scale = int(self.dlg.comboBoxPrintScale.currentText()[4:])
            QgsExpressionContextUtils.setProjectVariable(
                QgsProject.instance(), "folio_text_scale", self._text_scale
            )
            QgsExpressionContextUtils.setProjectVariable(
                QgsProject.instance(), "folio_print_scale", self._print_scale
            )
            if self._layout:
                self._layout.setPrintScale(self._print_scale)
            if self.point_tool is not None:
                self.point_tool.setPrintScale(
                    int(self.dlg.comboBoxPrintScale.currentText()[4:])
                )

    def on_lineedittitle_text_changed(self):
        try:
            QgsExpressionContextUtils.setProjectVariable(
                QgsProject.instance(), "folio_title", self.dlg.lineEdit_title.text()
            )
        except:
            pass

    def on_lineeditsubtitle_text_changed(self):
        try:
            QgsExpressionContextUtils.setProjectVariable(
                QgsProject.instance(),
                "folio_subtitle",
                self.dlg.lineEdit_subtitle.text(),
            )
        except:
            pass

    def on_lineeditdescription_text_changed(self):
        try:
            QgsExpressionContextUtils.setProjectVariable(
                QgsProject.instance(),
                "folio_description",
                self.dlg.lineEdit_description.text(),
            )
        except:
            pass

    def on_lineeditfield1_text_changed(self):
        try:
            QgsExpressionContextUtils.setProjectVariable(
                QgsProject.instance(), "folio_field1", self.dlg.lineEdit_field1.text()
            )
        except:
            pass

    def on_lineeditfield2_text_changed(self):
        try:
            QgsExpressionContextUtils.setProjectVariable(
                QgsProject.instance(), "folio_field2", self.dlg.lineEdit_field2.text()
            )
        except:
            pass

    def on_lineeditfield3_text_changed(self):
        try:
            QgsExpressionContextUtils.setProjectVariable(
                QgsProject.instance(), "folio_field3", self.dlg.lineEdit_field3.text()
            )
        except:
            pass

    def on_lineeditfield4_text_changed(self):
        try:
            QgsExpressionContextUtils.setProjectVariable(
                QgsProject.instance(), "folio_field4", self.dlg.lineEdit_field4.text()
            )
        except:
            pass

    def on_pushbuttonquit_clicked(self):
        clear_project_metadata_variables()
        self.dlg.hide()

    def init_map_name(self):
        try:
            self._map_name = f"{self._settings.maps_prefix} {QgsProject.instance().baseName()} {self._settings.maps_suffix}"
            self._map_name = Utils.expandVariablesInString(self._map_name)
            self._map_name = self._map_name.strip().replace(" ", "-")
            QgsExpressionContextUtils.setProjectVariable(
                QgsProject.instance(), "folio_map_name", self._map_name
            )
            self.titre = self._map_name
        except Exception as e:
            msg1 = tr("Unable to build map name : ")
            msg2 = str(e)
            self.iface.messageBar().pushMessage(msg1, msg2, Qgis.Critical, 10)

    def change_layout_on_existing_folios(self, layout_name):
        try:
            full_filename = "{}/{}.qpt".format(
                self._settings.maps_templates_folder,
                layout_name,
            )
            self._layout.loadLayout(full_filename, layout_name, layout_name)
            self._layout.setCurrentLayoutByName(layout_name)
            self._layout.setPrintScale(self._print_scale)
            size = self._layout.folioPrintSize()
            if self.point_tool is not None:
                self.point_tool.setSize(size.x(), size.y())
            # update existing folios with new layout name
            folios_layer = FolioGeometry.foliosLayer()
            with edit(folios_layer):
                for f in folios_layer.getFeatures():
                    f.setAttribute("layout", layout_name)
                    folios_layer.updateFeature(f)
        except Exception as e:
            msg1 = tr("Unable to change layout on existing folios : ")
            msg2 = str(e)
            self.iface.messageBar().pushMessage(msg1, msg2, Qgis.Critical, 10)

    def show_alert(
        self,
        parent,
        title,
        msg,
        yes: QtWidgets.QMessageBox = QtWidgets.QMessageBox.Yes,
        no: QtWidgets.QMessageBox = QtWidgets.QMessageBox.No,
    ):
        answer = QtWidgets.QMessageBox.question(parent, title, msg, yes | no)
        if answer == yes:
            return True
        else:
            return False

    def show_metadata(self):
        read_show_metadata(show_details=True, set_project_variables=False)
