"""
***************************************************************************
    i.py
    ----
    Date                 : April 2016
    Copyright            : (C) 2016 by Médéric Ribreux
    Email                : mederic dot ribreux at medspx dot 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.                                   *
*                                                                         *
***************************************************************************
"""

__author__ = "Médéric Ribreux"
__date__ = "April 2016"
__copyright__ = "(C) 2016, Médéric Ribreux"

import os
from processing.tools.system import isWindows, getTempFilename
from grassprovider.grass_utils import GrassUtils
from qgis.PyQt.QtCore import QDir
from qgis.core import QgsProcessingParameterString
from qgis.core import QgsMessageLog


def orderedInput(alg, parameters, context, src, tgt, numSeq=None):
    """Import multiple rasters in order
    :param alg: algorithm object.
    :param parameters: algorithm parameters dict.
    :param context: algorithm context.
    :param src: Name of the source parameter.
    :param tgt: Name of a new input parameter.
    :param numSeq: List of a sequence for naming layers.
    """
    rootFilename = f"rast_{os.path.basename(getTempFilename(context=context))}."
    # parameters[tgt] = rootFilename
    param = QgsProcessingParameterString(
        tgt, "virtual input", rootFilename, False, False
    )
    alg.addParameter(param)

    rasters = alg.parameterAsLayerList(parameters, src, context)
    # Handle specific range
    if numSeq is None:
        numSeq = list(range(1, len(rasters) + 1))

    for idx, raster in enumerate(rasters):
        rasterName = f"{rootFilename}{numSeq[idx]}"
        alg.loadRasterLayer(rasterName, raster, context, False, None, rasterName)

    # Don't forget to remove the old input parameter
    alg.removeParameter(src)


def regroupRasters(alg, parameters, context, src, group, subgroup=None, extFile=None):
    """
    Group multiple input rasters into a group
    * If there is a subgroupField, a subgroup will automatically be created.
    * When an external file is provided, the file is copied into the respective
    directory of the subgroup.
    :param parameters:
    :param context:
    :param src: name of input parameter with multiple rasters.
    :param group: name of group.
    :param subgroup: name of subgroup.
    :param extFile: dict : parameterName:directory name
    """
    # Create a group parameter
    groupName = f"group_{os.path.basename(getTempFilename(context=context))}"
    param = QgsProcessingParameterString(
        group, "virtual group", groupName, False, False
    )
    alg.addParameter(param)

    # Create a subgroup
    subgroupName = None
    if subgroup:
        subgroupName = f"subgroup_{os.path.basename(getTempFilename(context=context))}"
        param = QgsProcessingParameterString(
            subgroup, "virtual subgroup", subgroupName, False, False
        )
        alg.addParameter(param)

    # Compute raster names
    rasters = alg.parameterAsLayerList(parameters, src, context)
    rasterNames = []
    for idx, raster in enumerate(rasters):
        name = f"{src}_{idx}"
        if name in alg.exportedLayers:
            rasterNames.append(alg.exportedLayers[name])

    # Insert a i.group command
    command = "i.group group={}{} input={}".format(
        groupName,
        f" subgroup={subgroupName}" if subgroup else "",
        ",".join(rasterNames),
    )
    alg.commands.append(command)

    # Handle external files
    # if subgroupField and extFile:
    #     for ext in extFile.keys():
    #         extFileName = new_parameters[ext]
    #         if extFileName:
    #             shortFileName = os.path.basename(extFileName)
    #             destPath = os.path.join(GrassUtils.grassMapsetFolder(),
    #                                     'PERMANENT',
    #                                     'group', new_parameters[group.name()],
    #                                     'subgroup', new_parameters[subgroup.name()],
    #                                     extFile[ext], shortFileName)
    #             copyFile(alg, extFileName, destPath)

    alg.removeParameter(src)

    return groupName, subgroupName


