import { GoogleMap, Marker, InfoWindow, InfoBox, LoadScript, GoogleMapProps, StandaloneSearchBox, DrawingManager } from '@react-google-maps/api';
import { observable, action, computed, Lambda, runInAction } from "mobx";
import { observer } from "mobx-react";
import { Doc, DocListCast, Field, FieldResult, Opt } from "../../../../fields/Doc";
import { documentSchema } from "../../../../fields/documentSchemas";
import { Id } from "../../../../fields/FieldSymbols";
import { makeInterface } from "../../../../fields/Schema";
import { Cast, NumCast, ScriptCast, StrCast } from "../../../../fields/Types";
import { LinkManager } from "../../../util/LinkManager";
import { undoBatch, UndoManager } from "../../../util/UndoManager";
import "./CollectionMapView.scss";
import { CollectionSubView } from "../CollectionSubView";
import React = require("react");
import requestPromise = require("request-promise");
import ReactDOM from 'react-dom';


type MapSchema = makeInterface<[typeof documentSchema]>;
const MapSchema = makeInterface(documentSchema);

export type LocationData = {
    id?: number;
    pos?: { lat: number, lng: number };
};

const mapContainerStyle = {
    height: '100%',
};

const defaultCenter = {
    lat: 38.685,
    lng: -115.234,
};

@observer
export default class CollectionMapView extends CollectionSubView<MapSchema, GoogleMapProps>(MapSchema) {

    @observable private mapRef = null as any;
    @observable private selectedPlace: LocationData = { id: undefined, pos: undefined };
    @observable private markerMap = {};
    @observable private center = defaultCenter;
    @observable private zoom = 2.5;
    @observable private clickedLatLng = null;
    @observable private infoWindowOpen = false;

    @observable private myPlaces = [
        { id: 1, pos: { lat: 39.09366509575983, lng: -94.58751660204751 } },
        { id: 2, pos: { lat: 41.82399, lng: -71.41283 } },
        { id: 3, pos: { lat: 47.606214, lng: -122.33207 } },
        { id: 4, pos: { lat: 36.7783, lng: 119.4179 } }
    ];

    // iterate myPlaces to size, center, and zoom map to contain all markers
    private fitBounds = (map: any) => {
        const bounds = new window.google.maps.LatLngBounds();
        console.log('map bound is:' + bounds);
        this.myPlaces.map(place => {
            bounds.extend(place.pos);
            return place.id;
        });
        map.fitBounds(bounds)
    }

    // store a reference to google map instance; fit map bounds to contain all markers
    @action
    private loadHandler = (map: any) => {
        this.mapRef = map;
        this.fitBounds(map);

        // //add a custom control for button add marker 
        // //TODO: why this doesn't work
        // const google = window.google;
        // console.log("google window: " + google)
        // const controlButtonDiv = document.createElement('div');
        // ReactDOM.render(<button onClick={() => console.log('click me to add marker!')}>Add Marker</button>, controlButtonDiv);
        // map.controls[google.maps.ControlPosition.TOP_RIGHT].push(controlButtonDiv);
    }

    @action
    private markerClickHandler = (e: MouseEvent, place: LocationData) => {
        // set which place was clicked
        this.selectedPlace = place

        console.log(this.selectedPlace.id);
        console.log(this.selectedPlace.pos);

        // used so clicking a second marker works
        if (this.infoWindowOpen) {
            this.infoWindowOpen = false;
        }

        this.infoWindowOpen = true;
    }

    @action
    private handleInfoWindowClose = () => {
        if (this.infoWindowOpen) {
            this.infoWindowOpen = false;
        }
        this.infoWindowOpen = false;
        this.selectedPlace = { id: undefined, pos: undefined };
    }

    // @action 
    // private markerLoadHandler = (marker: any, place: LocationData) => {
    //     if (marker != null) {
    //         this.markerMap[place.id] = marker;
    //     }
    // }

    @action
    @undoBatch
    private handleDragMarker = (marker: any, place: LocationData) => {
        if (marker != null) {
            place = {
                id: place.id,
                pos: {
                    lat: marker.latLng.lat().toFixed(3),
                    lng: marker.latLng.lng().toFixed(3)
                }
            }

            console.log(place);
            console.log(this.myPlaces);
        }
    }

    /**
     * func that handles user's search location and zoom/pan on the input location
     */
    private searchLocation = () => {

    }

    /**
     * func that adds marker to google maps
     */
    @undoBatch
    private addMarker = () => {

    }

    /**
     * func that updates suggested results (and auto-complete) during user input
     */
    private handleChange = () => {

    }

    // private mapRef = document.getElementById("map")
    // private markers: google.maps.Marker[] = [];
    @observable private input: HTMLInputElement | undefined;

