import os
import shutil

import eel
import geopandas as gpd
from shapely.geometry import Polygon
import matplotlib.pyplot as plt
import folium

@eel.expose
def get_extent_types():
    """Return the list of extends of level layer."""
    return [
        {
            'name': 'Communes',
            'value': 'communes',
            'table': 'communes',
        },
        {
            'name': 'EPCI',
            'value': 'epci',
            'table': 'epci',
        },
        {
            'name': 'EPCI',
            'value': 'pnr',
            'table': 'pnr',
        },
        {
            'name': 'SCOT',
            'value': 'scot',
            'table': 'scot',
        }
    ]

@eel.expose
def get_extents(level='communes'):
    """Return the list of extends of level layer."""
    gdf_level = gpd.read_file("../../data/raster-dl.gpkg", layer=level)
    return gdf_level[['name', 'code']].to_dict(orient='records')


@eel.expose
def get_products(code=None, level=None, buffer=0, bbox=False):
    """Return the list of extends of level layer."""

    if not code or not level:
        return []

    gdf_level = gpd.read_file("../../data/raster-dl.gpkg", layer=level)
    level_feature = gdf_level[gdf_level['code'] == str(code)]
    level_feature = level_feature[['geometry', 'code', 'name']]

    if bbox:
        bbox_feature = get_bbox(level_feature, buffer)
        extent = bbox_feature    
    else:
        level_feature['geometry']= level_feature.buffer(int(buffer))
        bbox_feature = get_bbox(level_feature)
        extent = level_feature

    gdf_products = gpd.read_file("../../data/raster-dl.gpkg", layer='products')
    products_seleted = gpd.sjoin(gdf_products, extent, how='inner', predicate='intersects')
    products_seleted['code'] = products_seleted['code_left']
    products_seleted['name'] = products_seleted['name_left']
    products_seleted = products_seleted[['code', 'name', 'data_extent', 'data_product', 'data_date', 'data_resolution', 'data_compression', 'data_type', 'metadata_url', 'data_directory', 'data_url', 'layer_tiles', 'parent']]

    return products_seleted.to_dict(orient='records')


@eel.expose
def get_map(code=None, level=None, tiles_layer=None, buffer=0, bbox=False):
    """Generate plot map and return the list of extents of level layer."""

    if not code or not level or not tiles_layer:
        return []
    
    gdf_level = gpd.read_file("../../data/raster-dl.gpkg", layer=level)
    level_feature = gdf_level[gdf_level['code'] == code]
    level_feature = level_feature[['geometry', 'code', 'name']]
            
    if bbox:
        bbox_feature = get_bbox(level_feature, buffer)
        extent = bbox_feature    
    else:
        level_feature['geometry']= level_feature.buffer(int(buffer))
        bbox_feature = get_bbox(level_feature)
        extent = level_feature

    gdf_dalles = gpd.read_file("../../data/raster-dl.gpkg", layer=tiles_layer)
    dalles = gdf_dalles[['geometry', 'FILE_IMG', 'DALLE']]
    dalles_seleted = gpd.sjoin(dalles, extent, how='inner', predicate='intersects')

    # Generate plot map
    fig = plt.figure(figsize=(6, 6))
    spec = fig.add_gridspec(ncols=1, nrows=1)
    plot_map = fig.add_subplot(spec[0, 0])
    fig.suptitle('Selection des dalles sur {extent}'.format(extent=extent.iloc[0]['name']))
    level_feature.plot(facecolor='green', edgecolor='black', alpha=0.5, ax=plot_map)
    dalles_seleted.plot(facecolor='red', edgecolor='black', alpha=0.5, ax=plot_map)
    if bbox:
        bbox_feature.plot(facecolor='None', edgecolor='blue', linewidth=2, ax=plot_map)
    plt.axis('off')
    plt.savefig('./web/map.png')
    
    # Generate map html file
    map = level_feature.explore("code", name="extent", cmap=["green"], popup=False, tooltip=False, width=800, height=600, tiles="Stamen Terrain")
    map = dalles_seleted.explore("FILE_IMG", m=map, name="tiles", cmap=["red"], popup=False, tooltip="DALLE", legend=False)
    folium.LayerControl().add_to(map)
    map.save("./web/map.html")   
    
    return dalles_seleted[['DALLE', 'FILE_IMG', 'code']].to_dict(orient='records')
    


def get_bbox(layer, buffer=0):
    x_min, y_min, x_max, y_max = layer.total_bounds
    bbox_polygon = Polygon([(x_min, y_min), (x_max, y_min), (x_max, y_max), (x_min, y_max)])
    level_bbox = gpd.GeoDataFrame({'geometry': [bbox_polygon], 'name': layer.iloc[0]['name'], 'code': layer.iloc[0]['code']}, crs="EPSG:2154")
    level_bbox['geometry']= level_bbox.buffer(int(buffer))
    return level_bbox


def start_eel():
    """Start Eel."""
    
    if os.path.isfile('./web/map.png'):
        # os.remove('./web/map.png')
        shutil.copyfile('./web/empty.png', './web/map.png')

    directory = 'web'
    app = 'chrome-app'
    page = 'index.html'

    eel.init(directory, ['.js', '.html', '.txt', '.htm', '.xhtml'])

    try:
        eel.start(page, mode=app, host='localhost', port=8080, size=(800, 600))
    except EnvironmentError:
        # If Chrome isn't found, fallback to Microsoft Edge on Win10 or greater
        if sys.platform in ['win32', 'win64'] and int(platform.release()) >= 10:
            eel.start(page, mode='edge', host='localhost', port=8080, size=(800, 600))
        else:
            raise


if __name__ == '__main__':
    start_eel()
    