import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Autocomplete, GoogleMap, GoogleMapProps, Marker } from '@react-google-maps/api';
import * as dotenv from 'dotenv';
import { action, computed, IReactionDisposer, observable, ObservableMap } from 'mobx';
import { observer } from "mobx-react";
import * as React from "react";
import { Doc, DocListCast, Opt, WidthSym } from '../../../../fields/Doc';
import { documentSchema } from '../../../../fields/documentSchemas';
import { Id } from '../../../../fields/FieldSymbols';
import { InkTool } from '../../../../fields/InkField';
import { makeInterface } from '../../../../fields/Schema';
import { NumCast, StrCast } from '../../../../fields/Types';
import { TraceMobx } from '../../../../fields/util';
import { emptyFunction, OmitKeys, returnFalse, returnOne, setupMoveUpEvents, Utils } from '../../../../Utils';
import { Docs } from '../../../documents/Documents';
import { CurrentUserUtils } from '../../../util/CurrentUserUtils';
import { DragManager } from '../../../util/DragManager';
import { SnappingManager } from '../../../util/SnappingManager';
import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm';
import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../../DocComponent';
import { Colors } from '../../global/globalEnums';
import { MarqueeAnnotator } from '../../MarqueeAnnotator';
import { AnchorMenu } from '../../pdf/AnchorMenu';
import { Annotation } from '../../pdf/Annotation';
import { SidebarAnnos } from '../../SidebarAnnos';
import { StyleProp } from '../../StyleProvider';
import { FieldView, FieldViewProps } from '../FieldView';
import "./MapBox.scss";
import { MapBoxInfoWindow } from './MapBoxInfoWindow';

/**
 * MapBox architecture:
 * Main component: MapBox.tsx
 * Supporting Components: SidebarAnnos, CollectionStackingView
 * 
 * MapBox is a node that extends the ViewBoxAnnotatableComponent. Similar to PDFBox and WebBox, it supports interaction between sidebar content and document content. 
 * The main body of MapBox uses Google Maps API to allow location retrieval, adding map markers, pan and zoom, and open street view. 
 * Dash Document architecture is integrated with Maps API: When drag and dropping documents with ExifData (gps Latitude and Longitude information) available, 
 * sidebarAddDocument function checks if the document contains lat & lng information, if it does, then the document is added to both the sidebar and the infowindow (a pop up corresponding to a map marker--pin on map).
 * The lat and lng field of the document is filled when importing (spec see ConvertDMSToDD method and processFileUpload method in Documents.ts).
 * A map marker is considered a document that contains a collection with stacking view of documents, it has a lat, lng location, which is passed to Maps API's custom marker (red pin) to be rendered on the google maps
 */

// const _global = (window /* browser */ || global /* node */) as any;

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

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

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

const mapOptions = {
    fullscreenControl: false,
}

dotenv.config({ path: __dirname + '/.env' })
const apiKey = process.env.GOOGLE_MAPS;

