<reponame>bcgov-c/wally
import json
import logging
from sqlalchemy import text, func
from sqlalchemy.orm import Session

from api.layers.first_nations import CommunityLocations, TreatyAreas, TreatyLands
from api.v1.firstnations.schema import (
    Community as CommunityResponse,
    TreatyAreas as TreatyAreasResponse,
    TreatyLands as TreatyLandsResponse,
    NearbyAreasResponse
)
logger = logging.getLogger("api")

# arbitrary maximum radius (in metres) to search within.
# in the future, this could be a user-configurable option.
MAX_RADIUS = 50000


def get_nearest_communities(db: Session, geometry):
    """ get nearest First Nations Community Locations"""

    community_q = db.query(
        CommunityLocations,
        func.ST_Distance(func.Geography(CommunityLocations.SHAPE),
                         func.ST_GeographyFromText(geometry.wkt)).label('distance')
    ) \
        .filter(
            func.ST_DWithin(func.Geography(CommunityLocations.SHAPE),
                            func.ST_GeographyFromText(geometry.wkt), MAX_RADIUS)
    ) \
        .order_by('distance')

    community_results = community_q.all()

    return [CommunityResponse(
        **row[0].__dict__, distance=row[1]) for row in community_results]


def get_nearest_treaty_lands(db: Session, geometry):
    """ gets nearest First Nations Treaty Lands """

    land_q = db.query(
        TreatyLands,
        func.ST_Distance(func.Geography(TreatyLands.SHAPE),
                         func.ST_GeographyFromText(geometry.wkt)).label('distance')
    ) \
        .filter(
        func.ST_DWithin(func.Geography(TreatyLands.SHAPE),
                        func.ST_GeographyFromText(geometry.wkt), MAX_RADIUS)
    ) \
        .order_by('distance')
    land_results = land_q.all()

    return [TreatyLandsResponse(**row[0].__dict__, distance=row[1])
            for row in land_results]


def get_nearest_treaty_areas(db: Session, geometry):
    """ gets the nearest First Nations Treaty Areas """
    area_q = db.query(
        TreatyAreas,
        func.ST_Distance(func.Geography(TreatyAreas.SHAPE),
                         func.ST_GeographyFromText(geometry.wkt)).label('distance')
    ) \
        .filter(
        func.ST_DWithin(func.Geography(TreatyAreas.SHAPE),
                        func.ST_GeographyFromText(geometry.wkt), MAX_RADIUS)
    ) \
        .order_by('distance')
    area_results = area_q.all()

    return [TreatyAreasResponse(**row[0].__dict__, distance=row[1])
            for row in area_results]


def get_nearest_locations(db: Session, geometry):
    """
    returns the nearest areas and locations from the following datasets (available on DataBC):
    First Nations Community Locations
    First Nations Treaty Lands
    First Nations Treaty Areas
    """
    return NearbyAreasResponse(
        nearest_communities=get_nearest_communities(db, geometry),
        nearest_treaty_areas=get_nearest_treaty_areas(db, geometry),
        nearest_treaty_lands=get_nearest_treaty_lands(db, geometry)
    )

import json
import logging
from sqlalchemy import text, func
from sqlalchemy.orm import Session

from api.layers.first_nations import CommunityLocations, TreatyAreas, TreatyLands
from api.v1.firstnations.schema import (
    Community as CommunityResponse,
    TreatyAreas as TreatyAreasResponse,
    TreatyLands as TreatyLandsResponse,
    NearbyAreasResponse
)
logger = logging.getLogger("api")

# arbitrary maximum radius (in metres) to search within.
# in the future, this could be a user-configurable option.
MAX_RADIUS = 50000


def get_nearest_communities(db: Session, geometry):
    """ get nearest First Nations Community Locations"""

    community_q = db.query(
        CommunityLocations,
        func.ST_Distance(func.Geography(CommunityLocations.SHAPE),
                         func.ST_GeographyFromText(geometry.wkt)).label('distance')
    ) \
        .filter(
            func.ST_DWithin(func.Geography(CommunityLocations.SHAPE),
                            func.ST_GeographyFromText(geometry.wkt), MAX_RADIUS)
    ) \
        .order_by('distance')

    community_results = community_q.all()

    return [CommunityResponse(
        **row[0].__dict__, distance=row[1]) for row in community_results]


def get_nearest_treaty_lands(db: Session, geometry):
    """ gets nearest First Nations Treaty Lands """

    land_q = db.query(
        TreatyLands,
        func.ST_Distance(func.Geography(TreatyLands.SHAPE),
                         func.ST_GeographyFromText(geometry.wkt)).label('distance')
    ) \
        .filter(
        func.ST_DWithin(func.Geography(TreatyLands.SHAPE),
                        func.ST_GeographyFromText(geometry.wkt), MAX_RADIUS)
    ) \
        .order_by('distance')
    land_results = land_q.all()

    return [TreatyLandsResponse(**row[0].__dict__, distance=row[1])
            for row in land_results]


def get_nearest_treaty_areas(db: Session, geometry):
    """ gets the nearest First Nations Treaty Areas """
    area_q = db.query(
        TreatyAreas,
        func.ST_Distance(func.Geography(TreatyAreas.SHAPE),
                         func.ST_GeographyFromText(geometry.wkt)).label('distance')
    ) \
        .filter(
        func.ST_DWithin(func.Geography(TreatyAreas.SHAPE),
                        func.ST_GeographyFromText(geometry.wkt), MAX_RADIUS)
    ) \
        .order_by('distance')
    area_results = area_q.all()

    return [TreatyAreasResponse(**row[0].__dict__, distance=row[1])
            for row in area_results]


def get_nearest_locations(db: Session, geometry):
    """
    returns the nearest areas and locations from the following datasets (available on DataBC):
    First Nations Community Locations
    First Nations Treaty Lands
    First Nations Treaty Areas
    """
    return NearbyAreasResponse(
        nearest_communities=get_nearest_communities(db, geometry),
        nearest_treaty_areas=get_nearest_treaty_areas(db, geometry),
        nearest_treaty_lands=get_nearest_treaty_lands(db, geometry)
    )
# arbitrary maximum radius (in metres) to search within. # in the future, this could be a user-configurable option. get nearest First Nations Community Locations gets nearest First Nations Treaty Lands gets the nearest First Nations Treaty Areas returns the nearest areas and locations from the following datasets (available on DataBC):     First Nations Community Locations     First Nations Treaty Lands     First Nations Treaty Areas