from qgis.core import (
    QgsProcessing,
    QgsProcessingParameterDistance,
    QgsProcessingParameterFeatureSource,
    QgsProcessingParameterField,
    QgsProcessingParameterFeatureSink,
    QgsProcessingMultiStepFeedback,
)
import processing

from PreCourlis.processing.precourlis_algorithm import PreCourlisAlgorithm


class ImportPointsAlgorithm(PreCourlisAlgorithm):
    TRACKS = "TRACKS"
    TRACKS_FIELD_SEC_ID = "TRACKS_FIELD_SEC_ID"
    AXIS = "AXIS"
    SOURCE_POINTS = "SOURCE_POINTS"
    SOURCE_FIELD_Z = "SOURCE_FIELD_Z"
    BUFFER_DISTANCE = "BUFFER_DISTANCE"
    OUTPUT = "OUTPUT"

    def initAlgorithm(self, config=None):
        self.addParameter(
            QgsProcessingParameterFeatureSource(
                self.TRACKS,
                self.tr("Tracks"),
                types=[QgsProcessing.TypeVectorLine],
                defaultValue=None,
            )
        )
        self.addParameter(
            QgsProcessingParameterField(
                self.TRACKS_FIELD_SEC_ID,
                self.tr("Tracks unique identifier field"),
                parentLayerParameterName=self.TRACKS,
                defaultValue="sec_id",
            )
        )
        self.addParameter(
            QgsProcessingParameterFeatureSource(
                self.AXIS,
                self.tr("Axis"),
                types=[QgsProcessing.TypeVectorLine],
                defaultValue=None,
            )
        )
        self.addParameter(
            QgsProcessingParameterFeatureSource(
                self.SOURCE_POINTS,
                self.tr("Source points"),
                types=[QgsProcessing.TypeVectorPoint],
                defaultValue=None,
            )
        )
        self.addParameter(
            QgsProcessingParameterField(
                self.SOURCE_FIELD_Z,
                self.tr("Source Z field"),
                parentLayerParameterName=self.SOURCE_POINTS,
                defaultValue=None,
            )
        )
        self.addParameter(
            QgsProcessingParameterDistance(
                self.BUFFER_DISTANCE,
                self.tr("Buffer distance"),
                parentParameterName="profils",
                minValue=0.0,
                maxValue=1000.0,
                defaultValue=10.0,
            )
        )
        self.addParameter(
            QgsProcessingParameterFeatureSink(
                self.OUTPUT,
                self.tr("Sections"),
                type=QgsProcessing.TypeVectorLine,
                createByDefault=True,
                defaultValue=None,
            )
        )

    def processAlgorithm(self, parameters, context, model_feedback):
        feedback = QgsProcessingMultiStepFeedback(8, model_feedback)
        outputs = {}

        # join_points_to_profiles
        alg_params = {
            "SOURCE_POINTS": parameters[self.SOURCE_POINTS],
            "TARGET_PROFILES": parameters[self.TRACKS],
            "TARGET_PROFILES_FIELD_SEC_ID": parameters[self.TRACKS_FIELD_SEC_ID],
            "BUFFER_DISTANCE": parameters[self.BUFFER_DISTANCE],
            "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
        }
        outputs["JoinPointsToProfiles"] = processing.run(
            "precourlis:join_points_to_profiles",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )
        joined_points = outputs["JoinPointsToProfiles"]["OUTPUT"]

        feedback.setCurrentStep(1)
        if feedback.isCanceled():
            return {}

        # import_prepared_points
        alg_params = {
            "TRACKS": parameters[self.TRACKS],
            "TRACKS_FIELD_SEC_ID": parameters[self.TRACKS_FIELD_SEC_ID],
            "AXIS": parameters[self.AXIS],
            "SOURCE_POINTS": joined_points,
            "SOURCE_FIELD_SEC_ID": "sec_name",
            "SOURCE_FIELD_Z": parameters[self.SOURCE_FIELD_Z],
            "OUTPUT": parameters[self.OUTPUT],
        }
        outputs["ImportPreparedPoints"] = processing.run(
            "precourlis:import_prepared_points",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )
        imported_points = outputs["ImportPreparedPoints"]["OUTPUT"]

        return {"OUTPUT": imported_points}

    def name(self):
        return "import_points"

    def displayName(self):
        return self.tr("Import points by projection on tracks")

    def group(self):
        return self.tr("Import")

    def groupId(self):
        return "Import"

    def createInstance(self):
        return ImportPointsAlgorithm()

    def shortHelpString(self):
        return self.tr(
            "This algorithm create a new profiles layer from:"
            "\n- Tracks"
            "\n- Source points with elevation"
            "\n\n"
            "using a buffer to join points to tracks"
            " and then projecting points on tracks."
        )
