<template>
  <div class="">
    <q-layout
      view="hHh Lpr fFf"
      container
      style="height: 600px; max-width: 800px; width: 100vw"
      class="rounded-borders"
    >
      <q-footer
        :class="$q.dark.isActive ? 'bg-primary' : 'bg-black'"
        class="z-top"
        style="height: 48px"
      >
        <q-toolbar>
          <q-btn
            class="q-mr-sm"
            dense
            flat
            icon="mdi-menu"
            round
            size="sm"
            @click="qLocDrawer = !qLocDrawer"
          />
          <q-btn-dropdown flat label="Zoom To" size="sm" stretch>
            <q-list>
              <q-item v-close-popup v-ripple clickable @click="zoomTo('fmLoc')">
                <q-item-section>
                  <q-item-label>Find My Location</q-item-label>
                </q-item-section>
              </q-item>
              <q-item v-close-popup v-ripple clickable @click="zoomTo('simLoc')">
                <q-item-section>
                  <q-item-label>Sim Location</q-item-label>
                </q-item-section>
              </q-item>
            </q-list>
          </q-btn-dropdown>
          <q-btn-dropdown label="Routing" size="sm" stretch v-if="routeIsSet">
            <q-list>
              <q-item v-close-popup v-ripple clickable @click="routeToQueue">
                <q-item-section>
                  <q-item-label>Route Waypoints to SimQ</q-item-label>
                </q-item-section>
              </q-item>
              <q-item v-close-popup v-ripple clickable @click="routeAllPointsToQueue">
                <q-item-section>
                  <q-item-label>Route to SimQ</q-item-label>
                </q-item-section>
              </q-item>
              <q-item v-close-popup v-ripple clickable @click="clearRoute">
                <q-item-section>
                  <q-item-label>clearRoute</q-item-label>
                </q-item-section>
              </q-item>
            </q-list>
          </q-btn-dropdown>
        </q-toolbar>
      </q-footer>
      <q-drawer
        v-model="qLocDrawer"
        :width="300"
        side="left"
        :breakpoint="500"
        class="leafletDrawer"
      >
        <div class="full-height column no-wrap">
          <q-list padding>
            <q-item class="q-gutter-x-md">
              <q-item-section avatar>
                <q-item-label
                  ><span class="text-weight-bolder text-accent text-h6">Queue: </span><span :class="(simulationRunning)? 'text-positive' : 'text-negative'">{{ toTitleCase(simulationState) }}</span></q-item-label
                >
              </q-item-section>
              <q-item-section>
                <q-select
                  v-model="showItems"
                  :options="drawerOptions"
                  label="Items to Show"
                  dense
                  style="max-width: 125px"
                />
              </q-item-section>
            </q-item>
          </q-list>
          <q-separator />
          <q-scroll-area :horizontal-thumb-style="{ opacity: '50' }" class="col">
            <q-list padding>
              <VueDraggable
                ref="el"
                v-model="locationQueueOrderFiltered"
                handle=".drag-handle"
                :isDisabled="disableDraggable"
              >
                <LocationItem
                  v-for="(key, index) in locationQueueOrderFiltered"
                  :class="isDraggable(key)"
                  :key="key"
                  :loc_id="key"
                  :active="
                    (locationQueueData as Record<string, any>)[key]?.loc_id ===
                    currentLocation?.loc_id
                  "
                  :isCurrentDelay="
                    (locationQueueData as Record<string, any>)[key]?.loc_id ===
                    locationQueueOrderFiltered[index + 1]
                  "
                  :index="index"
                  :isLast="index == locationQueueOrderFiltered.length - 1"
                  :start="(locationQueueData as Record<string, any>)[key]?.start ?? ''"
                  :address="(locationQueueData as Record<string, any>)[key]?.address ?? ''"
                  :latitude="(locationQueueData as Record<string, any>)[key]?.latitude ?? 0"
                  :longitude="(locationQueueData as Record<string, any>)[key]?.longitude ?? 0"
                  :delay="(locationQueueData as Record<string, any>)[key]?.delay ?? 0"
                  :end="(locationQueueData as Record<string, any>)[key]?.end ?? undefined"
                  :status="(locationQueueData as Record<string, any>)[key]?.status ?? undefined"
                  @item-clicked="zoomToCoords"
                  @contextmenu.prevent="onDrawerContextMenu($event, key)"
                  active-class="text-orange"
                />
              </VueDraggable>
            </q-list>
          </q-scroll-area>
          <q-menu ref="contextMenu" context-menu touch-position>
            <q-list>
              <q-item clickable ripple v-close-popup @click="handleDrawerContextMenu('zoom')">
                <q-item-section label="Zoom to Location"> Zoom </q-item-section>
              </q-item>
              <q-item clickable ripple v-close-popup @click="handleDrawerContextMenu('delete')">
                <q-item-section label="Zoom to Location"> Delete </q-item-section>
              </q-item>
              <q-item clickable ripple v-close-popup @click="handleDrawerContextMenu('gp')">
                <q-item-section label="Zoom to Location"> Go Now </q-item-section>
              </q-item>
            </q-list>
          </q-menu>
        </div>
      </q-drawer>

      <q-page-container>
        <q-page>
          <div style="height: 550px; width: 100vw; max-width: 800px; color: #000000">
            <L-Map
              id="map"
              ref="mapRef"
              :center="safeCenter"
              :zoom="zoom"
              style="height: 550px; width: 100vw; max-width: 800px"
              @click="updateMarker"
              @ready="onMapReady"
            >
              <L-Tile-Layer
                layer-type="base"
                name="OpenStreetMap"
                url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
              ></L-Tile-Layer>
              <L-Layer-Group>
                <L-Marker
                  v-if="safeMarkerLatLng"
                  :lat-lng="safeMarkerLatLng"
                  @click="handleMarkerClick"
                >
                  <L-Popup
                    :options="{ closeOnClick: true, closeButton: false, className: 'marker-popup' }"
                  >
                    <q-list dense seperator style="min-width: 100px" class="bg-grey-10">
                      <q-item clickable v-ripple @click="handleAddLocation">
                        <q-item-section avatar>
                          <q-avatar
                            icon="mdi-map-marker"
                            color="accent"
                            text-color="white"
                            size="sm"
                          />
                        </q-item-section>
                        <q-item-section>Add Location</q-item-section>
                      </q-item>
                      <q-item clickable v-ripple @click="setStartRoute">
                        <q-item-section avatar>
                          <q-avatar color="accent" size="sm">
                            <q-icon class="small-icon" v-html="iconElement(startIcon).outerHTML" />
                          </q-avatar>
                        </q-item-section>
                        <q-item-section>Set Route Start</q-item-section>
                      </q-item>
                      <q-item clickable v-ripple @click="setEndRoute">
                        <q-item-section avatar>
                          <q-avatar color="accent" size="sm">
                            <q-icon class="small-icon" v-html="iconElement(endIcon).outerHTML" />
                          </q-avatar>
                        </q-item-section>
                        <q-item-section>Set Route End</q-item-section>
                      </q-item>
                      <q-item clickable v-ripple @click="handleFavorite('set')" v-if="!isFavorite">
                        <q-item-section avatar>
                          <q-avatar
                            icon="mdi-star-outline"
                            color="accent"
                            text-color="yellow"
                            size="sm"
                          />
                        </q-item-section>
                        <q-item-section>Set Favorite</q-item-section>
                      </q-item>
                      <q-item clickable v-ripple @click="handleFavorite('clear')" v-else>
                        <q-item-section avatar>
                          <q-avatar icon="mdi-star" color="accent" text-color="yellow" size="sm" />
                        </q-item-section>
                        <q-item-section>Clear Favorite</q-item-section>
                      </q-item>
                    </q-list>
                  </L-Popup>
                </L-Marker>
              </L-Layer-Group>
              <L-Layer-Group v-if="locationQueueOrder">
                <L-Marker
                  v-for="locid in locationQueueOrderFiltered"
                  :key="locid"
                  :icon="getCustomIcon(locid) as any"
                  :lat-lng="[
                    (locationQueueData as Record<string, any>)[locid]?.latitude ?? 0,
                    (locationQueueData as Record<string, any>)[locid]?.longitude ?? 0,
                  ]"
                >
                </L-Marker>
              </L-Layer-Group>
              <L-Layer-Group v-if="routeSet.start || routeSet.end">
                <LRoutingMachine
                  v-bind="routingOptions"
                  @routingstart="debugRoutingEvent"
                  @routesfound="handleRoutesFound"
                  @routingerror="debugRoutingEvent"
                />
              </L-Layer-Group>
              <L-Layer-Group v-if="findMyUpdate && showFindMy">
                <L-Marker
                  v-if="findMyUpdate"
                  :icon="fmIcon as any"
                  :lat-lng="[findMyUpdate.latitude ?? 0, findMyUpdate.longitude ?? 0]"
                >
                  <L-Popup
                    :options="{ closeOnClick: true, closeButton: false, className: 'marker-popup' }"
                  >
                    <q-list dense seperator style="min-width: 100px" class="bg-grey-10">
                      <q-item clickable v-ripple @click="handleAddLocation">
                        <q-item-section avatar>
                          <q-avatar
                            icon="add_location"
                            color="primary"
                            text-color="white"
                            size="sm"
                          />
                        </q-item-section>
                        <q-item-section>Add Location</q-item-section>
                      </q-item>
                      <q-item clickable v-ripple @click="setStartRoute">
                        <q-item-section avatar>
                          <q-avatar size="sm">
                            <q-icon v-html="iconElement(startIcon).outerHTML" />
                          </q-avatar>
                        </q-item-section>
                        <q-item-section>Set Route Start</q-item-section>
                      </q-item>
                      <q-item clickable v-ripple @click="setEndRoute">
                        <q-item-section avatar>
                          <q-avatar
                            icon="add_location"
                            color="primary"
                            text-color="white"
                            size="sm"
                          />
                        </q-item-section>
                        <q-item-section>Set Route End</q-item-section>
                      </q-item>
                    </q-list>
                  </L-Popup>
                  <L-Tooltip>
                    {{ findMyTimePast }}
                  </L-Tooltip>
                </L-Marker>
                <L-Circle
                  :fillOpacity="0.5"
                  :lat-lng="[findMyUpdate.latitude ?? 0, findMyUpdate.longitude ?? 0]"
                  :radius="findMyUpdate.horizontalAccuracy"
                  color="#f5bb39"
                  fillColor="indianred"
                ></L-Circle>
              </L-Layer-Group>
            </L-Map>
          </div>
        </q-page>
      </q-page-container>
    </q-layout>
  </div>
