<script setup lang="ts">
import { onMounted, onUnmounted, ref, Ref, defineProps, computed } from 'vue';
import SectionMain from '@/Components/SectionMain.vue';
import { Map } from 'leaflet/src/map/index';
import { Rectangle } from 'leaflet';
import { canvas } from 'leaflet/src/layer/vector/Canvas';
import { svg } from 'leaflet/src/layer/vector/SVG';
import axios from 'axios';
import { LatLngBoundsExpression } from 'leaflet/src/geo/LatLngBounds';
import { tileLayerWMS } from 'leaflet/src/layer/tile/TileLayer.WMS';
import { TileLayer } from 'leaflet/src/layer/tile/TileLayer';
import { Attribution } from 'leaflet/src/control/Control.Attribution';
import DrawControlComponent from '@/Components/Map/draw.component.vue';
import ZoomControlComponent from '@/Components/Map/zoom.component.vue';
import { MapService } from '@/Stores/map.service';
import { LayerGroup } from 'leaflet/src/layer/LayerGroup';
import { OpensearchDocument } from '@/Dataset';

Map.include({
    // @namespace Map; @method getRenderer(layer: Path): Renderer
    // Returns the instance of `Renderer` that should be used to render the given
    // `Path`. It will ensure that the `renderer` options of the map and paths
    // are respected, and that the renderers do exist on the map.
    getRenderer: function (layer) {
        // @namespace Path; @option renderer: Renderer
        // Use this specific instance of `Renderer` for this path. Takes
        // precedence over the map's [default renderer](#map-renderer).
        var renderer = layer.options.renderer || this._getPaneRenderer(layer.options.pane) || this.options.renderer || this._renderer;

        if (!renderer) {
            renderer = this._renderer = this._createRenderer();
        }

        if (!this.hasLayer(renderer)) {
            this.addLayer(renderer);
        }
        return renderer;
    },

    _getPaneRenderer: function (name) {
        if (name === 'overlayPane' || name === undefined) {
            return false;
        }

        var renderer = this._paneRenderers[name];
        if (renderer === undefined) {
            renderer = this._createRenderer({ pane: name });
            this._paneRenderers[name] = renderer;
        }
        return renderer;
    },

    _createRenderer: function (options) {
        // @namespace Map; @option preferCanvas: Boolean = false
        // Whether `Path`s should be rendered on a `Canvas` renderer.
        // By default, all `Path`s are rendered in a `SVG` renderer.
        return (this.options.preferCanvas && canvas(options)) || svg(options);
    },
});
const DEFAULT_BASE_LAYER_NAME = 'BaseLayer';
const DEFAULT_BASE_LAYER_ATTRIBUTION = '&copy; <a target="_blank" href="http://osm.org/copyright">OpenStreetMap</a> contributors';
// const OPENSEARCH_HOST = 'http://localhost:9200';
const OPENSEARCH_HOST = `${process.env.OPENSEARCH_HOST}`;
// const OPENSEARCH_HOST = `http://${process.env.OPENSEARCH_PUBLIC_HOST}`;
let map: Map;

const props = defineProps({
    dheckable: Boolean,
    datasets: {
        type: Array<OpensearchDocument>,
        default: () => [],
    },
    mapId: {
        type: String,
        default: 'map',
    },
    mapOptions: {
        type: Object,
        default: () => ({
            center: [48.208174, 16.373819],
            zoom: 3,
            zoomControl: false,
            attributionControl: false,
        }),
    },
});

const items = computed({
    get() {
        return props.datasets;
    },
    // setter
    set(value) {
        // Note: we are using destructuring assignment syntax here.

        props.datasets.length = 0;
        props.datasets.push(...value);
    },
});

const fitBounds: LatLngBoundsExpression = [
    [46.4318173285, 9.47996951665],
    [49.0390742051, 16.9796667823],
];

// const mapId = 'map';
const drawControl: Ref<DrawControlComponent | null> = ref(null);
const southWest = ref(null);
const northEast = ref(null);
const mapService = MapService();

const filterLayerGroup = new LayerGroup();
// Replace with your actual data
// const datasets: Ref<OpensearchDocument[]> = ref([]);

onMounted(() => {
    initMap();
});

onUnmounted(() => {
    map.off('zoomend zoomlevelschange');
});