const script = document.createElement('script');
script.defer = true;
script.async = true;
script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=places,drawing`;
document.head.appendChild(script);

/**
 * Consider integrating later: allows for drawing, circling, making shapes on map
 */
// const drawingManager = new window.google.maps.drawing.DrawingManager({
//     drawingControl: true,
//     drawingControlOptions: {
//         position: google.maps.ControlPosition.TOP_RIGHT,
//         drawingModes: [
//             google.maps.drawing.OverlayType.MARKER,
//             // currently we are not supporting the following drawing mode on map, a thought for future development
//             google.maps.drawing.OverlayType.CIRCLE,
//             google.maps.drawing.OverlayType.POLYLINE,
//         ],
//     },
// });


// options for searchbox in Google Maps Places Autocomplete API
const options = {
    fields: ["formatted_address", "geometry", "name"], // note: level of details is charged by item per retrieval, not recommended to return all fields
    strictBounds: false,
    types: ["establishment"], // type pf places, subject of change according to user need
} as google.maps.places.AutocompleteOptions;

@observer
export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps & Partial<GoogleMapProps>, MapDocument>(MapDocument) {

    private _dropDisposer?: DragManager.DragDropDisposer;
    private _disposers: { [name: string]: IReactionDisposer } = {};
    private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
    @observable private _overlayAnnoInfo: Opt<Doc>;
    showInfo = action((anno: Opt<Doc>) => this._overlayAnnoInfo = anno);
    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(MapBox, fieldKey); }
    public get SidebarKey() { return this.fieldKey + "-sidebar"; }
    private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean, hide: boolean) => void);
    @computed get inlineTextAnnotations() { return this.allMapMarkers.filter(a => a.textInlineAnnotations); }

    @observable private _map: google.maps.Map = null as unknown as google.maps.Map;
    @observable private selectedPlace: Doc | undefined;
    @observable private markerMap: { [id: string]: google.maps.Marker } = {};
    @observable private center = navigator.geolocation ? navigator.geolocation.getCurrentPosition : defaultCenter;
    @observable private _marqueeing: number[] | undefined;
    @observable private _isAnnotating = false;
    @observable private inputRef = React.createRef<HTMLInputElement>();
    @observable private searchMarkers: google.maps.Marker[] = [];
    @observable private searchBox = new window.google.maps.places.Autocomplete(this.inputRef.current!, options);
    @observable private _savedAnnotations = new ObservableMap<number, HTMLDivElement[]>();
    @computed get allSidebarDocs() { return DocListCast(this.dataDoc[this.SidebarKey]); };
    @computed get allMapMarkers() { return DocListCast(this.dataDoc[this.annotationKey]); };
    @observable private toggleAddMarker = false;
    private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();


    @observable _showSidebar = false;
    @computed get SidebarShown() { return this._showSidebar || this.layoutDoc._showSidebar ? true : false; }

    static _canAnnotate = true;
    static _hadSelection: boolean = false;
    private _sidebarRef = React.createRef<SidebarAnnos>();
    private _ref: React.RefObject<HTMLDivElement> = React.createRef();

    constructor(props: any) {
        super(props);
    }

    @action
    private setSearchBox = (searchBox: any) => {
        this.searchBox = searchBox;
    }

    // iterate allMarkers to size, center, and zoom map to contain all markers
    private fitBounds = (map: google.maps.Map) => {
        const curBounds = map.getBounds() ?? new window.google.maps.LatLngBounds();
        const isFitting = this.allMapMarkers.reduce((fits, place) =>
            fits && curBounds?.contains({ lat: NumCast(place.lat), lng: NumCast(place.lng) }), true as boolean);
        !isFitting && map.fitBounds(this.allMapMarkers.reduce((bounds, place) =>
            bounds.extend({ lat: NumCast(place.lat), lng: NumCast(place.lng) }),
            new window.google.maps.LatLngBounds()));
    }

    /**
     * Custom control for add marker button
     * @param controlDiv 
     * @param map 
     */
    private CenterControl = () => {
        const controlDiv = document.createElement("div");
        controlDiv.className = "mapBox-addMarker"
        // Set CSS for the control border.
        const controlUI = document.createElement("div");
        controlUI.style.backgroundColor = "#fff";
        controlUI.style.borderRadius = "3px";
        controlUI.style.cursor = "pointer";
        controlUI.style.marginTop = "10px";
        controlUI.style.borderRadius = "4px";
        controlUI.style.marginBottom = "22px";
        controlUI.style.textAlign = "center";
        controlUI.style.position = "absolute";
        controlUI.style.width = "32px";
        controlUI.style.height = "32px";
        controlUI.title = "Click to toggle marker mode.  In marker mode, click on map to place a marker.";

        const plIcon = document.createElement("img");
        plIcon.src = "https://cdn4.iconfinder.com/data/icons/wirecons-free-vector-icons/32/add-256.png";
        plIcon.style.color = "rgb(25,25,25)";
        plIcon.style.fontFamily = "Roboto,Arial,sans-serif";
        plIcon.style.fontSize = "16px";
        plIcon.style.lineHeight = "32px";
        plIcon.style.left = "18";
        plIcon.style.top = "15";
        plIcon.style.position = "absolute";
        plIcon.width = 14;
        plIcon.height = 14;
        plIcon.innerHTML = "Add";
        controlUI.appendChild(plIcon);

        // Set CSS for the control interior.
        const markerIcon = document.createElement("img");
        markerIcon.src = "https://cdn0.iconfinder.com/data/icons/small-n-flat/24/678111-map-marker-1024.png";
        markerIcon.style.color = "rgb(25,25,25)";
        markerIcon.style.fontFamily = "Roboto,Arial,sans-serif";
        markerIcon.style.fontSize = "16px";
        markerIcon.style.lineHeight = "32px";
        markerIcon.style.left = "-2";
        markerIcon.style.top = "1";
        markerIcon.width = 30;
        markerIcon.height = 30;
        markerIcon.style.position = "absolute";
        markerIcon.innerHTML = "Add";
        controlUI.appendChild(markerIcon);

        // Setup the click event listeners
        controlUI.addEventListener("click", () => {
            if (this.toggleAddMarker == true) {
                this.toggleAddMarker = false;
                console.log("add marker button status:" + this.toggleAddMarker);
                controlUI.style.backgroundColor = "#fff";
                markerIcon.style.color = "rgb(25,25,25)";
            } else {
                this.toggleAddMarker = true;
                console.log("add marker button status:" + this.toggleAddMarker);
                controlUI.style.backgroundColor = "#4476f7";
                markerIcon.style.color = "rgb(255,255,255)";
            };
        });
        controlDiv.appendChild(controlUI);
        return controlDiv;
    }

    /**
     * Place the marker on google maps & store the empty marker as a MapMarker Document in allMarkers list
     * @param position - the LatLng position where the marker is placed
     * @param map 
     */
    @action
    private placeMarker = (position: google.maps.LatLng, map: google.maps.Map) => {
        const marker = new google.maps.Marker({
            position: position,
            map: map
        });
        map.panTo(position);
        const mapMarker = Docs.Create.MapMarkerDocument(NumCast(position.lat()), NumCast(position.lng()), false, [], {});
        this.addDocument(mapMarker, this.annotationKey);
    }

    _loadPending = true;
    /**
     * store a reference to google map instance
     * setup the drawing manager on the top right corner of map
     * fit map bounds to contain all markers 
     * @param map 
     */
    @action
    private loadHandler = (map: google.maps.Map) => {
        this._map = map;
        this._loadPending = true;
        const centerControlDiv = this.CenterControl();
        map.controls[google.maps.ControlPosition.TOP_RIGHT].push(centerControlDiv);
        //drawingManager.setMap(map);
        // if (navigator.geolocation) {
        //     navigator.geolocation.getCurrentPosition(
        //         (position: Position) => {
        //             const pos = {
        //                 lat: position.coords.latitude,
        //                 lng: position.coords.longitude,
        //             };
        //             this._map.setCenter(pos);
        //         }
        //     );
        // } else {
        //     alert("Your geolocation is not supported by browser.")
        // };
        map.setZoom(NumCast(this.dataDoc.mapZoom, 2.5));
        map.setCenter(new google.maps.LatLng(NumCast(this.dataDoc.mapLat), NumCast(this.dataDoc.mapLng)));
        setTimeout(() => {

            if (this._loadPending && this._map.getBounds()) {
                this._loadPending = false;
                this.layoutDoc.fitToBox && this.fitBounds(this._map);
            }
        }, 250);
        // listener to addmarker event
        this._map.addListener('click', (e: MouseEvent) => {
            if (this.toggleAddMarker == true) {
                this.placeMarker((e as any).latLng, map);
            }
        })
    }

    @action
    centered = () => {
        if (this._loadPending && this._map.getBounds()) {
            this._loadPending = false;
            this.layoutDoc.fitToBox && this.fitBounds(this._map);
        }
        this.dataDoc.mapLat = this._map.getCenter()?.lat();
        this.dataDoc.mapLng = this._map.getCenter()?.lng();
    }

    @action
    zoomChanged = () => {
        if (this._loadPending && this._map.getBounds()) {
            this._loadPending = false;
            this.layoutDoc.fitToBox && this.fitBounds(this._map);
        }
        this.dataDoc.mapZoom = this._map.getZoom();
    }

    /**
     * Load and render all map markers
     * @param marker 
     * @param place 
     */
    @action
    private markerLoadHandler = (marker: google.maps.Marker, place: Doc) => {
        place[Id] ? this.markerMap[place[Id]] = marker : null;
    }

    /**
     * on clicking the map marker, set the selected place to the marker document & set infowindowopen to be true
     * @param e 
     * @param place 
     */
    @action
    private markerClickHandler = (e: google.maps.MapMouseEvent, place: Doc) => {
        // set which place was clicked
        this.selectedPlace = place;
        place.infoWindowOpen = true;
    }

    /**
     * Called when dragging documents into map sidebar or directly into infowindow; to create a map marker, ref to MapMarkerDocument in Documents.ts
     * @param doc 
     * @param sidebarKey 
     * @returns 
     */
    sidebarAddDocument = (doc: Doc | Doc[], sidebarKey?: string) => {
        console.log("print all sidebar Docs");
        console.log(this.allSidebarDocs);
        if (!this.layoutDoc._showSidebar) this.toggleSidebar();
        const docs = doc instanceof Doc ? [doc] : doc
        docs.forEach(doc => {
            if (doc.lat !== undefined && doc.lng !== undefined) {
                const existingMarker = this.allMapMarkers.find(marker => marker.lat === doc.lat && marker.lng == doc.lng);
                doc.onClickBehavior = "enterPortal";
                if (existingMarker) {
                    Doc.AddDocToList(existingMarker, "data", doc);
                } else {
                    const marker = Docs.Create.MapMarkerDocument(NumCast(doc.lat), NumCast(doc.lng), false, [doc], {});
                    this.addDocument(marker, this.annotationKey);
                }
            }
        }) //add to annotation list
        console.log("sidebaraddDocument");
        console.log(doc);

        return this.addDocument(doc, sidebarKey); // add to sidebar list
    }

    /**
     * Removing documents from the sidebar
     * @param doc 
     * @param sidebarKey 
     * @returns 
     */
    sidebarRemoveDocument = (doc: Doc | Doc[], sidebarKey?: string) => {
        if (this.layoutDoc._showSidebar) this.toggleSidebar();
        const docs = doc instanceof Doc ? [doc] : doc;
        docs.forEach(doc => {
            console.log(this.allMapMarkers);
            console.log(this.allSidebarDocs);
        })
        return this.removeDocument(doc, sidebarKey);
    }

    /**
     * Toggle sidebar onclick the tiny comment button on the top right corner
     * @param e 
     */
    sidebarBtnDown = (e: React.PointerEvent) => {
        setupMoveUpEvents(this, e, (e, down, delta) => {
            const localDelta = this.props.ScreenToLocalTransform().scale(this.props.scaling?.() || 1).transformDirection(delta[0], delta[1]);
            const nativeWidth = NumCast(this.layoutDoc[this.fieldKey + "-nativeWidth"]);
            const curNativeWidth = NumCast(this.layoutDoc.nativeWidth, nativeWidth);
            const ratio = (curNativeWidth + localDelta[0] / (this.props.scaling?.() || 1)) / nativeWidth;
            if (ratio >= 1) {
                this.layoutDoc.nativeWidth = nativeWidth * ratio;
                this.layoutDoc._width = this.layoutDoc[WidthSym]() + localDelta[0];
                this.layoutDoc._showSidebar = nativeWidth !== this.layoutDoc._nativeWidth;
            }
            return false;
        }, emptyFunction, this.toggleSidebar);
    }

    sidebarWidth = () => Number(this.sidebarWidthPercent.substring(0, this.sidebarWidthPercent.length - 1)) / 100 * this.props.PanelWidth();
    @computed get sidebarWidthPercent() { return StrCast(this.layoutDoc._sidebarWidthPercent, "0%"); }
    @computed get sidebarColor() { return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], "#e4e4e4")); }


    /**
     * function that reads the place inputed from searchbox, then zoom in on the location that's been autocompleted;
     * add a customized temporary marker on the map
     */
    @action
    private handlePlaceChanged = () => {
        console.log(this.searchBox);
        const place = this.searchBox.getPlace();

        if (!place.geometry || !place.geometry.location) {
            // user entered the name of a place that wasn't suggested & pressed the enter key, or place details request failed
            window.alert("No details available for input: '" + place.name + "'");
            return;
        }

        // zoom in on the location of the search result
        if (place.geometry.viewport) {
            console.log(this._map);
            this._map.fitBounds(place.geometry.viewport);
        } else {
            this._map.setCenter(place.geometry.location);
            this._map.setZoom(17);
        }

        // customize icon => customized icon for the nature of the location selected
        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),
        };

        // put temporary cutomized marker on searched location
        this.searchMarkers.forEach((marker) => {
            marker.setMap(null);
        });
        this.searchMarkers = [];
        this.searchMarkers.push(
            new window.google.maps.Marker({
                map: this._map,
                icon,
                title: place.name,
                position: place.geometry.location,
            })
        )
    }

    /**
     * Handles toggle of sidebar on click the little comment button
     */
    @computed get sidebarHandle() {
        TraceMobx();
        const annotated = DocListCast(this.dataDoc[this.SidebarKey]).filter(d => d?.author).length;
        const color = !annotated ? Colors.WHITE : Colors.BLACK;
        const backgroundColor = !annotated ? this.sidebarWidth() ? Colors.MEDIUM_BLUE : Colors.BLACK : this.props.styleProvider?.(this.rootDoc, this.props as any, StyleProp.WidgetColor + (annotated ? ":annotated" : ""));
        return (!annotated) ? (null) :
            <div className="formattedTextBox-sidebar-handle" onPointerDown={this.sidebarDown}
                style={{
                    left: `max(0px, calc(100% - ${this.sidebarWidthPercent} - 17px))`,
                    backgroundColor: backgroundColor,
                    color: color,
                    opacity: annotated ? 1 : undefined
                }} >
                <FontAwesomeIcon icon={"comment-alt"} />
            </div>;
    }

    // TODO: Adding highlight box layer to Maps
    @action
    toggleSidebar = () => {
        const prevWidth = this.sidebarWidth();
        this.layoutDoc._showSidebar = ((this.layoutDoc._sidebarWidthPercent = StrCast(this.layoutDoc._sidebarWidthPercent, "0%") === "0%" ? "50%" : "0%")) !== "0%";
        this.layoutDoc._width = this.layoutDoc._showSidebar ? NumCast(this.layoutDoc._width) * 2 : Math.max(20, NumCast(this.layoutDoc._width) - prevWidth);
    }

    sidebarDown = (e: React.PointerEvent) => {
        setupMoveUpEvents(this, e, this.sidebarMove, emptyFunction, () => setTimeout(this.toggleSidebar), false);
    }
    sidebarMove = (e: PointerEvent, down: number[], delta: number[]) => {
        const bounds = this._ref.current!.getBoundingClientRect();
        this.layoutDoc._sidebarWidthPercent = "" + 100 * Math.max(0, (1 - (e.clientX - bounds.left) / bounds.width)) + "%";
        this.layoutDoc._showSidebar = this.layoutDoc._sidebarWidthPercent !== "0%";
        e.preventDefault();
        return false;
    }

    setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean) => void) => this._setPreviewCursor = func;

    @action
    onMarqueeDown = (e: React.PointerEvent) => {
        if (!e.altKey && e.button === 0 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) {
            setupMoveUpEvents(this, e, action(e => {
                MarqueeAnnotator.clearAnnotations(this._savedAnnotations);
                this._marqueeing = [e.clientX, e.clientY];
                return true;
            }), returnFalse, () => MarqueeAnnotator.clearAnnotations(this._savedAnnotations), false);
        }
    }
    @action finishMarquee = (x?: number, y?: number) => {
        this._marqueeing = undefined;
        this._isAnnotating = false;
        x !== undefined && y !== undefined && this._setPreviewCursor?.(x, y, false, false);
    }

    addDocumentWrapper = (doc: Doc | Doc[], annotationKey?: string) => {
        return this.addDocument(doc, annotationKey);
    }

    @computed get annotationLayer() {
        const pe = this.props.isContentActive() && this.props.pointerEvents !== "none" && !MarqueeOptionsMenu.Instance.isShown() ? "all" :
            SnappingManager.GetIsDragging() ? undefined : "none"
        return <div className="mapBox-annotationLayer" style={{ height: Doc.NativeHeight(this.Document) || undefined }} ref={this._annotationLayer}>
            {this.inlineTextAnnotations.sort((a, b) => NumCast(a.y) - NumCast(b.y)).map(anno =>
                <Annotation key={`${anno[Id]}-annotation`} {...this.props}
                    fieldKey={this.annotationKey} pointerEvents={pe} showInfo={this.showInfo} dataDoc={this.dataDoc} anno={anno} />)}
        </div>;
    }

    getAnchor = () => {
        const anchor =
            AnchorMenu.Instance?.GetAnchor(this._savedAnnotations) ??
            this.rootDoc
        return anchor;
    }

    /**
     * render contents in allMapMarkers (e.g. images with exifData) into google maps as map marker
     * @returns 
     */
    private renderMarkers = () => {
        return this.allMapMarkers.map(place => (
            <Marker
                key={place[Id]}
                position={{ lat: NumCast(place.lat), lng: NumCast(place.lng) }}
                onLoad={marker => this.markerLoadHandler(marker, place)}
                onClick={(e: google.maps.MapMouseEvent) => this.markerClickHandler(e, place)}
            />
        ))
    }

    // TODO: auto center on select a document in the sidebar
    private handleMapCenter = (map: google.maps.Map) => {
        // console.log("print the selected views in selectionManager:")
        // if (SelectionManager.Views().lastElement()) {
        //     console.log(SelectionManager.Views().lastElement());
        // }
    }

    panelWidth = () => this.props.PanelWidth() / (this.props.scaling?.() || 1) - this.sidebarWidth(); // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0);
    panelHeight = () => this.props.PanelHeight() / (this.props.scaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document);
    scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._scrollTop));
    transparentFilter = () => [...this.props.docFilters(), Utils.IsTransparentFilter()];
    opaqueFilter = () => [...this.props.docFilters(), Utils.IsOpaqueFilter()];
    infoWidth = () => this.props.PanelWidth() / 5;
    infoHeight = () => this.props.PanelHeight() / 5;
    anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick;

    render() {
        const renderAnnotations = (docFilters?: () => string[]) => (null);
        // bcz: commmented this out.  Otherwise, any documents that are rendered with an InfoWindow of a marker
        //      will also be rendered as freeform annotations on the map. However, it doesn't seem that rendering
        //      freeform documents on the map does anything anyway, so getting rid of it for now.  Also, since documents
        //      are rendered twice, adding a new note to the InfoWindow loses focus immediately on creation since it gets
        //      shifted to the non-visible view of the document in this freeform view.
        // <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit}
        //     renderDepth={this.props.renderDepth + 1}
        //     isAnnotationOverlay={true}
        //     fieldKey={this.annotationKey}
        //     CollectionView={undefined}
        //     setPreviewCursor={this.setPreviewCursor}
        //     PanelWidth={this.panelWidth}
        //     PanelHeight={this.panelHeight}
        //     ScreenToLocalTransform={this.scrollXf}
        //     scaling={returnOne}
        //     dropAction={"alias"}
        //     docFilters={docFilters || this.props.docFilters}
        //     dontRenderDocuments={docFilters ? false : true}
        //     select={emptyFunction}
        //     ContentScaling={returnOne}
        //     bringToFront={emptyFunction}
        //     whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
        //     removeDocument={this.removeDocument}
        //     moveDocument={this.moveDocument}
        //     addDocument={this.sidebarAddDocument}
        //     childPointerEvents={true}
        //     pointerEvents={CurrentUserUtils.SelectedTool !== InkTool.None || this._isAnnotating || SnappingManager.GetIsDragging() ? "all" : "none"} />;
        return <div className="mapBox" ref={this._ref}>
            {/*console.log(apiKey)*/}
            {/* <LoadScript
                googleMapsApiKey={apiKey!}
                libraries={['places', 'drawing']}
            > */}
            <div className="mapBox-wrapper"
                onWheel={e => e.stopPropagation()}
                onPointerDown={e => (e.button === 0 && !e.ctrlKey) && e.stopPropagation()}
                style={{ width: `calc(100% - ${this.sidebarWidthPercent})` }}>

                <div style={{ mixBlendMode: "multiply" }}>
                    {renderAnnotations(this.transparentFilter)}
                </div>
                {renderAnnotations(this.opaqueFilter)}
                {SnappingManager.GetIsDragging() ? (null) : renderAnnotations()}
                {this.annotationLayer}
                <GoogleMap
                    mapContainerStyle={mapContainerStyle}
                    onZoomChanged={this.zoomChanged}
                    onCenterChanged={this.centered}
                    onLoad={this.loadHandler}
                    options={mapOptions}
                >
                    <Autocomplete
                        onLoad={this.setSearchBox}
                        onPlaceChanged={this.handlePlaceChanged}>
                        <input ref={this.inputRef} className="searchbox" type="text" placeholder="Search anywhere:" />
                    </Autocomplete>

                    {this.renderMarkers()}
                    {this.allMapMarkers.filter(marker => marker.infoWindowOpen).map(marker => <MapBoxInfoWindow key={marker[Id]}
                        {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit}
                        place={marker}
                        markerMap={this.markerMap}
                        PanelWidth={this.infoWidth}
                        PanelHeight={this.infoHeight}
                        moveDocument={this.moveDocument}
                        isAnyChildContentActive={this.isAnyChildContentActive}
                        whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
                    />)}
                    {this.handleMapCenter(this._map)}
                </GoogleMap>
                {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? (null) :
                    <MarqueeAnnotator rootDoc={this.rootDoc}
                        anchorMenuClick={this.anchorMenuClick}
                        scrollTop={0}
                        down={this._marqueeing} scaling={returnOne}
                        addDocument={this.addDocumentWrapper}
                        docView={this.props.docViewPath().lastElement()}
                        finishMarquee={this.finishMarquee}
                        savedAnnotations={this._savedAnnotations}
                        annotationLayer={this._annotationLayer.current}
                        mainCont={this._mainCont.current} />}
            </div>
            {/* </LoadScript > */}
            <div className="mapBox-sidebar"
                style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}>
                <SidebarAnnos ref={this._sidebarRef}
                    {...this.props}
                    fieldKey={this.fieldKey}
                    rootDoc={this.rootDoc}
                    layoutDoc={this.layoutDoc}
                    dataDoc={this.dataDoc}
                    showSidebar={this.SidebarShown}
                    nativeWidth={NumCast(this.layoutDoc._nativeWidth)}
                    whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
                    PanelWidth={this.sidebarWidth}
                    sidebarAddDocument={this.sidebarAddDocument}
                    moveDocument={this.moveDocument}
                    removeDocument={this.sidebarRemoveDocument}
                />
            </div>
            <div className="mapBox-overlayButton-sidebar" key="sidebar" title="Toggle Sidebar"
                style={{
                    display: !this.props.isContentActive() ? "none" : undefined,
                    top: StrCast(this.rootDoc._showTitle) === "title" ? 20 : 5,
                    backgroundColor: this.SidebarShown ? Colors.MEDIUM_BLUE : Colors.BLACK
                }}
                onPointerDown={this.sidebarBtnDown} >
                <FontAwesomeIcon style={{ color: Colors.WHITE }} icon={"comment-alt"} size="sm" />
            </div>
        </div>;
    }
}