</template>

<script lang="ts" setup>
import { useQuasar } from 'quasar';
import { computed, markRaw, onMounted, onUnmounted, reactive, ref } from 'vue';

// Draggable imports
import { VueDraggable } from 'vue-draggable-plus';

// Leaflet imports
import { GeoSearchControl, OpenStreetMapProvider } from 'leaflet-geosearch';
import 'leaflet-routing-machine/dist/leaflet-routing-machine.css';
import {
  Icon,
  PinCirclePanel,
  PinStarPanel,
  PinTriangle,
  PinSquare,
  ChipCircle,
} from 'leaflet-extra-markers';
import 'leaflet-geosearch/dist/geosearch.css';
import 'leaflet/dist/leaflet.css';
import {
  LCircle,
  LLayerGroup,
  LMap,
  LMarker,
  LPopup,
  LTileLayer,
  LTooltip,
} from '@vue-leaflet/vue-leaflet';
import * as LeafLet from 'leaflet';

// Custom Components
import LRoutingMachine from 'components/LRoutingMachine.vue';
import LocationItem from 'components/LocationItem.vue';
import SetLocationDialog from 'components/SetLocationDialog.vue';
import EditFavoriteDialog from 'components/EditFavoriteDialog.vue';
import { customRouter } from 'functions/serviceURL';
import { useRoutingEvents } from '../composables/useRoutingEvents';
import { useMarkerContextMenu } from '../composables/useMarkerContextMenu';
import type { IRouter } from 'leaflet-routing-machine';
import { reverseGeocodeRateLimited } from 'functions/reverseGeocodeSocket';

