# -*- coding: utf-8 -*-
# this script performs all the task dealing with the active channel processing

def active_channel_processing(QgsProject, QgsVectorLayer, outputs, QgsProcessing, processing, selected_layer_ac,
                              input_blocks_vb, export_ac, export_csv_ac, flag_load_temp_ac, name_active_channel_blocks,
                              name_active_channel_centerline):
    """

    :param QgsProject: the instance of the QGIS project
    :type QgsProject: QGIS project
    :param QgsVectorLayer: a QGIS vector layer
    :type QgsVectorLayer: QgsVectorLayer
    :param outputs: a dictionary to store the outputs of the QGIS processes
    :type outputs:dictionary
    :param QgsProcessing: the QGIS processes
    :type QgsProcessing: QgsProcessing
    :param processing: the QGIS processes
    :type processing: QgsProcessing
    :param selected_layer_ac: the polygon vector layer of the active channel
    :type selected_layer_ac: vector layer
    :param input_blocks_vb: the vector layer of the blocks of the valley bottom
    :type input_blocks_vb: vector layer
    :param export_ac: the path to the polygon vector layer to export the blocks of the active channel
    :type export_ac: string
    :param export_csv_ac: the path to the table to export the blocks of the active channel
    :type export_csv_ac: string
    :param flag_load_temp_ac: a flag in order to load or no the temporary layers
    :type flag_load_temp_ac: boolean
    :param name_active_channel_blocks: the name of the temporary layer of the active channel blocks
    :type name_active_channel_blocks: string
    :param name_active_channel_centerline: the name of the temporary layer of the centerline of the active channel
    :type name_active_channel_centerline: string
    :return: generate and load the layer (and the table) of the blocks of the active channel
    :rtype:
    """
    # we remove the islands from the active channel layer
    alg_params = {
        'INPUT': selected_layer_ac,
        'MIN_AREA': 0,
        'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
    }
    outputs['ac_noisland'] = processing.run('native:deleteholes', alg_params)

    # we build the centerlines of the active channel
    alg_params = {
        'Densify Field': '',
        'Line Spacing': 3,
        'Method': 0,  # Centerlines
        'Polygons': outputs['ac_noisland']['OUTPUT'],
        'Simplify': 0,
        'Simplify Field': '',
        'Trim Field': '',
        'Trim Iterations': 0,
        'Centerlines': QgsProcessing.TEMPORARY_OUTPUT
    }
    outputs['ac_centerline'] = processing.run('Algorithms:Centerlines', alg_params)

    # we dissolve the centerlines of the active channel
    alg_params = {
        'FIELD': [''],
        'INPUT': outputs['ac_centerline']['Centerlines'],
        'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
    }
    outputs['ac_centerline_dissolved'] = processing.run('native:dissolve', alg_params)

    # we only keep the field 'ID' of this dissolved centerline
    alg_params = {
        'INPUT': outputs['ac_centerline_dissolved']['OUTPUT'],
        'FIELDS_MAPPING': [
            {'expression': '"ID"', 'length': 10, 'name': 'ID', 'precision': 0, 'sub_type': 0, 'type': 4,
             'type_name': 'int8'}],
        'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
    }
    outputs['ac_centerline_id'] = processing.run('native:refactorfields', alg_params)

    # we intersect the active channel layer with the blocks of the valley bottom
    alg_params = {
        'INPUT': selected_layer_ac,
        'OVERLAY': input_blocks_vb,
        'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
    }
    outputs['ac_segmented'] = processing.run('native:intersection', alg_params)

    # we only keep the field 'distance' corresponding to the 'id' of the blocks of the valley bottom
    alg_params = {
        'INPUT': outputs['ac_segmented']['OUTPUT'],
        'FIELDS_MAPPING': [
            {'expression': '"distance"', 'length': 23, 'name': 'distance', 'precision': 15, 'sub_type': 0,
             'type': 6, 'type_name': 'double precision'}],
        'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
    }
    outputs['ac_segmented_distance'] = processing.run('native:refactorfields', alg_params)

    # we calculate the area in m2 of each block of the active channel (with islands)
    alg_params = {
        'INPUT': outputs['ac_segmented_distance']['OUTPUT'],
        'FIELD_NAME': 'area_m2',
        'FIELD_TYPE': 0,
        'FIELD_LENGTH': 0,
        'FIELD_PRECISION': 0,
        'FORMULA': '$area',
        'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
    }
    outputs['ac_segmented_area'] = processing.run('native:fieldcalculator', alg_params)

    # we intersect the active channel layer without islands with the blocks of the valley bottom
    alg_params = {
        'INPUT': outputs['ac_noisland']['OUTPUT'],
        'OVERLAY': input_blocks_vb,
        'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
    }
    outputs['ac_noislands_segmented'] = processing.run('native:intersection', alg_params)

    # we clip the centerline of the active channel with the blocks of the active channel without islands
    alg_params = {
        'INPUT': outputs['ac_centerline_id']['OUTPUT'],
        'OVERLAY': outputs['ac_noislands_segmented']['OUTPUT'],
        'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
    }
    outputs['ac_centerline_segmented'] = processing.run('native:intersection', alg_params)

    # We calculate the length of each segmented centerline of the active channel
    alg_params = {
        'FIELD_LENGTH': 0,
        'FIELD_NAME': 'length_m',
        'FIELD_PRECISION': 0,
        'FIELD_TYPE': 0,  # Flottant
        'FORMULA': ' $length ',
        'INPUT': outputs['ac_centerline_segmented']['OUTPUT'],
        'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
    }
    outputs['ac_centerline_length'] = processing.run('native:fieldcalculator', alg_params)

    # We reorder the columns of the layer of the active channel centerline segmented
    alg_params = {
        'INPUT': outputs['ac_centerline_length']['OUTPUT'],
        'FIELDS_MAPPING': [
            {'expression': '"distance"', 'length': 23, 'name': 'distance', 'precision': 15, 'sub_type': 0,
             'type': 6, 'type_name': 'double precision'},
            {'expression': '"length_m"', 'length': 23, 'name': 'length_m', 'precision': 15, 'sub_type': 0,
             'type': 6, 'type_name': 'double precision'}],
        'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
    }
    outputs['ac_centerline_length_reorder'] = processing.run('native:refactorfields', alg_params)

    # we join the blocks of the active channel (with islands) to the segmented centerlines according
    # to the field 'distance'
    alg_params = {
        'INPUT': outputs['ac_segmented_area']['OUTPUT'],
        'FIELD': 'distance',
        'INPUT_2': outputs['ac_centerline_length_reorder']['OUTPUT'],
        'FIELD_2': 'distance',
        'FIELDS_TO_COPY': ['length_m'],
        'METHOD': 1,
        'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
    }
    outputs['ac_blocks_centerlines'] = processing.run('native:joinattributestable', alg_params)

    # we calculate the mean width (in m) of each block of the active channel
    alg_params = {
        'FIELD_LENGTH': 10,
        'FIELD_NAME': 'mean_width_m',
        'FIELD_PRECISION': 3,
        'FIELD_TYPE': 1,  # Flottant
        'FORMULA': 'value = <area_m2> / <length_m>',
        'GLOBAL': '',
        'INPUT': outputs['ac_blocks_centerlines']['OUTPUT'],
        'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
    }
    outputs['ac_blocks_width'] = processing.run('qgis:advancedpythonfieldcalculator', alg_params)

    # we calculate an 'ID' field
    alg_params = {
        'INPUT': outputs['ac_blocks_width']['OUTPUT'],
        'FIELD_NAME': 'ID',
        'FIELD_TYPE': 1,
        'FIELD_LENGTH': 0,
        'FIELD_PRECISION': 0,
        'FORMULA': '$id',
        'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
    }
    outputs['ac_blocks_id'] = processing.run('native:fieldcalculator', alg_params)

    # we reorder the fields of the layer of the blocks of the active channel and we export the layer
    alg_params = {
        'INPUT': outputs['ac_blocks_id']['OUTPUT'],
        'FIELDS_MAPPING': [
            {'expression': '"ID"', 'length': 10, 'name': 'ID', 'precision': 0, 'sub_type': 0, 'type': 4,
             'type_name': 'int8'},
            {'expression': '"distance"', 'length': 23, 'name': 'distance', 'precision': 15, 'sub_type': 0,
             'type': 6, 'type_name': 'double precision'},
            {'expression': '"area_m2"', 'length': 23, 'name': 'area_m2', 'precision': 15, 'sub_type': 0,
             'type': 6, 'type_name': 'double precision'},
            {'expression': '"length_m"', 'length': 23, 'name': 'length_m', 'precision': 15, 'sub_type': 0,
             'type': 6, 'type_name': 'double precision'},
            {'expression': '"mean_width_m"', 'length': 23, 'name': 'mean_width_m', 'precision': 15, 'sub_type': 0,
             'type': 6, 'type_name': 'double precision'}],
        'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
    }
    outputs['ac_blocks_width'] = processing.run('native:refactorfields', alg_params)

    # we reorder the layer according to the 'distance' field by ascending order
    alg_params = {
        'INPUT': outputs['ac_blocks_width']['OUTPUT'],
        'EXPRESSION':'"distance"',
        'ASCENDING': True,
        'OUTPUT': export_ac
    }
    outputs['ac_blocks_width'] = processing.run('native:orderbyexpression', alg_params)

    # if the exported layer is in format Geopackage, we remove the 'fid' column before exporting the
    # attribute table into a spreadsheet
    if 'gpkg' in export_ac:
        alg_params = {
            'INPUT': outputs['ac_blocks_width']['OUTPUT'],
            'COLUMN': ['fid'],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['ac_blocks_width'] = processing.run('native:deletecolumn', alg_params)

    # We export the attribute table of the layer containing the blocks of the active channel into a csv file
    alg_params = {
        'INPUT': outputs['ac_blocks_width']['OUTPUT'],
        'LAYER_OPTIONS': 'SEPARATOR=SEMICOLON',
        'OUTPUT': export_csv_ac
    }
    outputs['av_csv_exported'] = processing.run('native:savefeatures', alg_params)

    # we load the temporary active channel layer if so wished
    if flag_load_temp_ac == True:
        QgsProject.instance().addMapLayer(outputs['ac_centerline_length_reorder']['OUTPUT']).setName(name_active_channel_centerline)

    # We load the final layer of the blocks of the active channel
    QgsProject.instance().addMapLayer(QgsVectorLayer(export_ac, name_active_channel_blocks, "ogr"))
