import type {LngLat} from '@yandex/ymaps3-types';
import type {Feature} from '@yandex/ymaps3-clusterer';
import {COMMON_LOCATION_PARAMS, type ExpandedFeature, getBounds, getRandomPoints, MARGIN} from '../common2';
import {BOUNDS, LOCATION} from '../variables2';
import type {SearchResponse} from '@yandex/ymaps3-types';

window.map = null;
window.map2 = null;

main();
async function main() {
    // Waiting for all api elements to be loaded
    await ymaps3.ready;
    interface ClustererChangeControlProps {
        toggleClusterer: () => void;
        changePointsCount: (count: number) => void;
        updatePoints: () => void;
    }

    class ClustererChangeControl extends ymaps3.YMapComplexEntity<ClustererChangeControlProps> {
        private _element: HTMLDivElement;
        private _detachDom: () => void;

        // Method for create a DOM control element
        _createElement(props: ClustererChangeControlProps) {
            const {toggleClusterer, changePointsCount, updatePoints} = props;

            const clustererChange = document.createElement('div');
            clustererChange.classList.add('clusterer-change');

            const inputSection = document.createElement('div');
            inputSection.classList.add('clusterer-change__section');

            const inputLabel = document.createElement('div');
            inputLabel.classList.add('clusterer-change__input__label');
            inputLabel.textContent = 'Point count:';
            inputSection.appendChild(inputLabel);

            const inputField = document.createElement('input');
            inputField.type = 'number';
            inputField.classList.add('clusterer-change__input');
            inputField.value = '100';
            inputField.addEventListener('input', (e: Event) => {
                const target = e.target as HTMLInputElement;
                changePointsCount(Number(target.value));
            });
            inputSection.appendChild(inputField);

            const btnSection = document.createElement('div');
            btnSection.classList.add('clusterer-change__buttons');

            const updatePointsBtn = document.createElement('button');
            updatePointsBtn.type = 'button';
            updatePointsBtn.classList.add('clusterer-change__btn');
            updatePointsBtn.textContent = 'Update points';
            updatePointsBtn.addEventListener('click', updatePoints);
            btnSection.appendChild(updatePointsBtn);

            const toggleClustererBtn = document.createElement('button');
            toggleClustererBtn.type = 'button';
            toggleClustererBtn.id = 'toggleBtn';
            toggleClustererBtn.classList.add('clusterer-change__btn');
            toggleClustererBtn.textContent = 'Disable cluster mode';
            toggleClustererBtn.addEventListener('click', toggleClusterer);
            btnSection.appendChild(toggleClustererBtn);

            const dividerElement = document.createElement('hr');
            dividerElement.classList.add('divider');

            clustererChange.appendChild(inputSection);
            clustererChange.appendChild(dividerElement);
            clustererChange.appendChild(btnSection);

            return clustererChange;
        }

        // Method for attaching the control to the map
        _onAttach() {
            this._element = this._createElement(this._props);
            this._detachDom = ymaps3.useDomContext(this, this._element, this._element);
        }

        // Method for detaching control from the map
        _onDetach() {
            this._detachDom();
            this._detachDom = null;
            this._element = null;
        }
    }

    const {YMap, YMapDefaultSchemeLayer, YMapDefaultFeaturesLayer, YMapMarker, YMapControls, YMapControl} = ymaps3;

    // Load the package with the cluster, extract the classes for creating clusterer objects and the clustering method
    const {YMapClusterer, clusterByGrid} = await ymaps3.import('@yandex/ymaps3-clusterer');
    const {YMapDefaultMarker} = await ymaps3.import('@yandex/ymaps3-default-ui-theme');

        // Load the control package and extract the geolocation control from it
        const {YMapGeolocationControl,YMapSearchControl} = await ymaps3.import('@yandex/ymaps3-default-ui-theme');

    // Declare number of points in the clusterer
    let pointsCount = 100;
    let points = getRandomPoints(pointsCount, BOUNDS);
    let markers = [];
    var zcnt = 0;
    let markers2 = [];
    var zcnt2 = 0;

    let fa = [];
    let fa2 = [];

    map = new YMap(document.getElementById('app'), {location: LOCATION, showScaleInCopyrights: true, margin: MARGIN}, [
        new YMapDefaultSchemeLayer({}),
        new YMapDefaultFeaturesLayer({})
    ]);

    map2 = new YMap(document.getElementById('app2'), {location: LOCATION, showScaleInCopyrights: true, margin: MARGIN}, [
        new YMapDefaultSchemeLayer({}),
        new YMapDefaultFeaturesLayer({})
    ]);

    //const newCoordinates = await getLocation();
   // map.setLocation({center: newCoordinates});


    function escapeHtml(s: string): string {
        return String(s)
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;');
    }

    function normalizeGtin(raw: string): string {
        const digits = String(raw || '').replace(/\D+/g, '');
        if (digits.length === 14 && digits.charAt(0) === '0') {
            return digits.substring(1);
        }
        return digits;
    }

    // Картинки попапа: GTIN из products_arr2.php. Нет в базе — серая бутылка.
    const gtinPicIndex: Record<string, {pic?: string, link?: string}> = {};
    if (typeof products !== 'undefined' && typeof cnt === 'number') {
        for (let i = 0; i < cnt; i++) {
            const zgt = products[i] && products[i]['gtins'] ? products[i]['gtins'] : {};
            Object.keys(zgt).forEach((k) => {
                gtinPicIndex[normalizeGtin(k)] = zgt[k];
            });
        }
    }

    let weeklyById: Record<string, any> = {};

    function genWeeklyPic(gtin: string, name: string): string {
        const key = normalizeGtin(gtin);
        const meta = gtinPicIndex[key];
        const title = escapeHtml((name || 'Неизвестный товар') + (gtin ? ' · ' + gtin : ''));
        if (meta && meta.pic) {
            const href = meta.link
                ? meta.link
                : ('https://mjolnir.pro/medovuha_catalog.html?gtin=' + encodeURIComponent(gtin));
            return '<a target="_blank" href="' + escapeHtml(href) + '"><div class="pdiv" title="' + title + '" style="background-image:url(' + meta.pic + ');"></div></a>';
        }
        return '<div class="pdiv pdiv-unknown" title="' + title + '"></div>';
    }

    function populateWeekly(pointId: string): void {
        const point = weeklyById[pointId];
        if (!point) {
            return;
        }
        const productsList = point.products || [];
        // Сначала бутылки, потом юрлицо: верх карточки обрезается (top:-27px у баллона).
        let h = '<div class="smallpics">';
        productsList.forEach((p: any) => {
            h += genWeeklyPic(p.gtin || '', p.name || '');
        });
        h += '</div>';
        h += '<div class="map-point-name">' + escapeHtml(point.name || '') + '</div>';
        const addrText = point.address || '';
        const addrJs = JSON.stringify(addrText);
        h += '<br/><div class="addrdiv addr' + pointId + '" onclick=\'copyTextToClipboard(' + addrJs + '); event.stopPropagation(); return false;\'>'
            + escapeHtml(addrText)
            + '&nbsp;&nbsp;<svg width="14" height="14" viewBox="0 0 115.77 122.88" style="display:inline-block;vertical-align:middle;"><path fill-rule="evenodd" d="M89.62,13.96v7.73h12.19h0.01v0.02c3.85,0.01,7.34,1.57,9.86,4.1c2.5,2.51,4.06,5.98,4.07,9.82h0.02v0.02 v73.27v0.01h-0.02c-0.01,3.84-1.57,7.33-4.1,9.86c-2.51,2.5-5.98,4.06-9.82,4.07v0.02h-0.02h-61.7H40.1v-0.02 c-3.84-0.01-7.34-1.57-9.86-4.1c-2.5-2.51-4.06-5.98-4.07-9.82h-0.02v-0.02V92.51H13.96h-0.01v-0.02c-3.84-0.01-7.34-1.57-9.86-4.1 c-2.5-2.51-4.06-5.98-4.07-9.82H0v-0.02V13.96v-0.01h0.02c0.01-3.85,1.58-7.34,4.1-9.86c2.51-2.5,5.98-4.06,9.82-4.07V0h0.02h61.7 h0.01v0.02c3.85,0.01,7.34,1.57,9.86,4.1c2.5,2.51,4.06,5.98,4.07,9.82h0.02V13.96L89.62,13.96z"/></svg></div>';
        $('.markerid' + pointId).html(h);
        setTimeout("clearContent('" + pointId + "')", 30000);
    }

    async function loadWeeklyFeatures() {
        const res = await fetch('/mjolnir-pro-weekly-sync/sales-map.json', {cache: 'no-cache'});
        if (!res.ok) {
            throw new Error('HTTP ' + res.status);
        }
        const data = await res.json();
        const list = data.points || [];
        weeklyById = {};
        const features = [];
        for (let i = 0; i < list.length; i++) {
            const p = list[i];
            if (p.lat == null || p.lon == null) {
                continue;
            }
            const id = String(i);
            weeklyById[id] = p;
            features.push({
                type: 'Feature',
                id,
                addr: p.address,
                gtins: '',
                nm: p.name,
                geometry: {type: 'Point', coordinates: [Number(p.lon), Number(p.lat)]}
            });
        }
        return features;
    }

    try {
        fa = await loadWeeklyFeatures();
    } catch (err) {
        console.error('Не удалось загрузить sales-map.json', err);
        const periodEl = document.getElementById('mjolnir-map-period');
        if (periodEl) {
            periodEl.textContent = 'Карта временно недоступна. Попробуйте обновить страницу позже.';
        }
        fa = [];
    }

    //console.log(fa);



function clearMTO(){
    clearTimeout(mTO);
}

const marker = (feature: ExpandedFeature) => {
    const markerContainerElement = document.createElement('div');
    markerContainerElement.classList.add('marker-container');

    const markerText = document.createElement('div');
    markerText.id = feature.id;
    markerText.classList.add('marker-text', 'hidden');
    markerText.innerText = ' ';//NAMES[feature.id];
    markerText.classList.add('markerid'+feature.id);
    markerText.setAttribute('addr',feature.addr);

    markerText.onmouseover = () => {
        console.log('mover mtext');
        clearMTO();
    }

    markerText.onmouseout = () => {
        console.log('mout mtext');
        mTO = setTimeout("clearContent('"+feature.id+"')",500);
        //$(markerText).html('');
    };
   //markerText.setAttribute('num',zcnt++);

    markerContainerElement.onmouseover = () => {
        markerText.classList.replace('hidden', 'visible');
        console.log('mover mc');
        clearMTO();
    };

    markerContainerElement.onmouseout = () => {
        markerText.classList.replace('visible', 'hidden');

        if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)){
            console.log('mout mc');
            mTO = setTimeout("clearContent('"+feature.id+"')",500);
        } //else setTimeout("clearContent('"+feature.id+"')",500);

        //$(markerText).html('');
    };

    const markerElement = document.createElement('div');
    markerElement.classList.add('marker');

    const markerImage = document.createElement('img');
    //markerImage.src = getImageSrc(feature.id);
    markerImage.classList.add('image');

    markerElement.appendChild(markerImage);

    markerContainerElement.appendChild(markerText);
    markerContainerElement.appendChild(markerElement);
    let tx = feature.addr;
    let zx = feature.id;

    const m = new YMapMarker({
            coordinates: feature.geometry.coordinates,
            onClick(e) {
                populateWeekly('' + zx);
            },
            id:feature.addr,
            class:'marker'+zcnt,
            num:zcnt++
        },
        markerContainerElement
    );

    m['addr'] = feature.addr;
    m['num'] = zcnt++;
    m['gtins'] = feature.gtins;
    return m;
};