// Types
import type { coords, SearchControlProps } from 'components/models';
import type { LeafletMouseEvent, Map } from 'leaflet';

// Stores
import { storeToRefs } from 'pinia';
import { useSocketStore } from 'stores/socket';
import { useSimulationStore } from 'stores/simulation';
import { useLeafletStore } from 'stores/leaflet';
import { useIcloudStore } from 'stores/icloud';
import { favorites } from 'constants/favorites';

const socketStore = useSocketStore();

const leafletStore = useLeafletStore();
const { zoom, center, markerLatLng, qLocDrawer, routeSet, routeDirections, routeCoordinates } =
  storeToRefs(leafletStore);

const simulationStore = useSimulationStore();
const { currentLocation, locationQueueData, locationQueueOrder, simulationState, simulationRunning } =
  storeToRefs(simulationStore);

const icloudStore = useIcloudStore();
const { findMyUpdate } = storeToRefs(icloudStore);

const $q = useQuasar();

const now = ref(Date.now());
const mapRef = ref();
const responseMessage = ref('');
const safeCenter = computed<[number, number]>(() => {
  const lat = center.value?.[0];
  const lng = center.value?.[1];
  if (typeof lat === 'number' && typeof lng === 'number') {
    return [lat, lng];
  }
  return [favorites.home.coords.lat, favorites.home.coords.lng];
});
const safeMarkerLatLng = computed<[number, number] | null>(() => {
  const lat = markerLatLng.value?.[0];
  const lng = markerLatLng.value?.[1];
  if (typeof lat === 'number' && typeof lng === 'number') {
    return [lat, lng];
  }
  return null;
});

