"""
***************************************************************************
    v_net.py
    --------
    Date                 : December 2015
    Copyright            : (C) 2015 by Médéric Ribreux
    Email                : medspx 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.                                   *
*                                                                         *
***************************************************************************

This Python module handles pre-treatment operations for v.net.* GRASS modules.
Before using a v.net module you often have to incorporate a points layer into
the network vector map.
"""

__author__ = "Médéric Ribreux"
__date__ = "December 2015"
__copyright__ = "(C) 2015, Médéric Ribreux"

import os
from qgis.core import QgsProcessingException
from processing.tools.system import getTempFilename

from qgis.PyQt.QtCore import QCoreApplication


def incorporatePoints(
    alg,
    parameters,
    context,
    feedback,
    pointLayerName="points",
    networkLayerName="input",
):
    """
    incorporate points with lines to form a GRASS network
    """

    # Grab the point layer and delete this parameter
    pointLayer = alg.parameterAsVectorLayer(parameters, pointLayerName, context)
    if pointLayer:
        # Create an intermediate GRASS layer which is the combination of network + centers
        intLayer = "net" + os.path.basename(getTempFilename(context=context))

        pointLayer = alg.exportedLayers[pointLayerName]

        # Grab the network layer
        lineLayer = alg.parameterAsVectorLayer(parameters, networkLayerName, context)
        if lineLayer:
            lineLayer = alg.exportedLayers[networkLayerName]
        else:
            raise QgsProcessingException(
                QCoreApplication.translate(
                    "GrassAlgorithmExt", "GRASS v.net requires a lines layer!"
                )
            )

        threshold = alg.parameterAsDouble(parameters, "threshold", context)

        # Create the v.net connect command for point layer integration
        command = "v.net -s input={} points={} output={} operation=connect threshold={}".format(
            lineLayer, pointLayer, intLayer, threshold
        )
        alg.commands.append(command)

        # Connect the point layer database to the layer 2 of the network
        command = f"v.db.connect -o map={intLayer} table={pointLayer} layer=2"
        alg.commands.append(command)

        # remove undesired parameters
        alg.removeParameter(pointLayerName)

        # Use temp layer for input
        alg.exportedLayers[networkLayerName] = intLayer

    # Process the command
    if "threshold" in parameters:
        alg.removeParameter("threshold")

    alg.processCommand(parameters, context, feedback)


def variableOutput(alg, layers, parameters, context, nocats=True):
    """Handle variable data output for v.net modules:
    :param layers:
    layers is a dict of outputs:
    { 'outputName': ['srcLayer', 'output_type', output_layer_number, nocats],
    ...
    }
    where:
    - outputName is the name of the output in the description file.
    - srcLayer is the grass name of the layer to export.
    - output_type is the GRASS datatype (point/line/area/etc.).
    - output_layer_number is the GRASS layer number for multiple layers datasets.
    - nocats indicates weither we need to also export without categories items.
    :param parameters:
    :param context:
    :param nocats: do not add categories.
    """
    for outputName, typeList in layers.items():
        if not isinstance(typeList, list):
            continue

        file_name = alg.parameterAsOutputLayer(parameters, outputName, context)

        src_layer = typeList[0]
        output_type = typeList[1]
        output_layer_number = typeList[2]
        no_cats = typeList[3]

        grass_name = f"{src_layer}{alg.uniqueSuffix}"
        alg.exportVectorLayer(
            grassName=grass_name,
            fileName=file_name,
            layer=output_layer_number,
            exportnocat=no_cats,
            dataType=output_type,
        )


def processOutputs(alg, parameters, context, feedback):
    idx = alg.parameterAsInt(parameters, "operation", context)
    operations = alg.parameterDefinition("operation").options()
    operation = operations[idx]

    if operation == "nodes":
        outputParameter = {"output": ["output", "point", 2, True]}
    elif operation == "connect":
        outputParameter = {"output": ["output", "line", 1, False]}
    elif operation == "arcs":
        outputParameter = {"output": ["output", "line", 1, True]}
    variableOutput(alg, outputParameter, parameters, context)