/*
    const marker = (feature: Feature) =>


        new YMapDefaultMarker({
            coordinates: feature.geometry.coordinates,
            iconName: 'landmark',
            onClick(e) {
                console.log('event');
                console.log(e);
                populate(e);
                //const bounds = getBounds(features.map((feature: Feature) => feature.geometry.coordinates));
                //map.update({location: {bounds, ...COMMON_LOCATION_PARAMS}});
            }
        } );

        */

    /*    {
            coordinates: feature.geometry.coordinates
        },
        markerContainerElement
*/
// As for ordinary markers, we declare a cluster rendering function that also returns an Entity element.
    const cluster = (coordinates: LngLat, features: Feature[]) =>
        new YMapMarker(
            {
                coordinates,
                onClick() {
                    const bounds = getBounds(features.map((feature: Feature) => feature.geometry.coordinates));
                    map.update({location: {bounds, ...COMMON_LOCATION_PARAMS}});
                }
            },
            circle(features.length).cloneNode(true) as HTMLElement
        );

    function circle(count: number) {
        const circle = document.createElement('div');
        circle.classList.add('circle');
        circle.innerHTML = `
                  <div class="circle-content" style="z-index:10;">
                      <span class="circle-text">${count}</span>
                  </div>
              `;
        return circle;
    }

    /* We create a clusterer object and add it to the map object.
  As parameters, we pass the clustering method, an array of features, the functions for rendering markers and clusters.
  For the clustering method, we will pass the size of the grid division in pixels. */
    const clusterer = new YMapClusterer({
        method: clusterByGrid({gridSize: 64}),
        features: fa,
        marker,
        cluster
    });
    map.addChild(clusterer);

    const searchResultHandler = (searchResult: SearchResponse) => {
        console.log('SEARCH');
        console.log(searchResult);  
       
         map.update({
            location: {
                center: searchResult[0].geometry.coordinates
              }
            });
        //updateSearchMarkers(searchResult);
        //updateMapLocation(searchResult);
    };

    const searchResultHandler2 = (searchResult: SearchResponse) => {
        console.log('SEARCH2');
        console.log(searchResult);  
       
         map2.update({
            location: {
                center: searchResult[0].geometry.coordinates
              }
            });
        //updateSearchMarkers(searchResult);
        //updateMapLocation(searchResult);
    };

    map.addChild(
          new YMapControls({position: 'top'}).addChild(
            new YMapSearchControl({
              searchResult: searchResultHandler
            })
          )
        );
