# -*- coding: utf-8 -*-

"""
/***************************************************************************
 AerodromeUtilities
                                 A QGIS plugin
 Fetches OSM Data and processes it for aerodroms with various algorithms
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                              -------------------
        begin                : 2024-09-08
        copyright            : (C) 2024 by Aiden Omondi
        email                : helpertech83@gmail.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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__ = 'Aiden Omondi'
__date__ = '2024-09-08'
__copyright__ = '(C) 2024 by Aiden Omondi'

# This will get replaced with a git SHA1 when you do a git archive

__revision__ = '$Format:%H$'

import processing
from qgis.PyQt.QtCore import QCoreApplication, QVariant
from qgis.core import (
	QgsProcessingAlgorithm, 
	QgsProcessingParameterFeatureSource, 
	QgsProcessingParameterFeatureSink,
	QgsFeatureSink,
	QgsProcessingUtils,
	QgsVectorLayer,
	QgsField,
)
from qgis.PyQt.QtGui import QColor


class PolygonToSinglePartLinesAlgorithm(QgsProcessingAlgorithm):

	INPUT = 'INPUT'
	OUTPUT = 'OUTPUT'

	def initAlgorithm(self, config=None):
		self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT, 'Input Polygon Layer'))
		self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, 'Output Line Layer'))

	def processAlgorithm(self, parameters, context, feedback):
		# Retrieve the input layer
		layer = self.parameterAsSource(parameters, self.INPUT, context)
		layer_source = self.parameterAsString(parameters, self.INPUT, context)
		map_layer = QgsProcessingUtils.mapLayerFromString(
			layer_source, context)
		
		color = None
		ts_color = None
		gr_color = None

		if map_layer:
			color = map_layer.customProperty('color', None)
			ts_color = map_layer.customProperty('ts_color', None)
			gr_color = map_layer.customProperty('gr_color', None)
		
		if layer is None:
			feedback.reportError('Could not load input layer!')
			return {}
		
		feedback.pushInfo(f'Input layer loaded: {layer.sourceName()}')

		layer_source = self.parameterAsString(parameters, self.INPUT, context)
		# Convert polygons to lines
		feedback.pushInfo('Converting polygons to lines...')
		lines_layer = processing.run("qgis:polygonstolines", {
			'INPUT': layer_source,
			'OUTPUT': 'memory:'
		}, context=context, feedback=feedback)['OUTPUT']
		
		if lines_layer is None:
			feedback.reportError('Polygon to line conversion failed!')
			return {}
		
		# Convert multipart lines to single parts
		feedback.pushInfo('Converting multipart geometries to single parts...')
		single_parts_layer: QgsVectorLayer | None = processing.run("qgis:multiparttosingleparts", {
			'INPUT': lines_layer,
			'OUTPUT': 'memory:'
		}, context=context, feedback=feedback)['OUTPUT']
		
		if single_parts_layer is None:
			feedback.reportError('Multipart to single-part conversion failed!')
			return {}
		
		single_parts_layer.startEditing()

		# Check if 'fid' exists, if not, add it
		fid_idx = single_parts_layer.fields().indexFromName("fid")
		if fid_idx == -1:
			single_parts_layer.dataProvider().addAttributes([QgsField("fid", QVariant.Int)])
			single_parts_layer.updateFields()
			fid_idx = single_parts_layer.fields().indexFromName("fid")

		# Assign new unique fids
		new_fid = 1
		for feature in single_parts_layer.getFeatures():
			feature.setAttribute(fid_idx, new_fid)  # Assign new fid
			single_parts_layer.updateFeature(feature)  # Update the feature in the layer
			new_fid += 1

		single_parts_layer.commitChanges()

		# Output the final single-part line layer
		(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
											   single_parts_layer.fields(), single_parts_layer.wkbType(), single_parts_layer.sourceCrs())

		for feature in single_parts_layer.getFeatures():
			sink.addFeature(feature, QgsFeatureSink.FastInsert)

		output_layer = QgsProcessingUtils.mapLayerFromString(dest_id, context)

		if output_layer and color:
			output_layer.setCustomProperty('color', color)
			output_layer.setCustomProperty('ts_color', ts_color)
			output_layer.setCustomProperty('gr_color', gr_color)
			color_comp = color.split(",")
			color_ints = list(map(int, color_comp))
			output_layer.renderer().symbol().setColor(
				QColor().fromRgb(color_ints[0], color_ints[1], color_ints[2]))

		feedback.pushInfo('Algorithm completed successfully.')
		return {self.OUTPUT: dest_id}
	
	def name(self):
		"""
		Returns the algorithm name, used for identifying the algorithm. This
		string should be fixed for the algorithm, and must not be localised.
		The name should be unique within each provider. Names should contain
		lowercase alphanumeric characters only and no spaces or other
		formatting characters.
		"""
		return 'polygontosinglepart'

	def displayName(self):
		"""
		Returns the translated algorithm name, which should be used for any
		user-visible display of the algorithm name.
		"""
		return 'Polygon To Singlepart'

	def group(self):
		"""
		Returns the name of the group this algorithm belongs to. This string
		should be localised.
		"""
		return self.tr(self.groupId())

	def groupId(self):
		"""
		Returns the unique ID of the group this algorithm belongs to. This
		string should be fixed for the algorithm, and must not be localised.
		The group id should be unique within each provider. Group id should
		contain lowercase alphanumeric characters only and no spaces or other
		formatting characters.
		"""
		return ''
	
	def tr(self, string):
		return QCoreApplication.translate('Processing', string)

	def createInstance(self):
		return PolygonToSinglePartLinesAlgorithm()
