# -------------------------------------------------------------------------------- NOTEBOOK-CELL: CODE
# -*- coding: utf-8 -*-
import dataiku
import pandas as pd, numpy as np
from dataiku import pandasutils as pdu

# -------------------------------------------------------------------------------- NOTEBOOK-CELL: CODE
import json

# -------------------------------------------------------------------------------- NOTEBOOK-CELL: CODE
from distribution_spatial_footprint.isochrones import IsochronesManager
from distribution_spatial_footprint.utils import (from_minutes_to_seconds,
                                                  from_seconds_to_minutes,
                                                  prettify_isochrone_label)
from distribution_spatial_footprint.geographic_handling import (compute_circular_polygon,
                                                                from_polygon_coordinates_to_geojson,
                                                                convert_from_geojson_to_list_polygon,
                                                                convert_polygon_from_list_to_shapely,
                                                                convert_polygon_from_shapely_to_wkt_string)
from dku_utils import get_current_project_and_variables

# -------------------------------------------------------------------------------- NOTEBOOK-CELL: CODE
project, variables = get_current_project_and_variables()
global_variables = variables["standard"]

# -------------------------------------------------------------------------------- NOTEBOOK-CELL: CODE
api_key = global_variables["api_key"]
isochrones_api_to_use = global_variables["isochrones_api_to_use"]
isochrones_api_parameters = global_variables[isochrones_api_to_use]
transportation_mode = isochrones_api_parameters["transportation_mode"]
isochrones_api_provides_attributes = (len(isochrones_api_parameters["isochrones_attributes"]) > 0)
isochrones_range_min = global_variables["isochrones_range_min"]
isochrones_max_amplitude = max(isochrones_range_min)

# -------------------------------------------------------------------------------- NOTEBOOK-CELL: CODE
# Read recipe inputs
locations_prepared = dataiku.Dataset("locations_prepared")
locations_prepared_df = locations_prepared.get_dataframe()

# -------------------------------------------------------------------------------- NOTEBOOK-CELL: CODE
locations_identifiers = list(locations_prepared_df["location_identifier"])

# -------------------------------------------------------------------------------- NOTEBOOK-CELL: MARKDOWN
# # Isochrones computation

# -------------------------------------------------------------------------------- NOTEBOOK-CELL: CODE
isochrones_manager = IsochronesManager(isochrones_api_to_use, api_key, transportation_mode, isochrones_range_min,
                                       isochrones_api_parameters)

# -------------------------------------------------------------------------------- NOTEBOOK-CELL: CODE
latitudes = list(locations_prepared_df["latitude"])
longitudes = list(locations_prepared_df["longitude"])

# -------------------------------------------------------------------------------- NOTEBOOK-CELL: CODE
isochrones = isochrones_manager.compute_isochrones_geojsons(latitudes, longitudes)

# -------------------------------------------------------------------------------- NOTEBOOK-CELL: CODE
if isochrones_api_provides_attributes:
    isochrones_attributes_to_extract = isochrones_manager.isochrones_attributes

for isochrone_amplitude in isochrones.keys():
    if isochrones_api_provides_attributes:
        isochrone_amplitude_attributes = {attribute:[] for attribute in isochrones_attributes_to_extract}
    isochrone_amplitude_radiuses = []
    isochrones_focus = isochrones[isochrone_amplitude]

    for isochrone_index, zip_data in enumerate(zip(isochrones_focus, locations_identifiers, longitudes, latitudes)):
        isochrone_geojson = zip_data[0]
        isochrone_location = zip_data[1]
        isochrone_center_longitude = zip_data[2]
        isochrone_center_latitude = zip_data[3]
        isochrone_polygon = isochrone_geojson["geometry"]["coordinates"]

        isochrone_has_no_geojson = (isochrone_polygon == [[]])
        if isochrone_has_no_geojson:
            isochrone_radius = 0
        else:
            isochrone_radius = isochrones_manager.compute_isochrone_radius(isochrone_geojson,
                                                                           isochrone_center_longitude,
                                                                           isochrone_center_latitude)
        isochrone_amplitude_radiuses.append(isochrone_radius)
        isochrone_attributes = isochrones_manager.extract_isochrone_attributes(isochrone_geojson)
        if isochrones_api_provides_attributes:
            for attribute in isochrones_attributes_to_extract:
                isochrone_amplitude_attributes[attribute].append(isochrone_attributes[attribute])

    locations_prepared_df[f"isochrone_{isochrone_amplitude}_min"] = isochrones[isochrone_amplitude]
    locations_prepared_df[f"isochrone_{isochrone_amplitude}_min_radius"] = isochrone_amplitude_radiuses

    if isochrones_api_provides_attributes:
        for attribute in isochrones_attributes_to_extract:
            locations_prepared_df["isochrone_{}_min_{}".format(isochrone_amplitude, attribute)] = \
            isochrone_amplitude_attributes[attribute]

