# -*- coding: utf-8 -*-
"""
/***************************************************************************
 LiDARForestryHeight
                                 A QGIS plugin. LiDAR Forestry Height
                                 generates a DEM with the forest height,
                                 calculated from a classified LiDAR point
                                 cloud using LasPy Library

 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                             -------------------
        begin                : 2018-09-24
        copyright            : (C) 2019 by PANOimagen S.L.
        email                : info@panoimagen.com
        git sha              : $Format:%H$
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/
"""
from __future__ import unicode_literals
import os

from qgis.PyQt import uic
from qgis.PyQt import QtWidgets

import logging
logger = logging.getLogger("lfh")
logger.setLevel(logging.DEBUG)

from qgis.core import Qgis, QgsRasterLayer, QgsProject
from qgis.gui import QgisInterface, QgsMessageBar

from .lfh_errors import LasPyNotFoundError

try:
    from . import plugin_process
    LASPY_INSTALLED = True
except LasPyNotFoundError as e:
    LASPY_INSTALLED = False
    
from. import files_paths_funs as dir_fns

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


class LiDARForestryHeightDialog(QtWidgets.QDialog, FORM_CLASS):
    def __init__(self, parent=None):
        """Constructor."""
        super(LiDARForestryHeightDialog, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)
        self._initUi()
        self.iface = QgisInterface
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.accepted.connect(self.preparingProcess)
        self.buttonBox.rejected.connect(self.reject)

        self.addResultsCheckBox.setChecked(True)
        self.createAndLoadIntermCheckBox.setChecked(False)

        self.outputFolderToolButton.clicked.connect(self.setOutPath)
        self.inputToolButton.clicked.connect(self.inputLiDAR)

    def _initUi(self):
        from . import version_number
        version = version_number.get_version_from_metadata()
        self.versionLabel.setText(u'Version: {}'.format(version))

        if LASPY_INSTALLED:
            text = u'LasPy Library avaible'
            color = u'color: black'
        else:
            text = (u'LasPy Library is not installed. Visit' +
                   u' plugin homepage or LasPy documentation')
            color = u'color: red'

        self.lasPyInstalledLabel.setText(text)
        self.lasPyInstalledLabel.setStyleSheet(color)

        interpolate_methods = ['nearest', 'linear', 'cubic']
        self.interpolatingMethodComboBox.addItems(interpolate_methods)

        self.updateUi()

    def updateUi(self):
        """ Enable/disable UI options if LasPy Library is/isn't installed
        """
        self.pluginGroupBox.setEnabled(LASPY_INSTALLED)
        self.inputGroupBox.setEnabled(LASPY_INSTALLED)
        self.resultsParamsGroupBox.setEnabled(LASPY_INSTALLED)

    def inputLiDAR(self):
        fileNames = QtWidgets.QFileDialog.getOpenFileNames(self,
                u"Select the input LiDAR classified file/s",
                self.inputLineEdit.text(),
                ("LiDAR files (*.laz *.LAZ* *.las *.LAS);;" +
                 " All files (*)"))
        if fileNames:
            # quoted = ['"{}"'.format(fn) for fn in fileNames]
            self.inputLineEdit.setText(", ".join(fileNames[0]))
            if not self.outputFolderLineEdit.text():
                try:
                    outPath = os.path.join(
                        os.path.split(os.path.abspath(fileNames[0][0]))[0],
                        u'lidar_forestry_height_output')
                    self.outputFolderLineEdit.setText(outPath)
                except IndexError:
                    pass

    def setOutPath(self):
        """Function to select the output folder and update the LineEdit
        """
        outPath = QtWidgets.QFileDialog.getExistingDirectory(self,
                u"Select the output folder",
                self.outputFolderToolButton.text())
        if outPath:
            self.outputFolderLineEdit.setText(os.path.join(
                    outPath, u'lidar_forestry_height_output'))

    def preparingProcess(self):

        if not LASPY_INSTALLED:
            self.showQMessage(u"Error: LasPy Library is not installed!" +
                              u"\nPlease, solve it. More information" +
                              u" at plugin homepage.")
            return

        filenames = self.inputLineEdit.text()

        if not filenames:
            self.showQMessage(u"Error: Not input file selected!\nPlease," +
                              u" select one.")

        outPath = self.outputFolderLineEdit.text()

        if not outPath:
            self.showQMessage(u"Error: Not output folder selected!\n" +
                              u"Please, select one.")

        if filenames and outPath:
            for f in filenames.split(","):
                full_filename = f.strip()
                _, filename = os.path.split(full_filename)
                if outPath:
                    self.settingProcessParams(full_filename, outPath)

    def settingProcessParams(self, full_filename, outPath):

        self.pixel_size = self.pixelSizeDoubleSpinBox.value()
        self.inter_method = self.interpolatingMethodComboBox.currentText()
        self.load_result = self.addResultsCheckBox.isChecked()
        self.partials_create_load = self.createAndLoadIntermCheckBox.isChecked()

        _, filename = os.path.split(full_filename)
        base_name, ext = os.path.splitext(filename)
        start_index = 1
        out_path = os.path.join(
                outPath, (base_name + '_r' + str(start_index)))

        if os.path.exists(out_path):
            import glob
            key_for_glob = os.path.join(outPath, (base_name + '_r*' ))
            dirs_list = glob.glob(key_for_glob)
            indexes = []
            for directory in dirs_list:
                try:
                    fn_index = int(directory[-3:])
                except ValueError:
                    try:
                        fn_index = int(directory[-2:])
                    except ValueError:
                        fn_index = int(directory[-1])
                indexes.append(fn_index)
                max_index = max(indexes)
            next_index = max_index + 1
            out_path = os.path.join(outPath,
                        (base_name + '_r' + str(next_index)))

        self.dir_fns = dir_fns.DirAndPaths(filename, out_path)

        self.showMessage(u'Starting processing LiDAR data {}'.format(base_name),
            Qgis.MessageLevel(0))

        try:
            self.process = plugin_process.Process(full_filename,
                                            out_path,
                                            self.pixel_size,
                                            self.inter_method,
                                            self.partials_create_load)

        except (ValueError, OSError) as message:
            self.showQMessage(str(message))
            self.showMessage('LiDAR Forestry Height stopped process',
                                  Qgis.MessageLevel(1))
            return

        if self.partials_create_load:
            self.load_raster_layer(self.process.dirs.out_paths['dtm'])
            self.load_raster_layer(self.process.dirs.out_paths['dsm'])

        if self.load_result:
            self.load_raster_layer(self.process.dirs.out_paths['height'])

    def load_raster_layer(self, raster_full_path):
        """Add the result to canvas.
        """
        raster_filename, _ = os.path.splitext(os.path.split(raster_full_path)[-1])
        rlayer = QgsRasterLayer(raster_full_path,
                raster_filename)
        QgsProject.instance().addMapLayer(rlayer)

    def showMessage(self, message, msg_level):
        """This function shows a QGIS message bar when is called with the
        message and the message Level -i.e.:INFO-
        """
        QgsMessageBar().pushMessage(
                message, level=msg_level)

    def showQMessage(self, message, msg_level = "Error message"):
        """This function shows a Qt message dialog when is called with the
        message and the message Level-
        """
        QtWidgets.QMessageBox.warning(self, msg_level, message)