const drawerOptions = ['All', 'Done', 'Queued', 'Deleted'];
const showItems = ref('All');
const disableDraggable = computed(() => {
  return showItems.value === 'All';
});

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

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

const fmIcon = new Icon({
  color: 'indianred',
  accentColor: 'firebrick',
  content: 'FM',
  contentColor: 'white',
  scale: 1,
  svg: PinCirclePanel,
});

const startIcon = new Icon({
  color: '#006838',
  accentColor: 'rgba(0,0,0,0.25)',
  content: 'S',
  contentColor: 'white',
  scale: 1,
  svg: PinTriangle,
});

const iconElement = (icon: Icon) => {
  return icon.createIcon();
};

const endIcon = new Icon({
  color: '#a23337',
  accentColor: 'rgba(0,0,0,0.25)',
  content: 'E',
  contentColor: 'white',
  scale: 1,
  svg: PinSquare,
});

const intermediateIcon = new Icon({
  color: 'cornflowerblue',
  accentColor: 'rgba(0,0,0,0.25)',
  contentColor: 'white',
  svg: ChipCircle,
  scale: 1,
});

type RoutingWaypoint = {
  latLng: LeafLet.LatLng;
};

const locationQueueOrderFiltered = computed({
  get: () => {
    if (locationQueueOrder.value) {
      return locationQueueOrder.value.filter(
        (loc_id) => locationQueueData.value[loc_id]?.status !== 'deleted',
      );
    } else {
      return [];
    }
  },
  set: (val) => {
    simulationStore.updateLocationQueueOrder(val);
  },
});

