// @ts-ignore
import React, {FunctionComponent, useCallback, useEffect, useRef, useState} from "react";
// @ts-ignore
import {Tracker} from "meteor/tracker";
import Google from "/imports/api/Listings/client/init/google_api";
import {GeoJsonPolygon, Point} from "/imports/api/Listings/both/collections/locations";

function geoJsonPolygonToPoints(polygon: GeoJsonPolygon): google.maps.LatLng[] {
    const points = [];

    for (let i = 0; i < polygon.length; i++) {
        const [lng, lat] = polygon[i];
        points.push(new google.maps.LatLng(lat, lng));
    }

    return points;
}

interface SearchLocationMapProps {
    poly: GeoJsonPolygon,
    center: Point,
    onChange: (polygon: GeoJsonPolygon, center: Point | undefined) => void
}

export const AdminSearchLocationMap: FunctionComponent<SearchLocationMapProps> = ({ onChange, poly, center }) => {

    const { current: inst } = useRef<{
        map?: google.maps.Map
        polygon?: google.maps.Polygon
        lastPoint?: google.maps.Marker
        centerMarker?: google.maps.Marker
    }>({});

    const [isSettingCenter, setIsSettingCenter] = useState(false);

    const { polygon, lastPoint, centerMarker } = inst;

    const mapRef = useRef<HTMLDivElement>(null);

    useEffect(() => {
        Tracker.autorun(() => {
            if(Google.ready() && mapRef.current) {
                const [centerLng, centerLat] = center;
                if (!inst.map) {
                    inst.map = new google.maps.Map(mapRef.current, {
                        center: new google.maps.LatLng(centerLat, centerLng),
                        zoom: 6,
                        streetViewControl: false,
                        fullscreenControl: false
                    });
                } else {
                    inst.map.setCenter(new google.maps.LatLng(centerLat, centerLng));
                }
            }
        });
    }, [ center ]);

    useEffect(() => {
        let listenerHandle: google.maps.MapsEventListener;
        if (inst.map) {
            listenerHandle = inst.map.addListener("click", clickHandler);
            if (inst.polygon) {
                inst.polygon.addListener("click", clickHandler);
            }
        }
        return () => {
            if (listenerHandle) {
               google.maps.event.removeListener(listenerHandle);
            }
        }
    }, [ poly, inst.map, inst.polygon, isSettingCenter ]);

    const removeLastPoint = () => {
        const newValue = poly.slice(0);
        newValue.pop();
        onChange(newValue, center);
    };

    const clickHandler = (event: google.maps.MapMouseEvent) => {
        if (event.latLng) {
            const newValue = poly.slice(0);
            let newCenter = center;
            if (isSettingCenter) {
                newCenter = [event.latLng.lng(), event.latLng.lat()] as Point;
            } else {
                newValue.push([event.latLng.lng(), event.latLng.lat()]);
            }
            onChange(newValue, newCenter);
        }
    }

    useEffect(() => {
        if (inst.map) {
            if (polygon) {
                polygon.setMap(null);
            }

            if (lastPoint) {
                lastPoint.setMap(null);
            }

            if (centerMarker) {
                centerMarker.setMap(null);
            }

            if (poly.length) {
                const points = geoJsonPolygonToPoints(poly);
                inst.polygon = new google.maps.Polygon({
                    paths: points,
                    strokeColor: "#FF0000",
                    strokeOpacity: 0.8,
                    strokeWeight: 3,
                    fillColor: "#FF0000",
                    fillOpacity: 0.35,
                    clickable: false
                });

                inst.lastPoint = new google.maps.Marker({
                    position: points[points.length -1],
                    map: inst.map
                });

                inst.polygon.setMap(inst.map);
                inst.lastPoint.setMap(inst.map);
            }

            const [centerLng, centerLat] = center;
            inst.centerMarker = new google.maps.Marker({
                position: new google.maps.LatLng(centerLat, centerLng),
                map: inst.map
            });

            inst.centerMarker.setMap(inst.map);

        }
    }, [ poly.length, inst.map, center ]);

    return (
        <div>
            <button type="button" onClick={removeLastPoint} className="button alert tiny">Delete Last Point</button>
            &nbsp;
            <button type="button" onClick={() => onChange([], center)} className="button alert tiny">Delete Shape</button>
            &nbsp;
            <button type="button" onClick={() => setIsSettingCenter(!isSettingCenter)} className={`button tiny ${isSettingCenter ? "success":"warning"}`}>{isSettingCenter ? "Stop editting Center":"Edit Center"}</button>
            <div style={{ height: 400 }} ref={mapRef} />
        </div>
    );
}