    @action
    private setInputRef = (element: HTMLInputElement) => {
        this.input = element;
        console.log("htmlinputelement is:" + this.input)
    }
    // private searchBox = new window.google.maps.places.SearchBox(this.input);

    private handlePlacesChanged = () => {
        const searchBox = new window.google.maps.places.SearchBox(this.input!)
        const places = searchBox.getPlaces();

        console.log(places);

        if (places.length == 0) { return; }

        // // clear out old markers
        // this.markers.forEach((marker) => {
        //     marker.setMap(null);
        // });
        // this.markers = []

        // // for each place, get icon, name, location
        const bounds = new window.google.maps.LatLngBounds();
        places.forEach((place) => {
            if (!place.geometry || !place.geometry.location) {
                console.log("Returned place contains no geometry");
                return;
            }

            // const icon = {
            //     url: place.icon as string,
            //     size: new google.maps.Size(71, 71),
            //     origin: new google.maps.Point(0, 0),
            //     anchor: new google.maps.Point(17, 34),
            //     scaledSize: new google.maps.Size(25, 25),
            // }

            // //create a marker for each place
            // this.markers.push(
            //     new google.maps.Marker({
            //         mapRef, 
            //         title: place.name,
            //         position: place.geometry.location,
            //     })
            // );

            if (place.geometry.viewport) {
                // only geocodes have viewport
                bounds.union(place.geometry.viewport);
            }
            else {
                bounds.extend(place.geometry.location);
            }
        });
    }

    // private setBounds = () => {
    //     const places = this.searchBox.getPlaces();
    //     if (places.length == 0) { return; }

    //     const bounds = new google.maps.LatLngBounds();
    //     places.forEach((place) => {
    //         if (!place.geometry || !place.geometry.location) {
    //             console.log("Returned place contains no geometry");
    //             return;
    //         }

    //         if (place.geometry.viewport) {
    //             // only geocodes have viewport
    //             bounds.union(place.geometry.viewport);
    //         }
    //         else {
    //             bounds.extend(place.geometry.location);
    //         }
    //     });

    //     return bounds
    // }

    private onPolygonComplete = (polygon: any) => {
        console.log(polygon)
    }

    private onMarkerComplete = (marker: any) => {
        this.myPlaces.push(marker)
    }

    render() {
        const { Document, fieldKey, isContentActive: active } = this.props;

        return <div className="collectionMapView" ref={this.createDashEventsTarget}>

            <div className={"collectionMapView-contents"}
                style={{ pointerEvents: active() ? undefined : "none", overflow: 'hidden' }}
                onWheel={e => e.stopPropagation()}
                onPointerDown={e => (e.button === 0 && !e.ctrlKey) && e.stopPropagation()} >
                <LoadScript
                    googleMapsApiKey={process.env.GOOGLE_MAPS!}
                    libraries={['places', 'drawing']}
                >
                    <div className="map-wrapper">
                        <GoogleMap
                            mapContainerStyle={mapContainerStyle}
                            zoom={this.zoom}
                            center={this.center}
                            onLoad={map => this.loadHandler(map)}
                        >
                            <StandaloneSearchBox
                                onPlacesChanged={this.handlePlacesChanged}>
                                <input ref={this.setInputRef} className="searchbox" type="text" placeholder="Search anywhere:" />
                            </StandaloneSearchBox>

                            {this.myPlaces.map(place => (
                                <Marker
                                    key={place.id}
                                    position={place.pos}
                                    // onLoad={marker => this.markerLoadHandler(marker, place)}
                                    onClick={e => this.markerClickHandler(e, place)}
                                    draggable={true}
                                    onDragEnd={marker => this.handleDragMarker(marker, place)}
                                />
                            ))}
                            {this.infoWindowOpen && this.selectedPlace && (
                                <InfoWindow
                                    // anchor={this.markerMap[this.selectedPlace.id]}
                                    onCloseClick={this.handleInfoWindowClose}
                                    position={this.selectedPlace.pos}
                                // options={{ enableEventPropagation: true }}
                                >
                                    <div style={{ backgroundColor: 'white', opacity: 0.75, padding: 12 }}>
                                        <div style={{ fontSize: 16 }}>
                                            <div>
                                                <a>a link to another node</a>
                                            </div>
                                            <div>
                                                <a>a link to another node</a>
                                            </div>
                                            <div>
                                                <a>a link to another node</a>
                                            </div>
                                            <div>
                                                <button>New +</button>
                                            </div>
                                        </div>
                                    </div>
                                </InfoWindow>
                            )}
                            {/* <DrawingManager
                                onPolygonComplete={this.onPolygonComplete}
                                onMarkerComplete={this.onMarkerComplete}
                            /> */}
                        </GoogleMap>
                    </div>
                </LoadScript >
            </div >
        </div >;
    }

}