const isDraggable = (locid: string) => {
  const currentIndex = currentLocation.value
    ? locationQueueOrderFiltered.value.indexOf(currentLocation.value.loc_id)
    : 0;
  const myIndex = locationQueueOrder.value.indexOf(locid);
  const myUpdatedIndex = myIndex - currentIndex;
  if (myUpdatedIndex > 1) {
    return 'draggable';
  } else {
    return 'undraggable';
  }
};

const getCustomIcon = (locid: string) => {
  const currentIndex = currentLocation.value
    ? locationQueueOrderFiltered.value.indexOf(currentLocation.value.loc_id)
    : 0;
  const locationIndex = locationQueueOrderFiltered.value.indexOf(locid);
  const updatedIndex = locationIndex - currentIndex;
  if (currentLocation.value && currentLocation.value.loc_id === locid) {
    return new Icon({
      color: 'pink',
      accentColor: 'black',
      content: '*',
      contentColor: 'black',
      scale: 1,
      svg: PinStarPanel,
    });
  }
  if (updatedIndex > 0) {
    return new Icon({
      color: 'blue',
      accentColor: 'firebrick',
      content: updatedIndex.toString(),
      contentColor: 'white',
      scale: 1,
      svg: PinCirclePanel,
    });
  } else {
    return new Icon({
      color: 'black',
      accentColor: 'grey',
      content: updatedIndex.toString(),
      contentColor: 'white',
      scale: 1,
      svg: PinCirclePanel,
    });
  }
};

const routingOptions = reactive<{
  waypoints: LeafLet.LatLng[];
  router: IRouter;
  routeWhileDragging: boolean;
  createMarker: (i: number, waypoint: RoutingWaypoint, n: number) => LeafLet.Marker | false;
}>({
  createMarker: function (i, waypoint, n) {
    let icon;
    if (i === 0) {
      icon = startIcon;
    } else if (i === n - 1) {
      icon = endIcon;
    } else {
      icon = intermediateIcon;
    }
    return LeafLet.marker(waypoint.latLng, {
      draggable: true,
      icon,
      contextmenu: false,
      contextmenuItems: [],
    });
  },
  routeWhileDragging: true,
  router: markRaw(customRouter),
  waypoints: [],
});

const { handleRoutesFound } = useRoutingEvents();

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

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

function closeAllPopups() {
  if (mapRef.value) {
    // Access the Leaflet map instance directly
    mapRef.value.leafletObject.closePopup();
  }
}

const delay = (ms: number) => new Promise((res) => setTimeout(res, ms));

async function routeToQueue() {
  if (routeSet.value.start && routeSet.value.end && routeDirections) {
    if (routeDirections.value && routeDirections.value.length > 0) {
      for (const direction of routeDirections.value) {
        if (direction.coordinates) {
          await addLocation(
            { lat: Number(direction.coordinates.lat), lng: Number(direction.coordinates.lng) },
            direction.time,
            true,
          );
        }
        await delay(1000);
      }
    }
  }
}

async function routeAllPointsToQueue() {
  if (routeSet.value.start && routeSet.value.end && routeCoordinates) {
    if (routeCoordinates.value && routeCoordinates.value.length > 0) {
      for (const coord of routeCoordinates.value) {
        if (coord) {
          await addLocation(
            { lat: Number(coord.lat), lng: Number(coord.lng) },
            coord.timeFromPrev,
            false,
          );
        }
        await delay(1000);
      }
    }
  }
}

