import numpy as np
from itertools import compress
from geopandas import points_from_xy
from scipy.spatial import Voronoi, voronoi_plot_2d
from scipy.spatial.distance import cdist

def extract(lst, i):
    return [item[i] for item in lst]

def extract_coord(lst):
    return [item.coords[:] for item in lst]


def coord_lister(geom):
    coords = list(geom.exterior.coords)
    return (coords)

def find_lec_for_polygon(points, polygon):
    voronoi = Voronoi(points, furthest_site=False)
    furthest_pnt = voronoi.vertices

    voronoi_nodes = points_from_xy(extract(furthest_pnt, 0), extract(furthest_pnt, 1))
    voronoi_nodes_if_inside = polygon.contains(voronoi_nodes)
    voronoi_nodes = list(compress(voronoi_nodes, voronoi_nodes_if_inside))
    leccc = [item for sublist in extract_coord(voronoi_nodes) for item in sublist]

    dist = cdist(np.array([list(item) for item in points]), np.array([list(item) for item in leccc]))
    voronoi_nodes_dist = [min(dist[:, j]) for j in range(dist.shape[1])]
    lecc_ind = np.argmax(voronoi_nodes_dist)
    lecc = leccc[lecc_ind]
    lecc_dist = np.max(voronoi_nodes_dist)

    return lecc, lecc_dist

def get_lecc(shp):
    polygons_coord = [coord_lister(geom) for geom in shp.geometry]

    with ProcessPoolExecutor() as executor:
        results = list(executor.map(find_lec_for_polygon, polygons_coord, shp.geometry))

    lecc, lecc_dist = zip(*results)
    return lecc, lecc_dist