# QGIS Plugin Compatibility Helpers
# Copyright (C) 2026  NextGIS
#
# 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 any
# later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, see <https://www.gnu.org/licenses/>.

from typing import TYPE_CHECKING, Any, Dict, List, Set

from qgis.core import (
    Qgis,
    QgsFeature,
    QgsFeatureRequest,
    QgsGeometry,
    QgsMapLayerProxyModel,
    QgsMapLayerType,
    QgsProcessing,
    QgsProcessingParameterField,
    QgsProcessingParameterNumber,
    QgsWkbTypes,
)
from qgis.PyQt.QtCore import QMetaType, QVariant

QGIS_3_30 = 33000
QGIS_3_32 = 33200
QGIS_3_34 = 33400
QGIS_3_36 = 33600
QGIS_3_38 = 33800
QGIS_3_40 = 34000
QGIS_3_42 = 34200
QGIS_3_42_2 = 34202


QgsFeatureId = int
QgsFeatureIds = Set[QgsFeatureId]
QgsFeatureList = List[QgsFeature]

QgsAttributeList = List[int]
QgsAttributeMap = Dict[int, Any]
QgsChangedAttributesMap = Dict[
    QgsFeatureId, Dict[QgsFeatureId, QgsAttributeMap]
]

QgsGeometryMap = Dict[QgsFeatureId, QgsGeometry]


if Qgis.versionInt() >= QGIS_3_30 or TYPE_CHECKING:
    WkbType = Qgis.WkbType  # type: ignore

    GeometryType = Qgis.GeometryType  # type: ignore

    LayerType = Qgis.LayerType  # type: ignore

else:
    WkbType = QgsWkbTypes.Type  # type: ignore

    GeometryType = QgsWkbTypes.GeometryType  # type: ignore
    GeometryType.Point = GeometryType.PointGeometry  # type: ignore
    GeometryType.Point.is_monkey_patched = True
    GeometryType.Line = GeometryType.LineGeometry  # type: ignore
    GeometryType.Line.is_monkey_patched = True
    GeometryType.Polygon = GeometryType.PolygonGeometry  # type: ignore
    GeometryType.Polygon.is_monkey_patched = True
    GeometryType.Unknown = GeometryType.UnknownGeometry  # type: ignore
    GeometryType.Unknown.is_monkey_patched = True
    GeometryType.Null = GeometryType.NullGeometry  # type: ignore
    GeometryType.Null.is_monkey_patched = True

    LayerType = QgsMapLayerType
    LayerType.Vector = QgsMapLayerType.VectorLayer  # type: ignore
    LayerType.Vector.is_monkey_patched = True
    LayerType.Raster = QgsMapLayerType.RasterLayer  # type: ignore
    LayerType.Raster.is_monkey_patched = True
    LayerType.Plugin = QgsMapLayerType.PluginLayer  # type: ignore
    LayerType.Plugin.is_monkey_patched = True
    LayerType.Mesh = QgsMapLayerType.MeshLayer  # type: ignore
    LayerType.Mesh.is_monkey_patched = True
    LayerType.VectorTile = QgsMapLayerType.VectorTileLayer  # type: ignore
    LayerType.VectorTile.is_monkey_patched = True
    LayerType.Annotation = QgsMapLayerType.AnnotationLayer  # type: ignore
    LayerType.Annotation.is_monkey_patched = True
    LayerType.PointCloud = QgsMapLayerType.PointCloudLayer  # type: ignore
    LayerType.PointCloud.is_monkey_patched = True

if Qgis.versionInt() >= QGIS_3_34 or TYPE_CHECKING:
    LayerFilter = Qgis.LayerFilter
    LayerFilters = Qgis.LayerFilters

else:
    LayerFilter = QgsMapLayerProxyModel.Filter
    LayerFilters = QgsMapLayerProxyModel.Filters

if Qgis.versionInt() >= QGIS_3_36 or TYPE_CHECKING:
    FeatureRequestFlag = Qgis.FeatureRequestFlag
    FeatureRequestFlags = Qgis.FeatureRequestFlags

    ProcessingSourceType = Qgis.ProcessingSourceType

    ProcessingNumberParameterType = Qgis.ProcessingNumberParameterType
    ProcessingFieldParameterDataType = Qgis.ProcessingFieldParameterDataType

else:
    FeatureRequestFlag = QgsFeatureRequest.Flag
    FeatureRequestFlags = QgsFeatureRequest.Flags

    ProcessingSourceType = QgsProcessing.SourceType
    ProcessingSourceType.MapLayer = ProcessingSourceType.TypeMapLayer  # type: ignore
    ProcessingSourceType.VectorAnyGeometry = (
        ProcessingSourceType.TypeVectorAnyGeometry
    )  # type: ignore
    ProcessingSourceType.VectorPoint = ProcessingSourceType.TypeVectorPoint  # type: ignore
    ProcessingSourceType.VectorLine = ProcessingSourceType.TypeVectorLine  # type: ignore
    ProcessingSourceType.VectorPolygon = ProcessingSourceType.TypeVectorPolygon  # type: ignore
    ProcessingSourceType.Raster = ProcessingSourceType.TypeRaster  # type: ignore
    ProcessingSourceType.File = ProcessingSourceType.TypeFile  # type: ignore
    ProcessingSourceType.Vector = ProcessingSourceType.TypeVector  # type: ignore
    ProcessingSourceType.Mesh = ProcessingSourceType.TypeMesh  # type: ignore
    ProcessingSourceType.Plugin = ProcessingSourceType.TypePlugin  # type: ignore
    ProcessingSourceType.PointCloud = ProcessingSourceType.TypePointCloud  # type: ignore
    ProcessingSourceType.Annotation = ProcessingSourceType.TypeAnnotation  # type: ignore
    ProcessingSourceType.VectorTile = ProcessingSourceType.TypeVectorTile  # type: ignore

    ProcessingNumberParameterType = QgsProcessingParameterNumber.Type
    ProcessingFieldParameterDataType = QgsProcessingParameterField.DataType


if Qgis.versionInt() >= QGIS_3_38 or TYPE_CHECKING:
    FieldType = QMetaType.Type
else:
    FieldType = QVariant.Type
    FieldType.QString = QVariant.Type.String
    FieldType.QString.is_monkey_patched = True
    FieldType.QDate = QVariant.Type.Date
    FieldType.QDate.is_monkey_patched = True
    FieldType.QTime = QVariant.Type.Time
    FieldType.QTime.is_monkey_patched = True
    FieldType.QDateTime = QVariant.Type.DateTime
    FieldType.QDateTime.is_monkey_patched = True

try:
    from packaging import version

    parse_version = version.parse

except Exception:
    import pkg_resources

    parse_version = pkg_resources.parse_version  # type: ignore