/* function routeToQueue() {
  console.log('routeToQueue');
  if (routeSet.value.start && routeSet.value.end && routeSegments) {
    console.log('routeToQueue: start: ', routeSet.value.start);
    setLocation(
      { lat: Number(routeSet.value.start.lat), lng: Number(routeSet.value.start.lng) },
      0,
    );
    if (routeSegments.value) {
      routeSegments.value.forEach((segment: routeSegments) => {
        console.log('routeToQueue: segment: ', segment);
        setLocation(
          { lat: Number(segment.toCoordinates.lat), lng: Number(segment.toCoordinates.lng) },
          segment.timeSeconds,
        );
      });
    }
    console.log('routeToQueue: end: ', routeSet.value.end);
    setLocation({ lat: Number(routeSet.value.end.lat), lng: Number(routeSet.value.end.lng) }, 0);
  }
}
 */
function clearRoute() {
  void leafletStore.clearRouteSegments;
  routingOptions.waypoints = [];
  routeSet.value.start = { lat: null, lng: null };
  routeSet.value.end = { lat: null, lng: null };
  $q.notify({ type: 'positive', message: 'Route cleared' });
}

const updateRoute = () => {
  const waypoints: LeafLet.LatLng[] = [];
  const start = routeSet.value.start;
  const end = routeSet.value.end;
  if (start && typeof start.lat === 'number' && typeof start.lng === 'number') {
    waypoints.push(LeafLet.latLng(start.lat, start.lng));
  }
  if (end && typeof end.lat === 'number' && typeof end.lng === 'number') {
    waypoints.push(LeafLet.latLng(end.lat, end.lng));
  }

  routingOptions.waypoints = waypoints;
};

const { isFavorite, handleMarkerClick, clickedLatLng, setStartRoute, setEndRoute } =
  useMarkerContextMenu(routeSet, updateRoute, closeAllPopups);

const routeIsSet = computed(() => {
  return (
    routeSet.value.start.lat &&
    routeSet.value.start.lng &&
    routeSet.value.end.lat &&
    routeSet.value.end.lng
  );
});

const selectedItem = ref();
const contextMenu = ref();

function toTitleCase(word: string | null | undefined) {
  if (!word) return '';
  return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
}

function onDrawerContextMenu(e: MouseEvent, item: string) {
  console.log('onDrawerContextMenu: ', item);
  selectedItem.value = item;
}
function handleDrawerContextMenu(command: string) {
  let notType: string = 'positive';
  let notMsg: string = '';
  switch (command) {
    case 'zoom':
      zoomTo(selectedItem.value);
      break;
    case 'delete':
      try {
        const ack = simulationStore.simulationControl({
          command: 'delete',
          latitude: 0,
          longitude: 0,
          loc_id: selectedItem.value,
          delay: 0,
          address: '',
        });
        if (ack.sts === 'error') {
          notType = 'negative';
        }
        if (ack.msg) {
          notMsg = ack.msg;
        }
        if (ack.sts === 'error') {
          notType = 'negative';
        }
        if (ack.msg) {
          notMsg = ack.msg;
        }
      } catch (error: unknown) {
        notType = 'negative';
        if (error instanceof Error) {
          console.error('Simulation Command ERROR: ', error.message);
          notMsg = `Simulation Command Error: ${error.message}`;
        } else {
          console.error('Simulation Command Error: ', error);
          notMsg = 'Simulation Command Error: Unknow error';
        }
      } finally {
        $q.notify({ type: notType, message: notMsg });
      }
  }
  $q.notify(`context menu: ${command} ${selectedItem.value}`);
}

function handleFavorite(operation: string) {
  if (clickedLatLng.value) {
    const latlng = clickedLatLng.value;
    closeAllPopups();
    $q.notify(`${operation} favorite...${latlng.toString()}`);
    $q.dialog({
      component: EditFavoriteDialog,
      componentProps: {
        lat: Number(latlng.lat),
        lng: Number(latlng.lng),
        isFavorite: isFavorite.value,
        operation: operation,
      },
    })
      .onOk(({ operation, lat, lng, name, category, icon }) => {
        //        void setFavorite({ lat: Number(lat), lng: Number(lng) }, name, category, icon);
        console.log(
          'Confirmed favorite ' +
            operation +
            ': ' +
            lat +
            ', ' +
            lng +
            ', name: ' +
            name +
            ', category: ' +
            category +
            ', icon: ' +
            icon,
        );
      })
      .onCancel(() => {
        console.log('Dialog cancelled');
      })
      .onDismiss(() => {
        console.log('Dialog dismissed');
      });
  }
}