const initMap = async () => {
    // init leaflet map
    map = new Map('map', props.mapOptions);
    mapService.setMap(props.mapId, map);
    map.scrollWheelZoom.disable();
    map.fitBounds(fitBounds);
    drawControl.value?.toggleDraw();

    map.addLayer(filterLayerGroup);

    const attributionControl = new Attribution().addTo(map);
    attributionControl.setPrefix(false);

    let osmGgray = tileLayerWMS('https://ows.terrestris.de/osm-gray/service', {
        format: 'image/png',
        attribution: DEFAULT_BASE_LAYER_ATTRIBUTION,
        layers: 'OSM-WMS',
    });

    // let baseAt = new TileLayer('https://{s}.wien.gv.at/basemap/bmapgrau/normal/google3857/{z}/{y}/{x}.png', {
    //     subdomains: ['maps', 'maps1', 'maps2', 'maps3', 'maps4'],
    //     attribution: DEFAULT_BASE_LAYER_ATTRIBUTION,
    // });

    let layerOptions = {
        label: DEFAULT_BASE_LAYER_NAME,
        visible: true,
        layer: osmGgray,
    };
    layerOptions.layer.addTo(map);

    map.on('Draw.Event.CREATED', handleDrawEventCreated);

    // // const query = {
    // // 	query: {
    // // 		term: {
    // // 			id: "103"
    // // 		}
    // // 	}
    // // };
    // // to do : call extra method:
    // const query = {
    // 	// q: 'id:103'
    // 	// q: 'author:"Iglseder, Christoph" OR title:"Datensatz"',
    // 	// q: 'author:"Iglseder"',
    // 	q: '*',
    // 	_source: 'author,bbox_xmin,bbox_xmax,bbox_ymin,bbox_ymax,abstract,title',
    // 	size: 1000
    // 	// qf:"title^3 author^2 subject^1",
    // }
    // try {
    // 	let response = await axios({
    // 		method: 'GET',
    // 		url: OPEN_SEARCH_HOST + '/tethys-records/_search',
    // 		headers: { 'Content-Type': 'application/json' },
    // 		params: query
    // 	});
    // 	// Loop through the hits in the response
    // 	response.data.hits.hits.forEach(hit => {
    // 		// Get the geo_location attribute
    // 		// var geo_location = hit._source.geo_location;
    // 		let xMin = hit._source.bbox_xmin;
    // 		let xMax = hit._source.bbox_xmax;
    // 		let yMin = hit._source.bbox_ymin;
    // 		let yMax = hit._source.bbox_ymax;
    // 		var bbox: LatLngBoundsExpression = [[yMin, xMin], [yMax, xMax]];
    // 		// Parse the WKT string to get the bounding box coordinates
    // 		// var bbox = wktToBbox(geo_location);

    // 		// // Add the bounding box to the map as a rectangle
    // 		new Rectangle(bbox, { color: "#ff7800", weight: 1 }).addTo(map);
    // 		// console.log(hit._source);
    // 	});
    // } catch (error) {
    // 	console.error(error);
    // }
};

const handleDrawEventCreated = async (event) => {
    filterLayerGroup.clearLayers();
    items.value = [];

    let layer = event.layer;
    let bounds = layer.getBounds();
    // coverage.x_min = bounds.getSouthWest().lng;
    // coverage.y_min = bounds.getSouthWest().lat;
    // coverage.x_max = bounds.getNorthEast().lng;
    // coverage.y_max = bounds.getNorthEast().lat;

    try {
        let response = await axios({
            method: 'POST',
            url: OPENSEARCH_HOST + '/tethys-records/_search',
            headers: { 'Content-Type': 'application/json' },
            data: {
                size: 1000,
                query: {
                    bool: {
                        must: {
                            match_all: {},
                        },
                        filter: {
                            geo_shape: {
                                geo_location: {
                                    // replace 'location' with your geo-point field name
                                    shape: {
                                        type: 'envelope',
                                        coordinates: [
                                            [bounds.getSouthWest().lng, bounds.getNorthEast().lat],
                                            [bounds.getNorthEast().lng, bounds.getSouthWest().lat],
                                        ],
                                    },
                                    relation: 'within',
                                },
                            },
                        },
                        // _source: 'author,bbox_xmin,bbox_xmax,bbox_ymin,bbox_ymax,abstract,title',
                        // "size": 1000
                    },
                },
            },
        });
        // Loop through the hits in the response
        response.data.hits.hits.forEach((hit) => {
            // Get the geo_location attribute
            // var geo_location = hit._source.geo_location;
            let xMin = hit._source.bbox_xmin;
            let xMax = hit._source.bbox_xmax;
            let yMin = hit._source.bbox_ymin;
            let yMax = hit._source.bbox_ymax;
            var bbox: LatLngBoundsExpression = [
                [yMin, xMin],
                [yMax, xMax],
            ];
            // Parse the WKT string to get the bounding box coordinates
            // var bbox = wktToBbox(geo_location);

            // // Add the bounding box to the map as a rectangle
            let rect = new Rectangle(bbox, { color: '#ff7800', weight: 1 });
            filterLayerGroup.addLayer(rect);
            // add to result list
            items.value.push(hit._source);
        });
    } catch (error) {
        console.error(error);
    }
};
</script>

<template>
    <SectionMain>        
            <div id="map" class="map-container mt-6 mb-6 rounded-2xl py-12 px-6 text-center dark:bg-slate-900 bg-white">
                <ZoomControlComponent ref="zoomControl" :mapId="mapId"></ZoomControlComponent>
                <DrawControlComponent ref="drawControl" :preserve="false" :mapId="mapId" :southWest="southWest"
                    :northEast="northEast">
                </DrawControlComponent>
            </div>   
    </SectionMain>   
</template>


<style lang="css">
/* .leaflet-container {
    height: 600px;
    width: 100%;
    background-color: transparent;
    outline-offset: 1px;
} */
.leaflet-container {
    height: 600px;
    width: 100%;
}

.leaflet-container .leaflet-pane {
    z-index: 30!important;
}
</style>