def importSigFile(alg, group, subgroup, src, sigDir="sig"):
    """
    Import a signature file into an
    internal GRASSDB folder
    """
    shortSigFile = os.path.basename(src)
    interSig = os.path.join(
        GrassUtils.grassMapsetFolder(),
        "PERMANENT",
        "group",
        group,
        "subgroup",
        subgroup,
        sigDir,
        shortSigFile,
    )
    copyFile(alg, src, interSig)
    return shortSigFile


def exportSigFile(alg, group, subgroup, dest, sigDir="sig"):
    """
    Export a signature file from internal GRASSDB
    to final destination
    """
    shortSigFile = os.path.basename(dest)

    grass_version = int(GrassUtils.installedVersion().split(".")[0])
    if grass_version >= 8:
        interSig = os.path.join(
            GrassUtils.grassMapsetFolder(),
            "PERMANENT",
            "signatures",
            sigDir,
            shortSigFile,
            "sig",
        )
    else:
        interSig = os.path.join(
            GrassUtils.grassMapsetFolder(),
            "PERMANENT",
            "group",
            group,
            "subgroup",
            subgroup,
            sigDir,
            shortSigFile,
        )
    moveFile(alg, interSig, dest)
    return interSig


def exportInputRasters(alg, parameters, context, rasterDic):
    """
    Export input rasters
    Use a dict to make input/output link:
    { 'inputName1': 'outputName1', 'inputName2': 'outputName2'}
    """
    createOpt = alg.parameterAsString(parameters, alg.GRASS_RASTER_FORMAT_OPT, context)
    metaOpt = alg.parameterAsString(parameters, alg.GRASS_RASTER_FORMAT_META, context)

    # Get inputs and outputs
    for inputName, outputName in rasterDic.items():
        fileName = os.path.normpath(
            alg.parameterAsOutputLayer(parameters, outputName, context)
        )
        grassName = alg.exportedLayers[inputName]
        outFormat = GrassUtils.getRasterFormatFromFilename(fileName)
        alg.exportRasterLayer(grassName, fileName, True, outFormat, createOpt, metaOpt)


def verifyRasterNum(alg, parameters, context, rasters, mini, maxi=None):
    """Verify that we have at least n rasters in multipleInput"""
    num = len(alg.parameterAsLayerList(parameters, rasters, context))
    if num < mini:
        return (
            False,
            f"You need to set at least {mini} input rasters for this algorithm!",
        )
    if maxi and num > maxi:
        return (
            False,
            f"You need to set a maximum of {maxi} input rasters for this algorithm!",
        )
    return True, None


# def file2Output(alg, output):
#     """Transform an OutputFile to a parameter"""
#     # Get the outputFile
#     outputFile = alg.getOutputFromName(output)
#     alg.removeOutputFromName(output)

#     # Create output parameter
#     param = getParameterFromString("ParameterString|{}|output file|None|False|False".format(output), 'GrassAlgorithm')
#     param.value = outputFile.value
#     alg.addParameter(param)

#     return outputFile


def createDestDir(alg, toFile):
    """Generates an mkdir command for GRASS script"""
    # Creates the destination directory
    command = '{} "{}"'.format(
        "MD" if isWindows() else "mkdir -p",
        QDir.toNativeSeparators(os.path.dirname(toFile)),
    )
    alg.commands.append(command)


def moveFile(alg, fromFile, toFile):
    """Generates a move command for GRASS script"""
    createDestDir(alg, toFile)
    command = '{} "{}" "{}"'.format(
        "MOVE /Y" if isWindows() else "mv -f",
        QDir.toNativeSeparators(fromFile),
        QDir.toNativeSeparators(toFile),
    )
    alg.commands.append(command)


def copyFile(alg, fromFile, toFile):
    """Generates a copy command for GRASS script"""
    createDestDir(alg, toFile)
    command = '{} "{}" "{}"'.format(
        "COPY /Y" if isWindows() else "cp -f",
        QDir.toNativeSeparators(fromFile),
        QDir.toNativeSeparators(toFile),
    )
    alg.commands.append(command)