function handleAddLocation() {
  if (clickedLatLng.value) {
    const latlng = clickedLatLng.value;
    closeAllPopups();
    $q.notify(`add location...${latlng.toString()}`);
    $q.dialog({
      component: SetLocationDialog,
      componentProps: {
        lat: Number(latlng.lat),
        lng: Number(latlng.lng),
      },
    })
      .onOk(({ delay, address }) => {
        const revGeo = !address;
        void addLocation(
          { lat: Number(latlng.lat), lng: Number(latlng.lng) },
          delay,
          revGeo,
          address,
        );
        console.log(
          'Confirmed location add: latitude: ' +
            latlng.lat +
            ', longitude: ' +
            latlng.lng +
            ', delay: ' +
            delay,
        );
      })
      .onCancel(() => {
        console.log('Dialog cancelled');
      })
      .onDismiss(() => {
        console.log('Dialog dismissed');
      });
  }
}
/*
async function reverseGeocode(lat: number, lng: number) {
  loading.value = true;
  try {
    const response = await reverseGeocodeRateLimited(lat, lng);
    console.log('reverse geocode response: ', response);
    return response;
  } catch (error) {
    console.error('Error fetching reverse geocode:', error);
    throw error;
  } finally {
    loading.value = false;
  }
}


async function addLocation(
  coords: coords,
  delay: number | undefined,
  getRevGeocode: boolean,
  address?: string,
) {
  return new Promise((resolve, reject) => {
    let notType: string = 'positive';
    try {
      let revGeo;
      if (!address && getRevGeocode) {
        revGeo = reverseGeocodeRateLimited(coords.lat, coords.lng);
      }
      const addy = address ?? revGeo?.address;
      const setCmdRsp = simulationStore.simulationControl({
        command: 'add',
        latitude: coords.lat,
        longitude: coords.lng,
        loc_id: '',
        delay: delay,
        address: addy,
      });
      if (setCmdRsp.msg) {
        responseMessage.value = setCmdRsp.msg;
      }
      if (setCmdRsp.sts === 'error') {
        notType = 'negative';
        reject(new Error(setCmdRsp.msg || 'Unknown error'));
      }
      resolve(setCmdRsp);
    } catch (error: unknown) {
      notType = 'negative';
      if (error instanceof Error) {
        console.error('Error setting location:', error.message);
        responseMessage.value = `Failed to set location: ${error.message}`;
        reject(error);
      } else {
        console.error('Error setting location:', error);
        responseMessage.value = `Failed to set location: Unknown error`;
        reject(new Error('Unknown error'));
      }
    } finally {
      $q.notify({ type: notType, message: responseMessage.value });
    }
  });
}
*/

async function addLocation(
  coords: coords,
  delay: number | undefined,
  getRevGeocode: boolean,
  address?: string,
) {
  let notType: string = 'positive';
  let revGeo;
  if (!address && getRevGeocode) {
    revGeo = await reverseGeocodeRateLimited(coords.lat, coords.lng);
  }
  const addy = address ?? revGeo?.address;
  const setCmdRsp = simulationStore.simulationControl({
    command: 'add',
    latitude: coords.lat,
    longitude: coords.lng,
    loc_id: '',
    delay: delay,
    address: addy,
  });
  if (setCmdRsp.sts === 'error') {
    notType = 'negative';
    responseMessage.value = 'Failed to set location: ' + setCmdRsp.msg;
    console.error('Error setting location:', setCmdRsp.msg);
  }
  if (setCmdRsp.msg) {
    responseMessage.value = setCmdRsp.msg;
  }
  $q.notify({ type: notType, message: responseMessage.value });
}

