"""
***************************************************************************
    Relief.py
    ---------------------
    Date                 : December 2016
    Copyright            : (C) 2016 by Alexander Bruy
    Email                : alexander dot bruy at gmail dot com
***************************************************************************
*                                                                         *
*   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.                                   *
*                                                                         *
***************************************************************************
"""

__author__ = "Alexander Bruy"
__date__ = "December 2016"
__copyright__ = "(C) 2016, Alexander Bruy"

import os

from qgis.analysis import QgsRelief
from qgis.core import (
    QgsProcessingException,
    QgsProcessingParameterBoolean,
    QgsProcessingParameterDefinition,
    QgsProcessingParameterFileDestination,
    QgsProcessingParameterNumber,
    QgsProcessingParameterRasterDestination,
    QgsProcessingParameterRasterLayer,
    QgsRasterFileWriter,
)
from qgis.PyQt.QtGui import QColor, QIcon

from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm

pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]


class ParameterReliefColors(QgsProcessingParameterDefinition):
    def __init__(self, name="", description="", parent=None, optional=True):
        super().__init__(name, description, None, optional)
        self.parent = parent
        self.setMetadata(
            {
                "widget_wrapper": "processing.algs.qgis.ui.ReliefColorsWidget.ReliefColorsWidgetWrapper"
            }
        )

    def type(self):
        return "relief_colors"

    def clone(self):
        return ParameterReliefColors(
            self.name(),
            self.description(),
            self.parent,
            self.flags() & QgsProcessingParameterDefinition.Flag.FlagOptional,
        )

    @staticmethod
    def valueToColors(value):
        if value is None:
            return None

        if value == "":
            return None

        if isinstance(value, str):
            return value.split(";")
        else:
            return ParameterReliefColors.colorsToString(value)

    @staticmethod
    def colorsToString(colors):
        return ";".join(
            f"{c[0]:f}, {c[1]:f}, {c[2]:d}, {c[3]:d}, {c[4]:d}" for c in colors
        )


class Relief(QgisAlgorithm):
    INPUT = "INPUT"
    Z_FACTOR = "Z_FACTOR"
    AUTO_COLORS = "AUTO_COLORS"
    COLORS = "COLORS"
    OUTPUT = "OUTPUT"
    FREQUENCY_DISTRIBUTION = "FREQUENCY_DISTRIBUTION"

    def icon(self):
        return QIcon(os.path.join(pluginPath, "images", "dem.png"))

    def group(self):
        return self.tr("Raster terrain analysis")

    def groupId(self):
        return "rasterterrainanalysis"

    def __init__(self):
        super().__init__()

    def initAlgorithm(self, config=None):
        self.addParameter(
            QgsProcessingParameterRasterLayer(self.INPUT, self.tr("Elevation layer"))
        )
        self.addParameter(
            QgsProcessingParameterNumber(
                self.Z_FACTOR,
                self.tr("Z factor"),
                type=QgsProcessingParameterNumber.Type.Double,
                minValue=0.00,
                defaultValue=1.0,
            )
        )
        self.addParameter(
            QgsProcessingParameterBoolean(
                self.AUTO_COLORS,
                self.tr("Generate relief classes automatically"),
                defaultValue=False,
            )
        )
        self.addParameter(
            ParameterReliefColors(
                self.COLORS, self.tr("Relief colors"), self.INPUT, True
            )
        )
        self.addParameter(
            QgsProcessingParameterRasterDestination(self.OUTPUT, self.tr("Relief"))
        )
        self.addParameter(
            QgsProcessingParameterFileDestination(
                self.FREQUENCY_DISTRIBUTION,
                self.tr("Frequency distribution"),
                "CSV files (*.csv)",
                optional=True,
                createByDefault=False,
            )
        )

    def name(self):
        return "relief"

    def displayName(self):
        return self.tr("Relief")

    def shortDescription(self):
        return self.tr("Creates a shaded relief layer from digital elevation data.")

    def shortHelpString(self):
        return self.tr(
            "This algorithm creates a shaded relief layer from digital elevation data."
        )

    def processAlgorithm(self, parameters, context, feedback):
        inputFile = self.parameterAsRasterLayer(
            parameters, self.INPUT, context
        ).source()
        zFactor = self.parameterAsDouble(parameters, self.Z_FACTOR, context)
        automaticColors = self.parameterAsBoolean(parameters, self.AUTO_COLORS, context)
        outputFile = self.parameterAsOutputLayer(parameters, self.OUTPUT, context)
        frequencyDistribution = self.parameterAsFileOutput(
            parameters, self.FREQUENCY_DISTRIBUTION, context
        )

        outputFormat = QgsRasterFileWriter.driverForExtension(
            os.path.splitext(outputFile)[1]
        )

        relief = QgsRelief(inputFile, outputFile, outputFormat)

        if automaticColors:
            reliefColors = relief.calculateOptimizedReliefClasses()
        else:
            colors = ParameterReliefColors.valueToColors(parameters[self.COLORS])
            if colors is None or len(colors) == 0:
                raise QgsProcessingException(
                    self.tr(
                        'Specify relief colors or activate "Generate relief classes automatically" option.'
                    )
                )

            reliefColors = []
            for c in colors:
                v = c.split(",")
                color = QgsRelief.ReliefColor(
                    QColor(int(v[2]), int(v[3]), int(v[4])), float(v[0]), float(v[1])
                )
                reliefColors.append(color)

        relief.setReliefColors(reliefColors)
        relief.setZFactor(zFactor)
        if frequencyDistribution:
            relief.exportFrequencyDistributionToCsv(frequencyDistribution)
        res = relief.processRaster(feedback)
        if res == 1:
            raise QgsProcessingException(self.tr("Can not open input file."))
        elif res == 2:
            raise QgsProcessingException(
                self.tr("Can not get GDAL driver for output file.")
            )
        elif res == 3:
            raise QgsProcessingException(self.tr("Can not create output file."))
        elif res == 4:
            raise QgsProcessingException(self.tr("Can not get input band."))
        elif res == 5:
            raise QgsProcessingException(self.tr("Can not create output bands."))
        elif res == 6:
            raise QgsProcessingException(
                self.tr("Output raster size is too small (at least 3 rows needed).")
            )
        elif res == 7:
            feedback.pushInfo(self.tr("Canceled."))

        return {
            self.OUTPUT: outputFile,
            self.FREQUENCY_DISTRIBUTION: frequencyDistribution,
        }