console.log('adding search with limit');
    map2.addChild(
          new YMapControls({position: 'top'}).addChild(
            new YMapSearchControl({
                limit:5,
                options:{limit:5,results:5},
              searchResult: searchResultHandler2
            })
          )
        );

    // Creating handler functions for changing the clusterer. We will use these functions in a custom control
    // THe handler function for changing the number of clusterer points
    function changePointsCount(count: number) {
        pointsCount = count;
    }
    // The handler function for updating coordinates of clusterer points
    function updatePoints() {
        points = getRandomPoints(pointsCount, map.bounds);
        clusterer.update({features: points});
        if (!clusterer.parent) {
            markers.forEach((markerEl) => {
                map.removeChild(markerEl);
            });
            markers = [];
            points.forEach((feature) => {
                const markerElement = marker(feature);
                map.addChild(markerElement);
                markers.push(markerElement);
            });
        }
    }
    // The handler function for attach/detach the clusterer
    function toggleClusterer() {
        const button = document.getElementById('toggleBtn');
        if (clusterer.parent) {
            map.removeChild(clusterer);
            points.forEach((feature) => {
                const markerElement = marker(feature);
                map.addChild(markerElement);
                markers.push(markerElement);
            });
            button.innerText = 'Enable cluster mode';
        } else {
            map.addChild(clusterer);
            markers.forEach((markerEl) => {
                map.removeChild(markerEl);
            });
            markers = [];
            button.innerText = 'Disable cluster mode';
        }
    }


    map.addChild(
        // Using YMapControls you can change the position of the control
        new YMapControls({position: 'right'})
          // Add the geolocation control to the map
          .addChild(new YMapGeolocationControl(COMMON_LOCATION_PARAMS))
      );

     setTimeout("hGeolocationClick()",100);

































    function pointsFromDots2(){
        fa2 = [];
        let cntp = 0;
        console.log('pfd2');

        Object.keys(dots_ba).forEach(function(idx){
            let z = {
            type: 'Feature',
            id: cntp.toString(),
            addr:idx,
            gtins:dots_ba[idx].gtins,
            nm:dots_ba[idx].nm,
            geometry: {type: 'Point', coordinates: dots_ba[idx].pos.split(" ")}   
            };
            cntp++;
            fa2.push(z);
         });
    }



    function getProductIndex2(gtin){
            
        console.log('Getting products index 2  for '+gtin);
        let tgtin = gtin.substring(1);
        
          for (let i=0;i<cnt_meda;i++) {
            let zgt = products_meda[i]["gtins"];
            //console.log("testing ");
            console.log(zgt);
            if (Object.keys(zgt).includes(tgtin+'')) {console.log("RETURNUNG INDEX "+i); console.log(products_meda[i]); return i;}
            //if (zgt.indexOf(tgtin)>-1) {console.log("RETURNUNG INDEX "+i); console.log(products_meda[i]); return i;}
          }
          console.log("IDX FAIL");
          return 0;
        
        }
        
        function genPic2(gtin){
        
            console.log('generating pic by \''+gtin+'\'');
                let idx = getProductIndex2(gtin);
                //let pic = products[idx]["pictureset"]["bar"];
                let tgtin = gtin.substring(1);
                let pic = products_meda[idx]["gtins"][tgtin]["pic"];
                //console.log(products[idx]);
               // console.log(pic);
            let r = '<a target="_blank" href="https://mjolnir.pro/meda_catalog.html?gtin='+gtin+'"><div class="pdiv" style="background-image:url('+pic+');"></div></a>';
            return r;
        }
        

        function getDot2(z,x){
let k = 'no key';
            Object.keys(dots_ba).forEach(function(key){
                //console.log('testing '+key+ ' against '+z);
                if (String(z)==String(key)) k = key;
                if (dots_ba[key].id==x) k = key;
            });
            //console.log('getdot '+z+' '+x);
             //console.log('found key '+k);
             return dots_ba[String(k)];
        }


            function populate2(ev,ex){
                //console.log('_'+ev+'_');
                //console.log('_'+ex+'_');
                let el = $('.markerid2'+ex);
                let par = ev.parentElement;
                let id = ex;
                let addr = ev;

                let dot = getDot2(ev,ex);
                //console.log('the dot');
                //console.log(dot);

                //setTimeout("$('.markerid"+id+"').html('"+addr+"')",2000);
                //console.log('popping '+addr+' w id '+id);
                //console.log(el);
                //console.log('now');
                //console.log(dots);
                //console.log(addr);
                //console.log(dots[ev]);
                //console.log('parent');
                //console.log(par);
        
                let d = dots_ba[addr]["gtins"].split(",");
                //console.log('gtins'); console.log(d);
                let h = '<div class="smallpics">';
                    d.forEach( (gid)=>{
                        h += genPic2(gid);
                    });
                h+= '</div>';//<br/>'+dots[addr]["nm"];
        //console.log(h);

        h += '<br/><div class="addrdiv addr2'+ex+'" onclick="showAddress2('+ex+',\''+ev+'\'); event.stopPropagation(); return false;">Адрес&nbsp;<svg style="display:inline-block;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="13" height="13" viewBox="0 -50 256 256" xml:space="preserve"><g style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: none; fill-rule: nonzero; opacity: 1;" transform="translate(1.4065934065934016 1.4065934065934016) scale(2.81 2.81)">	<path d="M 90 24.25 c 0 -0.896 -0.342 -1.792 -1.025 -2.475 c -1.366 -1.367 -3.583 -1.367 -4.949 0 L 45 60.8 L 5.975 21.775 c -1.367 -1.367 -3.583 -1.367 -4.95 0 c -1.366 1.367 -1.366 3.583 0 4.95 l 41.5 41.5 c 1.366 1.367 3.583 1.367 4.949 0 l 41.5 -41.5 C 89.658 26.042 90 25.146 90 24.25 z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round"/></g></svg></div>'
        //h += '<br/><div class="addrdiv addr'+ex+'">'+ev.replace("+","")+'</div>';
        
                $('.markerid2'+ex).html(h);

                setTimeout("clearContent2('"+ex+"')",30000);

                //$(el).appendChild(h);

            }



    pointsFromDots2();

    //console.log(fa);