# -------------------------------------------------------------------------------- NOTEBOOK-CELL: CODE
# Webapp | Location id :
locations_prepared_df["location_id"] = range(len(locations_prepared_df))

# -------------------------------------------------------------------------------- NOTEBOOK-CELL: CODE
isochrones_types = ["isochrone_{}_min".format(isochrone_amplitude) for isochrone_amplitude in isochrones_range_min]

# -------------------------------------------------------------------------------- NOTEBOOK-CELL: CODE
locations_isochrones_denormalized_df = pd.DataFrame(columns=["isochrone_id", "location_id",
                                                             "location_geo_point", "isochrone_amplitude",
                                                             "isochrone_type","isochrone_label", "isochrone_data"])

# -------------------------------------------------------------------------------- NOTEBOOK-CELL: CODE
denormalization_columns = ["location_id", "geo_point"] + isochrones_types

# -------------------------------------------------------------------------------- NOTEBOOK-CELL: CODE
for row in locations_prepared_df[denormalization_columns].iterrows():
    row_data = row[1]
    location_id = row_data["location_id"]
    location_geo_point = row_data["geo_point"]

    for isochrone_amplitude, isochrone_type in zip(isochrones_range_min, isochrones_types):
        isochrone_id = "{}_{}".format(location_id, isochrone_amplitude)
        isochrone_geojson = row_data[isochrone_type]
        list_polygon = convert_from_geojson_to_list_polygon(isochrone_geojson)
        shapely_polygon = convert_polygon_from_list_to_shapely(list_polygon, False)
        wkt_polygon = convert_polygon_from_shapely_to_wkt_string(shapely_polygon, False)
        locations_isochrones_denormalized_df =\
        locations_isochrones_denormalized_df.append({"isochrone_id":isochrone_id,
                                                     "location_id":location_id,
                                                     "location_geo_point":location_geo_point,
                                                     "isochrone_amplitude":isochrone_amplitude,
                                                     "isochrone_type":isochrone_type,
                                                     "isochrone_label":prettify_isochrone_label(isochrone_type),
                                                     "isochrone_data":isochrone_geojson,
                                                     "isochrone_data_wkt": wkt_polygon
                                                    },
                                                    ignore_index=True)

# -------------------------------------------------------------------------------- NOTEBOOK-CELL: CODE
for isochrone_amplitude in isochrones.keys():
    locations_prepared_df[f"isochrone_{isochrone_amplitude}_min"] =\
    locations_prepared_df[f"isochrone_{isochrone_amplitude}_min"].apply(lambda x: json.dumps(x))

# -------------------------------------------------------------------------------- NOTEBOOK-CELL: CODE
locations_isochrones = dataiku.Dataset("locations_isochrones")
locations_isochrones.write_with_schema(locations_prepared_df)

# -------------------------------------------------------------------------------- NOTEBOOK-CELL: CODE
locations_isochrones_denormalized_df["isochrone_data"] =\
locations_isochrones_denormalized_df["isochrone_data"].apply(lambda x: json.dumps(x))

# -------------------------------------------------------------------------------- NOTEBOOK-CELL: CODE
locations_isochrones_denormalized = dataiku.Dataset("locations_isochrones_denormalized")
locations_isochrones_denormalized.write_with_schema(locations_isochrones_denormalized_df)