<template>
  <div style="height: 600px; width: 800px; color: #000000">
    <L-Map
      @ready="onMapReady"
      ref="mapRef"
      :zoom="zoom"
      :center="center"
      style="height: 500px; width: 100%"
      @click="updateMarker"
    >
      <L-Tile-Layer
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        layer-type="base"
        name="OpenStreetMap"
        @click="updateMarker($event.latlng)"
      ></L-Tile-Layer>
      <L-Marker :lat-lng="markerLatLng" @click="handleMarkerClick"></L-Marker>
      <L-Routing-Machine
        @routingstart="debugRoutingEvent"
        @routesfound="debugRoutingEvent"
        @routingerror="debugRoutingEvent"
        :waypoints="waypoints"
      />
    </L-Map>
  </div>
</template>

<script setup lang="ts">
import { useQuasar } from 'quasar';
import { ref } from 'vue';
import { GeoSearchControl, OpenStreetMapProvider } from 'leaflet-geosearch';
import LRoutingMachine from 'components/LRoutingMachine.vue';
import 'leaflet-geosearch/dist/geosearch.css';
import 'leaflet/dist/leaflet.css';

import type { coords, SearchControlProps } from 'src/types';
import type { Map, LeafletMouseEvent } from 'leaflet';

import { storeToRefs } from 'pinia';
import { useSocketioStore } from 'stores/socketio';
import { useLeafletStore } from 'stores/leaflet';

import SetLocationDialog from 'components/SetLocationDialog.vue';
import { LMap, LMarker, LTileLayer } from '@vue-leaflet/vue-leaflet';

const waypoints = [
  [ 38.7436056, -9.2304153 ],
  [ 38.7436056, -0.131281 ],
];


const leafletStore = useLeafletStore();
const socketStore = useSocketioStore();
const { zoom, center, markerLatLng } = storeToRefs(socketStore);
const $q = useQuasar();
const mapRef = ref(null);
const responseMessage = ref('');

const debugRoutingEvent = (event) => {
  console.log(`${event.type} event: `, event);
};

const onMapReady = (map: Map) => {
  const provider = new OpenStreetMapProvider();
  const searchOptions: SearchControlProps = {
    provider: provider,
    showMarker: false,
    autoClose: true,
    updateMap: true,
    showPopup: true,
    style: 'bar',
    acceptAutoLoad: true,
    autoComplete: true,
    autoCompleteDelay: 250,
    retainZoomLevel: false,
    animateZoom: true,
    keepResult: true,
  };

  const searchControl = GeoSearchControl(searchOptions);
  map.addControl(searchControl);
};

function updateMarker(event: LeafletMouseEvent) {
  markerLatLng.value = [event.latlng.lat, event.latlng.lng];
  center.value = [event.latlng.lat, event.latlng.lng];
}

function handleMarkerClick(event: LeafletMouseEvent) {
  $q.dialog({
    component: SetLocationDialog,
    componentProps: {
      lat: event.latlng.lat,
      lng: event.latlng.lng,
    },
  })
    .onOk((delay: number) => {
      void setLocation({ lat: event.latlng.lat, lng: event.latlng.lng }, delay);
      console.log(
        'Confirmed location add: latitude: ' +
          event.latlng.lat +
          ', longitude: ' +
          event.latlng.lng +
          ', delay: ' +
          delay,
      );
    })
    .onCancel(() => {
      console.log('Dialog cancelled');
    })
    .onDismiss(() => {
      console.log('Dialog dismissed');
    });
}

function setLocation(coords: coords, delay: number) {
  try {
    responseMessage.value = socketStore.simulationControl('add', delay, coords.lat, coords.lng);
    $q.notify({ type: 'positive', message: responseMessage.value });
  } catch (error: unknown) {
    if (error instanceof Error) {
      console.error('Error setting location:', error.message);
      responseMessage.value = `Failed to set location: ${error.message}`;
    } else {
      console.error('Error setting location:', error);
      responseMessage.value = `Failed to set location: Unknown error`;
    }
    $q.notify({ type: 'negative', message: responseMessage.value });
  }
}
</script>

<style>
.l-map {
  height: 100vh;
  width: 100vw;
}
</style>
