# -*- coding: utf-8 -*-
# /***************************************************************************
# Irmt
#                                 A QGIS plugin
# OpenQuake Integrated Risk Modelling Toolkit
#                              -------------------
#        begin                : 2015-04-16
#        copyright            : (C) 2015 by GEM Foundation
#        email                : devops@openquake.org
# ***************************************************************************/
#
# OpenQuake is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# OpenQuake is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with OpenQuake.  If not, see <http://www.gnu.org/licenses/>.

import json
from copy import deepcopy
from qgis.core import QgsProject

from qgis.PyQt.QtCore import pyqtSlot
from qgis.PyQt.QtWidgets import QDialog, QDialogButtonBox, QInputDialog

from svir.utilities.utils import tr, log_msg, get_ui_class
from svir.utilities.shared import PROJECT_TEMPLATE

FORM_CLASS = get_ui_class('ui_projects_manager_dialog.ui')


class ProjectsManagerDialog(QDialog, FORM_CLASS):
    """
    Modal dialog allowing to select (and possibly edit) one of the project
    definitions available for the active layer, or for creating a new project
    definition
    """
    def __init__(self, iface):
        self.iface = iface
        QDialog.__init__(self)
        # Set up the user interface from Designer.
        self.setupUi(self)
        self.cancel_button = self.buttonBox.button(QDialogButtonBox.Cancel)
        self.ok_button = self.buttonBox.button(QDialogButtonBox.Ok)
        self.ok_button.setEnabled(False)
        self.suppl_info = {}
        self.selected_proj_def = None
        self.get_suppl_info()
        self.populate_proj_def_cbx()

    def get_suppl_info(self):
        active_layer_id = self.iface.activeLayer().id()
        suppl_info_str, is_available = \
            QgsProject.instance().readEntry('irmt', active_layer_id)
        if is_available and suppl_info_str:
            self.suppl_info = json.loads(suppl_info_str)
        else:
            project_definition = deepcopy(PROJECT_TEMPLATE)
            self.suppl_info = {'selected_project_definition_idx': 0,
                               'project_definitions': [project_definition]
                               }

    # NOTE: Still unused
    def get_selected_proj_def(self):
        try:
            selected_idx = self.suppl_info['selected_project_definition_idx']
            self.selected_proj_def = self.suppl_info['project_definitions'][
                selected_idx]
        except KeyError:
            return None

    def populate_proj_def_cbx(self):
        self.proj_def_cbx.blockSignals(True)
        self.proj_def_cbx.clear()
        for proj_def in self.suppl_info['project_definitions']:
            if 'title' in proj_def:
                self.proj_def_cbx.addItem(proj_def['title'])
            else:
                self.proj_def_cbx.addItem('Untitled project definition')
        if ('selected_project_definition_idx' in self.suppl_info
                and self.suppl_info['selected_project_definition_idx']
                is not None):
            self.proj_def_cbx.setCurrentIndex(
                self.suppl_info['selected_project_definition_idx'])
        self.proj_def_cbx.blockSignals(False)
        self.update_form()

    def update_proj_def_title(self):
        if self.selected_proj_def is not None:
            try:
                self.proj_def_title.setText(self.selected_proj_def['title'])
            except KeyError:
                self.proj_def_title.setText('')

    def update_proj_def_descr(self):
        if self.selected_proj_def is not None:
            try:
                self.proj_def_descr.setPlainText(
                    self.selected_proj_def['description'])
            except KeyError:
                self.proj_def_descr.setPlainText('')

    def display_proj_def_raw(self):
        proj_def_str = json.dumps(self.selected_proj_def,
                                  sort_keys=False,
                                  indent=2,
                                  separators=(',', ': '))
        self.proj_def_raw.setPlainText(proj_def_str)

    def add_proj_def(self, title, proj_def=None):
        if proj_def is None:
            proj_def = deepcopy(PROJECT_TEMPLATE)
        proj_def['title'] = title
        self.suppl_info['project_definitions'].append(proj_def)
        self.suppl_info['selected_project_definition_idx'] = \
            len(self.suppl_info['project_definitions']) - 1
        self.populate_proj_def_cbx()

    def update_title_in_combo(self):
        current_index = self.proj_def_cbx.currentIndex()
        self.proj_def_cbx.setItemText(
            current_index, self.proj_def_title.text())

    @pyqtSlot(str)
    def on_proj_def_title_textEdited(self):
        self.selected_proj_def['title'] = self.proj_def_title.text()
        self.update_title_in_combo()
        self.display_proj_def_raw()

    @pyqtSlot()
    def on_proj_def_descr_textChanged(self):
        self.selected_proj_def['description'] = \
            self.proj_def_descr.toPlainText()
        self.display_proj_def_raw()

    def update_form(self):
        self.suppl_info['selected_project_definition_idx'] = \
            self.proj_def_cbx.currentIndex()
        self.selected_proj_def = self.suppl_info['project_definitions'][
            self.suppl_info['selected_project_definition_idx']]
        self.update_proj_def_title()
        self.update_proj_def_descr()
        self.display_proj_def_raw()

    @pyqtSlot(str)
    def on_proj_def_cbx_currentIndexChanged(self):
        self.update_form()

    @pyqtSlot()
    def on_clone_btn_clicked(self):
        title = (self.selected_proj_def['title'] + ' (copy)'
                 if 'title' in self.selected_proj_def
                 else '(copy)')
        title, ok = QInputDialog().getText(self,
                                           tr('Assign a title'),
                                           tr('Project definition title'),
                                           text=title)
        if ok:
            self.add_proj_def(title, self.selected_proj_def)

    @pyqtSlot()
    def on_add_proj_def_btn_clicked(self):
        title, ok = QInputDialog().getText(
            self, tr('Assign a title'), tr('Project definition title'))
        if ok:
            self.add_proj_def(title)

    @pyqtSlot()
    def on_proj_def_raw_textChanged(self):
        try:
            project_definition_str = self.proj_def_raw.toPlainText()
            project_definition = json.loads(project_definition_str)
            self.suppl_info['project_definitions'][self.suppl_info[
                'selected_project_definition_idx']] = project_definition
            self.selected_proj_def = project_definition
            self.ok_button.setEnabled(True)
        except ValueError as exc:
            # get the exception message
            exc_msg = exc.args[0]
            if isinstance(exc_msg, bytes):
                exc_msg = exc_msg.decode('utf-8')   # make it a unicode object
            log_msg(exc_msg, level='C', message_bar=self.iface.messageBar(),
                    exception=exc)
            self.ok_button.setEnabled(False)