function clearMTO2(){
    clearTimeout(mTO2);
}

const marker2 = (feature: ExpandedFeature) => {
    const markerContainerElement = document.createElement('div');
    markerContainerElement.classList.add('marker-container');

    const markerText = document.createElement('div');
    markerText.id = feature.id;
    markerText.classList.add('marker-text', 'hidden');
    markerText.innerText = ' ';//NAMES[feature.id];
    markerText.classList.add('markerid2'+feature.id);
    markerText.setAttribute('addr2',feature.addr);

    markerText.onmouseover = () => {
        console.log('mover mtext');
        clearMTO();
    }

    markerText.onmouseout = () => {
        console.log('mout mtext');
        mTO = setTimeout("clearContent2('"+feature.id+"')",500);
        //$(markerText).html('');
    };
   //markerText.setAttribute('num',zcnt++);

    markerContainerElement.onmouseover = () => {
        markerText.classList.replace('hidden', 'visible');
        console.log('mover mc');
        clearMTO2();
    };

    markerContainerElement.onmouseout = () => {
        markerText.classList.replace('visible', 'hidden');

        if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)){
            console.log('mout mc');
            mTO2 = setTimeout("clearContent2('"+feature.id+"')",500);
        } //else setTimeout("clearContent('"+feature.id+"')",500);

        //$(markerText).html('');
    };

    const markerElement = document.createElement('div');
    markerElement.classList.add('marker');

    const markerImage = document.createElement('img');
    //markerImage.src = getImageSrc(feature.id);
    markerImage.classList.add('image');

    markerElement.appendChild(markerImage);

    markerContainerElement.appendChild(markerText);
    markerContainerElement.appendChild(markerElement);
    let tx = feature.addr;
    let zx = feature.id;

    const m2 = new YMapMarker({
            coordinates: feature.geometry.coordinates,
            onClick(e) {
                console.log('event');
                console.log(e);
                populate2(''+tx,''+zx);
                //const bounds = getBounds(features.map((feature: Feature) => feature.geometry.coordinates));
                //map.update({location: {bounds, ...COMMON_LOCATION_PARAMS}});
            },
            id:feature.addr,
            class:'marker'+zcnt,
            num:zcnt++
        },
        markerContainerElement
    );

    m2['addr'] = feature.addr;
    m2['num'] = zcnt++;
    m2['gtins'] = feature.gtins;

    console.log('this '+feature.addr+' '+feature.gtins);
    return m2;
};     
    const cluster2 = (coordinates: LngLat, features: Feature[]) =>
        new YMapMarker(
            {
                coordinates,
                onClick() {
                    const bounds = getBounds(features.map((feature: Feature) => feature.geometry.coordinates));
                    map2.update({location: {bounds, ...COMMON_LOCATION_PARAMS}});
                }
            },
            circle2(features.length).cloneNode(true) as HTMLElement
        );

    function circle2(count: number) {
        const circle = document.createElement('div');
        circle.classList.add('circle');
        circle.innerHTML = `
                  <div class="circle-content" style="z-index:10;">
                      <span class="circle-text">${count}</span>
                  </div>
              `;
        return circle;
    }

    const clusterer2 = new YMapClusterer({
        method: clusterByGrid({gridSize: 64}),
        features: fa2,
        marker:marker2,
        cluster:cluster2
    });
    map2.addChild(clusterer2);
    

    map2.addChild(
        // Using YMapControls you can change the position of the control
        new YMapControls({position: 'right'})
          // Add the geolocation control to the map
          .addChild(new YMapGeolocationControl(COMMON_LOCATION_PARAMS))
      );





    // Creating and adding a custom clusterer change element to the map
    /*
    map.addChild(
        new YMapControls({position: 'top right'}).addChild(
            new YMapControl().addChild(new ClustererChangeControl({toggleClusterer, changePointsCount, updatePoints}))
        )
    );
    */

}