function zoomToCoords(arg: string) {
  console.log('zoomToCoords: ', arg);
  const item = locationQueueData.value[arg];
  if (!item || item.latitude == null || item.longitude == null) {
    return;
  }
  leafletStore.setCenter(item.latitude, item.longitude);
  leafletStore.setZoom(50);
  qLocDrawer.value = false;
}

const showFindMy = computed(() => {
  if (findMyUpdate.value) {
    const diffInSec = Math.floor(Math.abs(now.value - findMyUpdate.value.timeStamp) / 1000);
    return diffInSec < 120;
  } else {
    return false;
  }
});

const findMyTimePast = computed(() => {
  if (findMyUpdate.value) {
    const diffInMs = Math.abs(now.value - findMyUpdate.value.timeStamp);
    const seconds = Math.floor((diffInMs / 1000) % 60);
    const minutes = Math.floor((diffInMs / (1000 * 60)) % 60);
    const hours = Math.floor((diffInMs / (1000 * 60 * 60)) % 24);
    const days = Math.floor(diffInMs / (1000 * 60 * 60 * 24));

    if (days > 1) {
      return (
        days + ' days, ' + hours + ' hours, ' + minutes + 'minutes, ' + seconds + 'seconds ago'
      );
    } else if (hours > 1) {
      return hours + ' hours, ' + minutes + 'minutes, ' + seconds + 'seconds ago';
    } else if (minutes > 1) {
      return minutes + ' minutes, ' + seconds + ' seconds ago';
    } else {
      return seconds + ' seconds ago';
    }
  } else {
    return 'Find My Location not available';
  }
});

function zoomTo(loc: string) {
  switch (loc) {
    case 'fmLoc':
      if (findMyUpdate.value && findMyUpdate.value.latitude && findMyUpdate.value.longitude) {
        leafletStore.setCenter(findMyUpdate.value.latitude, findMyUpdate.value.longitude);
      } else {
        $q.notify({ type: 'negative', message: 'Find My Location not available' });
      }
      break;
    case 'simLoc':
      if (
        currentLocation.value &&
        currentLocation.value.latitude &&
        currentLocation.value.longitude
      ) {
        leafletStore.setCenter(currentLocation.value.latitude, currentLocation.value.longitude);
      } else {
        $q.notify({ type: 'negative', message: 'Simulation Location not available' });
      }
      break;
    default:
      $q.notify({ type: 'negative', message: 'Invalid location' });
      break;
  }
}

const timer = ref();
onMounted(() => {
  if (findMyUpdate.value && findMyUpdate.value.latitude && findMyUpdate.value.longitude) {
    leafletStore.setCenter(findMyUpdate.value.latitude, findMyUpdate.value.longitude);
  } else {
    console.log('favorites: home: ', favorites.home.coords.lat, favorites.home.coords.lng);
    leafletStore.setCenter(favorites.home.coords.lat, favorites.home.coords.lng);
  }
  socketStore.requestUpdate();
  timer.value = setInterval(() => {
    now.value = Date.now();
  }, 1000);
});
onUnmounted(() => {
  clearInterval(timer.value);
});
</script>

<style lang="sass">
.l-map
  height: 100vh
  width: 100vw

.q-item.q-router-link--active, .q-item--active
  background-color: $accent
  color: $primary

.leafletDrawer
  background-color: $dark
  color: $dark

.marker-popup .leaflet-popup-content-wrapper, .marker-popup .leaflet-popup-tip
  background-color: $dark
.marker-popup .leaflet-popup-content
  margin: 13px 10px 13px 10px

.small-icon svg
  transform: scale(0.6)
  transform-origin: center
  bottom: 0
  right: 0

.small-icon
  position: absolute
  margin-left: 14px
  margin-top: 48px
</style>
