
import traceback
import numbers
from typing import List, Tuple

from qgis.core import *

from gst.core.inspections.errors import *
from gst.core.inspections.functions import *


def extract_geometry_type_of_vector_layer(
        layer: QgsMapLayer.VectorLayer
) -> Optional[str]:

    if layer.geometryType() == QgsWkbTypes.PointGeometry:
        return "point"
    elif layer.geometryType() == QgsWkbTypes.LineGeometry:
        return "line"
    elif layer.geometryType() == QgsWkbTypes.PolygonGeometry:
        return "polygon"
    else:
        return None


def try_geoms_attrs(
        layer: QgsVectorLayer,
        field_indices: Optional[List[numbers.Integral]] = None
) -> Tuple[bool, Union[str, List[Tuple[QgsGeometry, Tuple]]]]:
    """
    Returns geometry (unchanged) and attributes of (selected) layer records.
    """

    try:

        assert isinstance(layer, QgsVectorLayer)

        if field_indices is None:
            field_indices = []

        records = []

        if layer.selectedFeatureCount() > 0:
            features = layer.selectedFeatures()
        else:
            features = layer.getFeatures()

        for feature in features:

            geom = feature.geometry()

            attrs = feature.fields().toList()
            rec_data = tuple([feature.attribute(attrs[field_ndx].name()) for field_ndx in field_indices])

            records.append((geom, rec_data))

        return True, records

    except Exception as e:

        return False, f"{e!r}"


def extract_selected_geometries(
        layer: QgsVectorLayer,
) -> Tuple[Union[type(None), List[QgsGeometry]], Error]:
    """
    Returns geometry (unchanged) and attributes of (selected) layer records.
    """

    try:

        geometries = []

        if layer.selectedFeatureCount() > 0:
            features = layer.selectedFeatures()
        else:
            features = layer.getFeatures()

        for feature in features:

            geometries.append(feature.geometry())

        return geometries, Error()

    except Exception as e:

        return None, Error(
            True,
            caller_name(),
            e,
            traceback.format_exc()
        )

