
from typing import List, Union, Tuple

import numbers

from qgis.core import QgsVectorLayer

from gst.core.inspections.errors import *


def field_values(
    layer,
    curr_field_ndx: numbers.Integral
):

    values = []

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

    for feature in features:
        values.append(feature.attributes()[curr_field_ndx])

    return values


def extract_vector_attributes(
    layer,
    field_list
):
    """
    Probably to deprecate in favour of 'extract_layer_attributes'
    """

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

    provider = layer.dataProvider()
    field_indices = [provider.fieldNameIndex(field_name) for field_name in field_list]

    # retrieve (selected) attributes features
    data_list = []
    for feature in features:
        attrs = feature.fields().toList()
        data_list.append([feature.attribute(attrs[field_ndx].name()) for field_ndx in field_indices])

    return data_list


def extract_layer_attributes(
        layer: QgsVectorLayer,
        fields: List[str]
) -> List:
    """
    Get attributes from layer based on provided field names list.

    :param layer: the source layer for attribute extraction.
    :param fields: a list of field names for attribute extraction.
    :return: list of table values.
    """

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

    provider = layer.dataProvider()
    field_indices = [provider.fieldNameIndex(field_name) for field_name in fields]

    # retrieve selected features with relevant attributes

    rec_list = []

    for feature in features:

        attrs = feature.fields().toList()

        # creates feature attribute list

        feat_list = []
        for field_ndx in field_indices:
            feat_list.append(feature.attribute(attrs[field_ndx].name()))

        # add to result list

        rec_list.append(feat_list)

    return rec_list


def extract_point_layer_geometries_and_attributes(
        layer: QgsVectorLayer,
        fields: List[str]
) -> Tuple[Union[None, List], Error]:
    """
    Get attributes from point layer based on provided field names list.

    :param layer: the source layer for attribute extraction.
    :param fields: a list of field names for attribute extraction.
    :return: list of table values.
    """

    try:

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

        provider = layer.dataProvider()
        field_indices = [provider.fieldNameIndex(field_name) for field_name in fields]

        # retrieve selected features with relevant attributes

        rec_list = []

        for point in points:

            qgs_point_xy = point.geometry().asPoint()
            attrs = point.fields().toList()

            # creates feature attribute list

            feat_list = [qgs_point_xy.x(), qgs_point_xy.y()]
            for field_ndx in field_indices:
                feat_list.append(point.attribute(attrs[field_ndx].name()))

            # add to result list

            rec_list.append(feat_list)

        return rec_list, Error()

    except Exception as e:

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