# -*- encoding=utf-8 -*-
"""
useful link : https://docs.qgis.org/3.22/en/docs/user_manual/processing_algs/qgis/vectorgeometry.html
"""
import logging

from qgis.core import QgsVectorLayer
from qgis import processing


def multi_part_to_single_parts_algorithm(layer: QgsVectorLayer) -> QgsVectorLayer:
    params = {'INPUT': layer, 'OUTPUT': 'TEMPORARY_OUTPUT'}
    single_part_layer_copy = processing.run("native:multiparttosingleparts", params)['OUTPUT']
    return single_part_layer_copy


def check_validity_algorithm(layer: QgsVectorLayer) -> int:
    params = {'INPUT_LAYER': layer,
              'VALID_OUTPUT': 'TEMPORARY_OUTPUT',
              'INVALID_OUTPUT': 'TEMPORARY_OUTPUT',
              'ERROR_OUTPUT': 'TEMPORARY_OUTPUT'
              }
    number_of_errors = processing.run("qgis:checkvalidity", params)['ERROR_COUNT']
    return number_of_errors


def snap_points_to_grid_algorithm(layer: QgsVectorLayer, snapping_distance: float) -> QgsVectorLayer:
    params = {'INPUT': layer,
              'HSPACING': snapping_distance,
              'VSPACING': snapping_distance,
              'ZSPACING': snapping_distance,
              'OUTPUT': 'TEMPORARY_OUTPUT'
              }
    snapped_layer = processing.run("native:snappointstogrid", params)['OUTPUT']
    return snapped_layer


def fix_geometries_algorithm(layer: QgsVectorLayer) -> QgsVectorLayer:
    params = {'INPUT': layer, 'OUTPUT': 'TEMPORARY_OUTPUT'}
    layer_with_fixed_geometries = processing.run("native:fixgeometries", params)['OUTPUT']
    return layer_with_fixed_geometries


def drop_mvalue_algorithm(layer: QgsVectorLayer) -> QgsVectorLayer:
    params = {'INPUT': layer,
              'OUTPUT': 'TEMPORARY_OUTPUT',
              'DROP_M_VALUES': True,
              'DROP_Z_VALUES': False
              }
    layer_without_mvalues = processing.run("native:dropmzvalues", params)['OUTPUT']
    return layer_without_mvalues


def process_layer_before_exporting_to_database(layer: QgsVectorLayer) -> QgsVectorLayer:
    logging.info("Preprocessing : fixing invalid geometries")
    fixed_geometries_layer = fix_geometries_algorithm(layer)
    logging.info("Preprocessing : removing mvalues")
    layer_without_mvalues = drop_mvalue_algorithm(fixed_geometries_layer)
    logging.info("Preprocessing : converting multi parts to single parts")
    final_layer = multi_part_to_single_parts_algorithm(layer_without_mvalues)

    # renaming layer
    new_name = f"morpheo_{layer.name()}"
    final_layer.setName(new_name)

    return final_layer

