/**
* 2007-2024 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License (AFL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/afl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
*  @author    PrestaShop SA <contact@prestashop.com>
*  @copyright 2007-2024 PrestaShop SA
*  @license   http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
*  International Registered Trademark & Property of PrestaShop SA
*
* Don't forget to prefix your containers with your own identifier
* to avoid any conflicts with others containers.
*/
class AgileGMapClass {
    map;
    infoWindow;
    geocoder;
    curentMarker;
    markers = {};
    lastGeocode;

    constructor(agileGmapKey, countries = []) {
        this.gKey = agileGmapKey;
        this.countries = countries;
    }

    setElemBySelector(selector, position = 'after') {
        if ('append' === position) {
            $(selector).append('<div id="agile_map"></div>')
        } else {
            $(selector).after('<div id="agile_map"></div>')
        }
    }

    async downloadGMap(language = '') {
        let gMapJs = (g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({
            key: this.gKey,
            v: "weekly",
            language: language
          });

        let script = '<script type="text/javascript"> ' + gMapJs + ' </script>'
        $('head').append(script);
    }

    async initMap(center, title, zoom = 10, isDraggable = true) {
        const { Map } = await google.maps.importLibrary('maps');

        this.map = new Map(document.getElementById('agile_map'), {
            center: center,
            zoom: zoom,
        });

        this.infoWindow = new google.maps.InfoWindow();
        this.geocoder = new google.maps.Geocoder();

        this.addMarker(center, title, isDraggable);

        if (true === isDraggable) {
            this.map.addListener('click', this.setMarkerPosition.bind(this), false);
        } else {
            this.markers[0].setMap(null)
        }
    }

    addMarker(location, title = '', isDraggable = true, label = '', idMarker = 0) {
        const marker = new google.maps.Marker({
            position: location,
            map: this.map,
            draggable: isDraggable,
            title: title,
            label: label,
        });

        marker.idMarker = idMarker;

        if (!this.markers[idMarker]) {
            this.markers[idMarker] = marker;
        }

        const infoWindow = this.infoWindow;

        marker.addListener('click', function({ domEvent, latLng }) {

            infoWindow.close();
            infoWindow.setContent(marker.title);
            infoWindow.open(marker.map, marker);
        });

        if (true === isDraggable) {
            this.curentMarker = marker;
            this.curentMarker.addListener('dragend', this.dragendMarker.bind(this), false);
        } else {
            marker.addListener('click', function({ domEvent, latLng }) {
                $('#location_carrier_' + marker.idMarker).click();
            })
        }
    }

    displayCenterMarker(idMarker) {
        if (this.markers[idMarker]) {
            this.infoWindow.close();
            this.infoWindow.setContent(this.markers[idMarker].title);
            this.infoWindow.open(this.markers[idMarker].map, this.markers[idMarker]);
        }
    }

    setMapOnAll(map) {
        for (const i in this.markers) {
            this.markers[i].setMap(map);
        }
    }

    hideMarkerById(idMarker) {
        if (this.markers[idMarker]) {
            this.markers[idMarker].setMap(null);
        }
    }

    hideMarkers() {
        this.setMapOnAll(null);
    }

    showMarkerById(idMarker) {
        if (this.markers[idMarker]) {
            this.markers[idMarker].setMap(this.map);
        }
    }

    deleteMarkers() {
        this.hideMarkers();
        this.markers = {};
    }

    setMarkerPosition(e) {
        let lat = +e.latLng.lat(),
            lng = +e.latLng.lng();

        this.curentMarker.setPosition({lat: lat, lng: lng });

        this.setNewValue('latitude', lat);
        this.setNewValue('longitude', lng);

        this.geocodeLatLng(lat, lng);
    }

    dragendMarker(e) {
        let lat = +e.latLng.lat(),
            lng = +e.latLng.lng();

        this.setNewValue('latitude', lat);
        this.setNewValue('longitude', lng);

        this.geocodeLatLng(lat, lng);
    }

    geocodeLatLng(lat, lng) {
        const latlng = {
          lat: parseFloat(lat),
          lng: parseFloat(lng),
        };

        this.geocoder
            .geocode({ location: latlng })
            .then((response) => {
                if (response.results[0]) {
                    this.map.setZoom(10);
                    this.lastGeocode = response.results[0];

                    this.infoWindow.setContent(response.results[0].formatted_address);
                    this.infoWindow.open(this.map, this.curentMarker);

                    this.setGeocodeDate();
                } else {
                    window.alert("No results found");
                }
            })
            .catch((e) => window.alert("Geocoder failed due to: " + e));
    }

    setGeocodeDate() {
        if (this.lastGeocode) {
            if (typeof this.lastGeocode.formatted_address != 'undefined') {
                this.setNewValue('location', this.lastGeocode.formatted_address);
            }

            if (typeof this.lastGeocode.address_components != 'undefined' && this.lastGeocode.address_components.length) {
                let address1 = '';

                this.lastGeocode.address_components.forEach(function(el) {
                    let type = el.types[0];

                    if (type.includes('administrative')) {
                        type = 'administrative';
                    }

                    switch(type) {
                        case 'street_number':
                        case 'route':
                            if (address1) {
                                address1 += ', ' + el.short_name;
                            } else {
                                address1 = el.short_name;
                            }
                            break;
                        case 'locality':
                            this.setNewValue('city', el.short_name);
                            break;
                        case 'country':
                            this.setCountryByIso(el.short_name);
                            break;
                        case 'postal_code':
                            this.setNewValue('postcode', el.short_name);
                            break;
                        case 'administrative':
                            this.setStateByName(el.short_name);
                            break;
                    }
                }, this)

                if (address1) {
                    this.setNewValue('address1', address1);
                }
            }
        }
    }

    setCountryByIso(isoCode) {
        for (const i in this.countries) {
            if (this.countries[i].iso_code == isoCode) {
                let idCountry = +this.countries[i].id_country;

                if ($('select[name="id_country"]').length > 0) {
                    $('select[name="id_country"]').val(idCountry);
                    $('select[name="id_country"]').trigger('change');
                } else {
                    $('select.agile-country').val(idCountry);
                    $('select.agile-country').trigger('change');
                }

                break;
            }
        }
    }

    setStateByName(nameState) {
        for (const i in this.countries) {
            if (typeof this.countries[i].states != 'undefined') {
                for (const j in this.countries[i].states) {
                    if (this.countries[i].states[j].name == nameState) {
                        idSelectedState = +this.countries[i].states[j].id_state;

                        if ($('select[name="id_country"]').length > 0) {
                            $('select[name="id_country"]').trigger('change');
                        } else {
                            // $('select.agile-country').trigger('change');
                            $('select.agile-state').val(idSelectedState);
                            $('select.agile-state').trigger('change');
                        }

                        break;
                    }
                }
            }
        }
    }

    setNewValue(name, value) {
        if ($('input[name="' + name + '"]').length > 0) {
            $('input[name="' + name + '"]').val(value);
        } else {
            $('input.agile-' + name).val(value);
        }
    }
}
