
from qgis.core import *

from gst.core.geometries.lines import *


def qgis_project_coords(
        x: float,
        y: float,
        src_crs: QgsCoordinateReferenceSystem = None,
        dest_crs:Optional[QgsCoordinateReferenceSystem] = None
) -> Tuple[Union[None, Tuple[float, float], Error]]:
    """
    Project a pair of x-y coordinates to a new projection.
    If the source/destination CRS is not provided, it will be set to EPSG 4236 (WGS-84).

    :param x: the x coordinate.
    :param y: the y coordinate.
    :param src_crs: the source coordinate.
    :param dest_crs: the destination coordinate.
    :return: the projected x-y coordinates.
    """

    try:

        if not src_crs:
            src_crs = QgsCoordinateReferenceSystem("EPSG:4326")

        if not dest_crs:
            dest_crs = QgsCoordinateReferenceSystem("EPSG:4326")

        context = QgsCoordinateTransformContext()
        context.addCoordinateOperation(
            src_crs,
            dest_crs,
            "",
        )

        coordinate_transform = QgsCoordinateTransform(
            src_crs,
            dest_crs,
            context)

        qgs_pt = coordinate_transform.transform(
            x,
            y)

        x, y = qgs_pt.x(), qgs_pt.y()

        return (x, y), Error()

    except Exception as e:

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


def qgs_project_xy(
        x: float,
        y: float,
        src_crs: QgsCoordinateReferenceSystem = None,
        dest_crs:Optional[QgsCoordinateReferenceSystem] = None
) -> Tuple[float, float]:
    """
    DEPRECATED. Use 'qgis_project_coords'
    Project a pair of x-y coordinates to a new projection.
    If the source/destination CRS is not provided, it will be set to EPSG 4236 (WGS-84).

    :param x: the x coordinate.
    :param y: the y coordinate.
    :param src_crs: the source coordinate.
    :param dest_crs: the destination coordinate.
    :return: the projected x-y coordinates.
    """

    if not src_crs:
        src_crs = QgsCoordinateReferenceSystem("EPSG:4326")

    if not dest_crs:
        dest_crs = QgsCoordinateReferenceSystem("EPSG:4326")

    context = QgsCoordinateTransformContext()
    context.addCoordinateOperation(
        src_crs,
        dest_crs,
        "",
    )

    coordinate_transform = QgsCoordinateTransform(
        src_crs,
        dest_crs,
        context)

    qgs_pt = coordinate_transform.transform(
        x,
        y)

    x, y = qgs_pt.x(), qgs_pt.y()

    return x, y


def project_qgs_point(
        qgsPt,
        srcCrs,
        destCrs
):
    return QgsCoordinateTransform(srcCrs, destCrs, QgsProject.instance()).transform(qgsPt)


def project_line_2d(srcLine, srcCrs, destCrs):

    destLine = Ln()

    for pt in srcLine._pts:

        srcPt = QgsPointXY(
            pt._x,
            pt._y
        )

        destPt = project_qgs_point(
            srcPt,
            srcCrs,
            destCrs
        )

        destLine = destLine.add_pt(
            Point(
                destPt.x(),
                destPt.y()
            )
        )

    return destLine
