<script setup lang="ts">
import { storeToRefs } from 'pinia';
import { useQuasar } from 'quasar';
import { useRoute } from 'vue-router';
import { computed, ref } from 'vue';

import ConfirmCommandDialog from 'components/ConfirmCommandDiaglog.vue';

import { favorites } from 'constants/favorites';
import { controls } from 'constants/controls';

import type { coords, DeviceCommands, TunneldCommands } from 'components/models';

import { useDeviceStore } from 'stores/device';
import { useLeafletStore } from 'stores/leaflet';
import { useSimulationStore } from 'stores/simulation';
import { useIcloudStore } from 'stores/icloud';
import { useTunneldStore } from 'stores/tunneld';

const route = useRoute();
const $q = useQuasar();

const deviceStore = useDeviceStore();
const leafletStore = useLeafletStore();
const simulationStore = useSimulationStore();
const icloudStore = useIcloudStore();
const tunneldStore = useTunneldStore();
const { center, markerLatLng, zoom } = storeToRefs(leafletStore);

const {
  simulationRunning,
  simulationState,
  simulationQueueLength,
  locationQueueOrder,
  testMode,
  gpsNoise,
  currentLocation,
} = storeToRefs(simulationStore);

const { icloudMonitor } = storeToRefs(icloudStore);

const menuOpen = ref(false);
const favoritesMap = favorites as Record<string, unknown>;

const isLast = computed(() => {
  if (locationQueueOrder.value && locationQueueOrder.value.length > 0 && currentLocation.value) {
    const currentIndex = locationQueueOrder.value.indexOf(currentLocation.value.loc_id);
    return locationQueueOrder.value.length - 1 === currentIndex;
  } else {
    return false;
  }
});

type ControlAction = {
  name: string;
  cmd: string;
  cmdClass: string;
  icon: string;
  cnfrm: boolean;
  delay: number;
};

type FavoriteWithCoords = {
  name: string;
  icon: string;
  coords: coords;
};

type FavoriteWithSubitems = {
  name: string;
  icon: string;
  subitems: Record<string, FavoriteWithCoords>;
};

function hasCoords(item: unknown): item is FavoriteWithCoords {
  return typeof item === 'object' && item !== null && 'coords' in item;
}

function hasSubitems(item: unknown): item is FavoriteWithSubitems {
  return typeof item === 'object' && item !== null && 'subitems' in item;
}

function handleFavClick(coords: coords) {
  center.value = [coords.lat, coords.lng];
  markerLatLng.value = [coords.lat, coords.lng];
  zoom.value = 15;
}

function handleTestToggle() {
  const response = simulationStore.simulationControl({
    command: 'test-mode',
    latitude: null,
    longitude: null,
    loc_id: null,
    delay: 0,
    address: null,
  });
  if (response.sts === 'error') {
    $q.notify({ type: 'negative', message: response.msg ?? 'Failed to toggle test mode' });
  }
}

function handleGpsNoiseToggle() {
  const response = simulationStore.simulationControl({
    command: 'gps-noise',
    latitude: null,
    longitude: null,
    loc_id: null,
    delay: 0,
    address: null,
  });
  if (response.sts === 'error') {
    $q.notify({ type: 'negative', message: response.msg ?? 'Failed to toggle test mode' });
  }
}

