<template>
  <div style="display: none"></div>
</template>

<script setup lang="ts">
import {
  ref,
  markRaw,
  inject,
  nextTick,
  onMounted,
  onBeforeUnmount,
  useAttrs,
} from 'vue';

import { routingControlProps, setupRoutingControl } from 'functions/routingControl';
import { Utilities, InjectionKeys } from '@vue-leaflet/vue-leaflet';

import 'leaflet';
import 'leaflet-routing-machine';
import 'leaflet-routing-machine/dist/leaflet-routing-machine.css';

type RoutingControlInstance = {
  on: (listeners: unknown) => void;
  setWaypoints: (waypoints: unknown[]) => void;
  remove: () => void;
};

// ---- Emits ----
const emit = defineEmits<{
  (e: 'ready', value: RoutingControlInstance): void;
}>();

// ---- Props ----
const props = defineProps(routingControlProps);

// ---- Attrs (for events) ----
const attrs = useAttrs();

// ---- Injections ----
const { UseGlobalLeafletInjection, RegisterControlInjection } = InjectionKeys;
const { WINDOW_OR_GLOBAL, assertInject, propsBinder, remapEvents } = Utilities;

const useGlobalLeaflet = inject(UseGlobalLeafletInjection, false);
const registerControl = assertInject(RegisterControlInjection);

// ---- State ----
const leafletObject = ref<RoutingControlInstance | null>(null);

// ---- Setup logic ----

const { options, methods } = setupRoutingControl(props);

onMounted(async () => {
  const leafletModule = useGlobalLeaflet
    ? ((WINDOW_OR_GLOBAL as unknown as { L: { routing: { control: (options: unknown) => unknown } } }).L)
    : ((await import('leaflet/dist/leaflet-src.esm')) as unknown as {
        routing: { control: (options: unknown) => unknown };
      });
  const routing = leafletModule.routing;

  const { listeners } = remapEvents(attrs);

  const control = markRaw(routing.control(options) as object) as RoutingControlInstance;
  leafletObject.value = control;
  control.on(listeners);

  propsBinder(methods, control, props);
  (registerControl as unknown as (payload: { leafletObject: unknown }) => void)({
    leafletObject: control,
  });

  await nextTick();
  emit('ready', control);
});

onBeforeUnmount(() => {
  if (leafletObject.value) {
    leafletObject.value.setWaypoints([]);
    leafletObject.value.remove();
  }
});
</script>
