from projektcheck.base.domain import Worker
from .tables import Haltestellen
from projektcheck.domains.definitions.tables import Projektrahmendaten
from projektcheck.utils.spatial import points_within, Point
from projektcheck.settings import settings
from projektcheck.utils.connection import Request
import pandas as pd

requests = Request(synchronous=True)

URL = 'https://sgx.geodatenzentrum.de/wfs_poi_open' #&REQUEST=GetCapabilities


class BKGStops(Worker):
    '''
    worker to scrape and write public stops and number of departures per stop
    '''
    def __init__(self, project, parent=None):
        '''
        Parameters
        ----------
        project : Poject
            the project
        parent : QObject, optional
            parent object of thread, defaults to no parent (global)
        '''
        super().__init__(parent=parent)
        self.project = project
        self.distance = 2000
        self.haltestellen = Haltestellen.features(create=True, project=project)
        self.project_frame = Projektrahmendaten.features(project=project)[0]

    def work(self):
        self.log('Rufe die Haltestellen vom BKG POI Service ab...')

        centroid = self.project_frame.geom.asPoint()
        p_centroid = Point(centroid.x(), centroid.y(),
                           epsg=settings.EPSG)
        df_stops = self.stops_near(p_centroid, max_distance=self.distance)
        df_stops.rename(columns={'verkehrsm': 'verkehrsmittel',
                                 'tag_f_awo': 'abfahrten_pro_tag_arbeitswoche',
                                 'tag_f_wo': 'abfahrten_pro_tag_gesamtwoche',},
                        inplace=True)
        df_stops['geom'] = df_stops['coordinates'].apply(
            lambda c: Point(c[0], c[1], epsg=4326).transform(
                settings.EPSG, inplace=False).geom)
        # only add parent stations
        df_stops = df_stops[df_stops['parent_st'].isna()]
        self.stops_to_db(df_stops)

    def stops_near(self, center, max_distance=2000, n=2000):
        '''
        query closest stations to given point

        Parameters
        ----------
        point : tuple
            x, y values in WGS84 (4326)
        bbox = (1, 2, 3, 4)
        '''
        c_etrs = center.transform(25832)
        p_u = Point(c_etrs[0] - max_distance, c_etrs[1] - max_distance,
                    epsg=25832)
        p_l = Point(c_etrs[0] + max_distance, c_etrs[1] + max_distance,
                    epsg=25832)
        params = {
            'service': 'WFS',
            'version': '2.0.0',
            'request': 'GetFeature',
            'typeNames': 'poi-open:haltestellen',
            'maxFeatures': n,
            'outputFormat': 'json',
            'srsName': 'EPSG:4326',
            'bbox': f'{p_u.x},{p_u.y},{p_l.x},{p_l.y},EPSG:25832'
        }
        res = requests.get(URL, params)
        feats = [{'coordinates': f['geometry']['coordinates']} | f['properties']
                 for f in res.json()['features']]
        return pd.DataFrame.from_dict(feats)

    def stops_to_db(self, df_stops):
        self.haltestellen.delete()
        self.haltestellen.update_pandas(df_stops)