function handleControlClick(cmdAttr: ControlAction) {
  if (cmdAttr.cnfrm) {
    $q.dialog({
      component: ConfirmCommandDialog,
      componentProps: {
        name: cmdAttr.name,
        icon: cmdAttr.icon,
      },
    })
      .onOk(() => {
        if (cmdAttr.cmdClass === 'sim_cntrl_class') {
          let notType: string = 'positive';
          let notMsg: string = '';
          try {
            const ack = simulationStore.simulationControl({
              command: cmdAttr['cmd'],
              latitude: null,
              longitude: null,
              loc_id: null,
              delay: cmdAttr.delay,
              address: null,
            });
            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 });
          }
        }
        if (cmdAttr.cmdClass === 'dev_cntrl_class') {
          let notType: string = 'positive';
          let notMsg: string = '';
          try {
            const ack = deviceStore.deviceControl(cmdAttr.cmd as DeviceCommands, cmdAttr.delay);
            if (ack.sts === 'error') {
              notType = 'negative';
            }
            if (ack.msg) {
              notMsg = ack.msg;
            }
          } catch (error: unknown) {
            notType = 'negative';
            if (error instanceof Error) {
              console.error('Device Command ERROR: ', error.message);
              notMsg = `Device Command Error: ${error.message}`;
            } else {
              console.error('Device Command Error: ', error);
              notMsg = 'Device Command Error: Unknow error';
            }
          } finally {
            $q.notify({ type: notType, message: notMsg });
          }
        }
        if (cmdAttr.cmdClass === 'tunneld_cntrl_class') {
          let notType: string = 'positive';
          let notMsg: string = '';
          try {
            const ack = tunneldStore.tunneldControl(cmdAttr.cmd as TunneldCommands);
            if (ack.sts === 'error') {
              notType = 'negative';
            }
            if (ack.msg) {
              notMsg = ack.msg;
            }
          } catch (error: unknown) {
            notType = 'negative';
            if (error instanceof Error) {
              console.error('Tunneld Command ERROR: ', error.message);
              notMsg = `Tunneld Command Error: ${error.message}`;
            } else {
              console.error('Tunneld Command Error: ', error);
              notMsg = 'Tunneld Command Error: Unknow error';
            }
          } finally {
            $q.notify({ type: notType, message: notMsg });
          }
        }
      })
      .onCancel(() => {
        console.log('Dialog cancelled');
      })
      .onDismiss(() => {
        console.log('Dialog dismissed');
      });
  } else {
    if (cmdAttr.cmdClass === 'sim_cntrl_class') {
      let notType: string = 'positive';
      let notMsg: string = '';
      try {
        const ack = simulationStore.simulationControl({
          command: cmdAttr.cmd,
          latitude: null,
          longitude: null,
          loc_id: null,
          delay: cmdAttr.delay,
          address: null,
        });
        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 });
      }
    }
    if (cmdAttr.cmdClass === 'icloud-monitor_cntrl_class') {
      let notType: string = 'positive';
      let notMsg: string = '';
      try {
        const ack = icloudStore.icloudMonitorControl(cmdAttr.cmd);
        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 });
      }
    }

    if (cmdAttr.cmdClass === 'dev_cntrl_class') {
      let notType: string = 'positive';
      let notMsg: string = '';
      try {
        const ack = deviceStore.deviceControl(cmdAttr.cmd as DeviceCommands, cmdAttr.delay);
        if (ack.sts === 'error') {
          notType = 'negative';
        }
        if (ack.msg) {
          notMsg = ack.msg;
        }
      } catch (error: unknown) {
        notType = 'negative';
        if (error instanceof Error) {
          console.error('Device Command ERROR: ', error.message);
          notMsg = `Device Command Error: ${error.message}`;
        } else {
          console.error('Device Command Error: ', error);
          notMsg = 'Device Command Error: Unknow error';
        }
      } finally {
        $q.notify({ type: notType, message: notMsg });
      }
    }
    if (cmdAttr.cmdClass === 'tunneld_cntrl_class') {
      let notType: string = 'positive';
      let notMsg: string = '';
      try {
        const ack = tunneldStore.tunneldControl(cmdAttr.cmd as TunneldCommands);
        if (ack.sts === 'error') {
          notType = 'negative';
        }
        if (ack.msg) {
          notMsg = ack.msg;
        }
      } catch (error: unknown) {
        notType = 'negative';
        if (error instanceof Error) {
          console.error('Tunneld Command ERROR: ', error.message);
          notMsg = `Tunneld Command Error: ${error.message}`;
        } else {
          console.error('Tunneld Command Error: ', error);
          notMsg = 'Tunneld Command Error: Unknow error';
        }
      } finally {
        $q.notify({ type: notType, message: notMsg });
      }
    }
  }
}
</script>

<template>
  <q-toolbar :class="testMode ? 'bg-warning text-black' : 'bg-primary text-white'">
    <!-- <q-btn
      @click="
        $emit('drawer');
        leafletStore.toggleQLocDrawer();
      "
      flat
      round
      dense
      icon="menu"
      class="q-mr-sm"
    />
    -->
    <q-avatar>
      <q-img src="~assets/simloc_logo2.png" class="logo" />
    </q-avatar>
    <q-separator dark inset />
    <q-space />
    <q-btn
      :icon-right="menuOpen ? 'mdi-menu-up' : 'mdi-menu-down'"
      stretch
      flat
      label="Favorites"
      v-if="route.name === 'Leaflet'"
      class="text-weight-bold"
    >
      <q-menu @show="menuOpen = true" @hide="menuOpen = false" anchor="bottom end" self="top end">
        <q-list dark>
          <template v-for="(favObj, favId) in favoritesMap" :key="favId">
            <q-item
              dark
              v-if="hasCoords(favObj)"
              clickable
              v-ripple
              v-close-popup
              @click="handleFavClick(favObj.coords)"
            >
              <q-item-section avatar>
                <q-avatar :icon="favObj.icon" color="secondary" size="sm" text-color="black" />
              </q-item-section>
              <q-item-section>
                <q-item-label>{{ favObj.name }}</q-item-label>
              </q-item-section>
            </q-item>
            <q-item v-else-if="hasSubitems(favObj)" clickable v-ripple dark>
              <q-item-section avatar>
                <q-avatar :icon="favObj.icon" color="secondary" size="sm" text-color="black" />
              </q-item-section>
              <q-item-section>
                <q-item-label>{{ favObj.name }}</q-item-label>
              </q-item-section>
              <q-item-section side>
                <q-icon name="mdi-chevron-right" />
              </q-item-section>
              <q-menu anchor="bottom start" self="bottom end">
                <q-list dark>
                  <q-item
                    dark
                    v-for="(favSubObj, favSubId) in favObj.subitems"
                    :key="favSubId"
                    clickable
                    v-ripple
                    v-close-popup
                    @click="handleFavClick(favSubObj.coords)"
                  >
                    <q-item-section avatar>
                      <q-avatar
                        :icon="favSubObj.icon"
                        color="secondary"
                        size="sm"
                        text-color="black"
                      />
                    </q-item-section>
                    <q-item-section>
                      <q-item-label>{{ favSubObj.name }}</q-item-label>
                    </q-item-section>
                  </q-item>
                </q-list>
              </q-menu>
            </q-item>
          </template>
        </q-list>
      </q-menu>
    </q-btn>
    <q-btn-dropdown class="text-weight-bold"  stretch flat label="Controls">
      <q-list dark>
        <q-expansion-item
          group="controls"
          dense-toggle
          default-opened
          icon="mdi-map-marker"
          label="Simulation Controls"
          color="accent"
        >
          <q-item dark tag="label" v-ripple>
            <q-item-section avatar class="q-pl-lg">
              <q-toggle
                v-model="testMode"
                size="sm"
                color="yellow"
                @update:model-value="handleTestToggle"
                dark
                dense
                :disabled="simulationRunning"
              />
            </q-item-section>
            <q-item-section>
              <q-item-label>Test Mode</q-item-label>
            </q-item-section>
          </q-item>
          <q-item dark tag="label" v-ripple>
            <q-item-section avatar class="q-pl-lg">
              <q-toggle
                v-model="gpsNoise"
                size="sm"
                color="accent"
                @update:model-value="handleGpsNoiseToggle"
                dark
                dense
              />
            </q-item-section>
            <q-item-section>
              <q-item-label>GPS Noise</q-item-label>
            </q-item-section>
          </q-item>
          <q-item
            dark
            v-if="!simulationRunning"
            clickable
            v-ripple
            v-close-popup
            @click="handleControlClick(controls.simulation.start)"
          >
            <q-item-section avatar class="q-pl-lg">
              <q-avatar
                :icon="controls.simulation.start.icon"
                color="secondary"
                text-color="black"
                size="sm"
              />
            </q-item-section>
            <q-item-section>
              <q-item-label> {{ controls.simulation.start.name }} </q-item-label>
            </q-item-section>
          </q-item>
          <q-item
            dark
            v-if="simulationState === 'RUNNING' && simulationRunning"
            clickable
            v-ripple
            v-close-popup
            @click="handleControlClick(controls.simulation.pause)"
          >
            <q-item-section avatar class="q-pl-lg">
              <q-avatar
                :icon="controls.simulation.pause.icon"
                color="secondary"
                text-color="black"
                size="sm"
              />
            </q-item-section>
            <q-item-section>
              <q-item-label> {{ controls.simulation.pause.name }} </q-item-label>
            </q-item-section>
          </q-item>
          <q-item
            dark
            v-if="simulationState === 'PAUSED'"
            clickable
            v-ripple
            v-close-popup
            @click="handleControlClick(controls.simulation.resume)"
          >
            <q-item-section avatar class="q-pl-lg">
              <q-avatar
                :icon="controls.simulation.resume.icon"
                color="secondary"
                text-color="black"
                size="sm"
              />
            </q-item-section>
            <q-item-section>
              <q-item-label> {{ controls.simulation.resume.name }} </q-item-label>
            </q-item-section>
          </q-item>
          <q-item
            dark
            v-if="simulationQueueLength && simulationQueueLength > 0 && !isLast"
            clickable
            v-ripple
            v-close-popup
            @click="handleControlClick(controls.simulation.clear)"
          >
            <q-item-section avatar class="q-pl-lg">
              <q-avatar
                :icon="controls.simulation.clear.icon"
                color="secondary"
                text-color="black"
                size="sm"
              />
            </q-item-section>
            <q-item-section>
              <q-item-label> {{ controls.simulation.clear.name }} </q-item-label>
            </q-item-section>
          </q-item>
          <q-item
            dark
            v-if="simulationQueueLength && simulationQueueLength > 0"
            clickable
            v-ripple
            v-close-popup
            @click="handleControlClick(controls.simulation.reset)"
          >
            <q-item-section avatar class="q-pl-lg">
              <q-avatar
                :icon="controls.simulation.reset.icon"
                color="secondary"
                text-color="black"
                size="sm"
              />
            </q-item-section>
            <q-item-section>
              <q-item-label> {{ controls.simulation.reset.name }} </q-item-label>
            </q-item-section>
          </q-item>
          <q-item
            dark
            v-if="simulationRunning"
            clickable
            v-ripple
            v-close-popup
            @click="handleControlClick(controls.simulation.end)"
          >
            <q-item-section avatar class="q-pl-lg">
              <q-avatar
                :icon="controls.simulation.end.icon"
                color="secondary"
                text-color="black"
                size="sm"
              />
            </q-item-section>
            <q-item-section>
              <q-item-label> {{ controls.simulation.end.name }} </q-item-label>
            </q-item-section>
          </q-item>
        </q-expansion-item>
        <q-expansion-item
          group="controls"
          icon="mdi-cloud"
          dense-toggle
          label="iCloud Monitor Controls"
          color="accent"
        >
          <q-item
            dark
            v-if="!icloudMonitor"
            clickable
            v-ripple
            v-close-popup
            @click="handleControlClick(controls.icloudmonitor.start)"
          >
            <q-item-section avatar class="q-pl-lg">
              <q-avatar
                :icon="controls.icloudmonitor.start.icon"
                color="secondary"
                text-color="black"
                size="sm"
              />
            </q-item-section>
            <q-item-section>
              <q-item-label> {{ controls.icloudmonitor.start.name }} </q-item-label>
            </q-item-section>
          </q-item>
          <q-item
            dark
            v-if="icloudMonitor"
            clickable
            v-ripple
            v-close-popup
            @click="handleControlClick(controls.icloudmonitor.stop)"
            size="sm"
          >
            <q-item-section avatar class="q-pl-lg">
              <q-avatar
                :icon="controls.icloudmonitor.stop.icon"
                color="secondary"
                text-color="black"
                size="sm"
              />
            </q-item-section>
            <q-item-section>
              <q-item-label> {{ controls.icloudmonitor.stop.name }} </q-item-label>
            </q-item-section>
          </q-item>
        </q-expansion-item>
        <q-expansion-item group="controls" dense-toggle icon="mdi-subway" label="Tunneld Controls">
          <q-item
            v-if="!tunneldStore.tunnelConnected"
            dark
            clickable
            v-ripple
            v-close-popup
            @click="handleControlClick(controls.tunneld.start)"
          >
            <q-item-section avatar class="q-pl-lg">
              <q-avatar
                :icon="controls.tunneld.start.icon"
                color="secondary"
                text-color="black"
                size="sm"
              />
            </q-item-section>
            <q-item-section>
              <q-item-label> {{ controls.tunneld.start.name }} </q-item-label>
            </q-item-section>
          </q-item>
          <q-item
            v-if="!tunneldStore.tunneldWatcher"
            dark
            clickable
            v-ripple
            v-close-popup
            @click="handleControlClick(controls.tunneld.start_watcher)"
          >
            <q-item-section avatar class="q-pl-lg">
              <q-avatar
                :icon="controls.tunneld.start_watcher.icon"
                color="secondary"
                text-color="black"
                size="sm"
              />
            </q-item-section>
            <q-item-section>
              <q-item-label> {{ controls.tunneld.start_watcher.name }} </q-item-label>
            </q-item-section>
          </q-item>
          <q-item
            v-if="tunneldStore.tunnelConnected"
            dark
            clickable
            v-ripple
            v-close-popup
            @click="handleControlClick(controls.tunneld.restart)"
          >
            <q-item-section avatar class="q-pl-lg">
              <q-avatar
                :icon="controls.tunneld.restart.icon"
                color="secondary"
                text-color="black"
                size="sm"
              />
            </q-item-section>
            <q-item-section>
              <q-item-label> {{ controls.tunneld.restart.name }} </q-item-label>
            </q-item-section>
          </q-item>
          <q-item
            v-if="tunneldStore.tunnelConnected"
            dark
            clickable
            v-ripple
            v-close-popup
            @click="handleControlClick(controls.tunneld.clear)"
          >
            <q-item-section avatar class="q-pl-lg">
              <q-avatar
                :icon="controls.tunneld.clear.icon"
                color="secondary"
                text-color="black"
                size="sm"
              />
            </q-item-section>
            <q-item-section>
              <q-item-label> {{ controls.tunneld.clear.name }} </q-item-label>
            </q-item-section>
          </q-item>
          <q-item
            v-if="tunneldStore.tunnelConnected"
            dark
            clickable
            v-ripple
            v-close-popup
            @click="handleControlClick(controls.tunneld.cancel)"
          >
            <q-item-section avatar class="q-pl-lg">
              <q-avatar
                :icon="controls.tunneld.cancel.icon"
                color="secondary"
                text-color="black"
                size="sm"
              />
            </q-item-section>
            <q-item-section>
              <q-item-label> {{ controls.tunneld.cancel.name }} </q-item-label>
            </q-item-section>
          </q-item>
          <q-item
            v-if="tunneldStore.tunneldWatcher"
            dark
            clickable
            v-ripple
            v-close-popup
            @click="handleControlClick(controls.tunneld.end_watcher)"
          >
            <q-item-section avatar class="q-pl-lg">
              <q-avatar
                :icon="controls.tunneld.end_watcher.icon"
                color="secondary"
                text-color="black"
                size="sm"
              />
            </q-item-section>
            <q-item-section>
              <q-item-label> {{ controls.tunneld.end_watcher.name }} </q-item-label>
            </q-item-section>
          </q-item>
          <q-item
            v-if="tunneldStore.tunnelConnected"
            dark
            clickable
            v-ripple
            v-close-popup
            @click="handleControlClick(controls.tunneld.shutdown)"
          >
            <q-item-section avatar class="q-pl-lg">
              <q-avatar
                :icon="controls.tunneld.shutdown.icon"
                color="secondary"
                text-color="black"
                size="sm"
              />
            </q-item-section>
            <q-item-section>
              <q-item-label> {{ controls.tunneld.shutdown.name }} </q-item-label>
            </q-item-section>
          </q-item>
        </q-expansion-item>
        <q-expansion-item
          dense-toggle
          icon="mdi-raspberry-pi"
          label="Device Controls"
          group="controls"
        >
          <q-item
            dark
            clickable
            v-ripple
            v-close-popup
            @click="handleControlClick(controls.device.reboot)"
          >
            <q-item-section avatar class="q-pl-lg">
              <q-avatar
                :icon="controls.device.reboot.icon"
                color="secondary"
                text-color="black"
                size="sm"
              />
            </q-item-section>
            <q-item-section>
              <q-item-label> {{ controls.device.reboot.name }} </q-item-label>
            </q-item-section>
          </q-item>
          <q-item
            dark
            clickable
            v-ripple
            v-close-popup
            @click="handleControlClick(controls.device.shutdown)"
          >
            <q-item-section avatar class="q-pl-lg">
              <q-avatar
                :icon="controls.device.shutdown.icon"
                color="secondary"
                text-color="black"
                size="sm"
              />
            </q-item-section>
            <q-item-section>
              <q-item-label> {{ controls.device.shutdown.name }} </q-item-label>
            </q-item-section>
          </q-item>
        </q-expansion-item>
      </q-list>
    </q-btn-dropdown>
  </q-toolbar>
</template>

<style scoped lang="sass">

.logo
    transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275)
    display: inline-block
    cursor: pointer


.logo:hover
  transform: scale(1.3) translateY(-5px)
  filter: drop-shadow(0 10px 15px rgba(0, 0, 0, 0.3))
</style>
