<script setup lang="ts">
import { storeToRefs } from 'pinia';
import { useSimulationStore } from 'stores/simulation';
import { computed, onMounted, onUnmounted, ref } from 'vue';
import type { NominatimResponse } from 'components/models';
import { Icon, PinCirclePanel, PinStarPanel } from 'leaflet-extra-markers';

import FormattedAddress from 'components/FormattedAddress.vue';
//import NestedKnob from 'components/NestedKnob.vue';

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

const props = defineProps({
  address: {
    type: Object as () => NominatimResponse,
    required: false,
  },
  latitude: {
    type: Number,
    required: true,
  },
  longitude: {
    type: Number,
    required: true,
  },
  icon: {
    type: String,
    default: 'mdi-map-marker',
  },
  start: {
    type: String,
    required: true,
  },
  end: {
    type: String,
    required: false,
  },
  delay: {
    type: Number,
    default: 0,
  },
  active: {
    type: Boolean,
    default: false,
  },
  isCurrentDelay: {
    type: Boolean,
    default: false,
  },
  loc_id: {
    type: String,
    required: true,
  },
  isLast: {
    type: Boolean,
    default: false,
  },
  index: {
    type: Number,
    default: 0,
  },
  status: {
    type: String,
    default: 'queued',
  },
});

// Define custom events that this component can emit
const emit = defineEmits(['item-clicked']);

function itemClicked() {
  const param1 = props.loc_id;
  emit('item-clicked', param1);
}

const currentTime = ref(new Date());
let timerId: number;

function formatInAgo(seconds: number) {
  let delta;
  if (seconds === 0) {
    delta = 'now';
  }
  if (seconds > 0) {
    const minutes: number = Math.floor(seconds / 60);
    const hours: number = Math.floor(minutes / 60);
    const days: number = Math.floor(hours / 24);
    if (days > 0) {
      delta = `in ${days} day${days > 1 ? 's' : ''}`;
    } else if (hours > 0) {
      delta = `in ${hours} hour${hours > 1 ? 's' : ''}`;
    } else if (minutes > 0) {
      delta = `in ${minutes} minute${minutes > 1 ? 's' : ''}`;
    } else {
      delta = `in ${seconds} second${seconds > 1 ? 's' : ''}`;
    }
  }
  return delta;
}

const calculateDeltaTime = computed(() => {
  let delta;
  if (props.active) {
    delta = 'now';
  } else if (props.end && props.end !== '') {
    const pastTime: Date = new Date(props.end);
    const nowMs: number = currentTime.value.getTime();
    const pastMs: number = pastTime.getTime();
    const diffMs: number = Math.abs(nowMs - pastMs);
    const seconds: number = Math.floor(diffMs / 1000);
    const minutes: number = Math.floor(seconds / 60);
    const hours: number = Math.floor(minutes / 60);
    const days: number = Math.floor(hours / 24);
    if (days > 0) {
      delta = `${days} day${days > 1 ? 's' : ''} ago`;
    } else if (hours > 0) {
      delta = `${hours} hr${hours > 1 ? 's' : ''} ago`;
    } else if (minutes > 0) {
      delta = `${minutes} min${minutes > 1 ? 's' : ''} ago`;
    } else {
      delta = `${seconds} sec${seconds > 1 ? 's' : ''} ago`;
    }
  } else {
    let startSlice;
    if (currentIndex.value > 0) {
      startSlice = currentIndex.value;
    } else {
      startSlice = 0;
    }
    const waitingFor = locationQueueOrder.value.slice(startSlice, myIndex.value + 1);
    const willWait = waitingFor.reduce((sum, loc_id) => {
      return sum + (locationQueueData.value[loc_id]?.delay || 0);
    }, 0);
    delta = formatInAgo(willWait);
  }
  return delta;
});

const secondsToHhMmSs = (seconds: number) => {
  const hours = Math.floor(seconds / 3600);
  const minutes = Math.floor((seconds % 3600) / 60);
  const remainingSeconds = seconds % 60;
  return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${remainingSeconds
    .toString()
    .padStart(2, '0')}`;
};
/*
const secondsToTimeShort = (seconds: number) => {
  const hours = Math.floor(seconds / 3600);
  const minutes = Math.floor((seconds % 3600) / 60);
  if (hours > 2) {
    return hours.toString();
  }
  if (minutes > 5) {
    return minutes.toString();
  } else return seconds.toString();
};
const timeToSeconds = (timeIn: string) => {
  const a = timeIn.split(':');
  const seconds = +a[0] * 60 * 60 + +a[1] * 60 + +a[2];
  return seconds;
};
*/
const humanReadableDateTime = (iso: string) => {
  return new Date(iso).toLocaleDateString('en-US', {
    //    year: 'numeric',
    //    month: 'long',
    //    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
  });
};

const currentIndex = computed(() => {
  return currentLocation.value ? locationQueueOrder.value.indexOf(currentLocation.value.loc_id) : 0;
});

const myIndex = computed(() => {
  return locationQueueOrder.value.indexOf(props.loc_id);
});

const myUpdatedIndex = computed(() => {
  return myIndex.value - currentIndex.value;
});

const itemClass = computed(() => {
  if (myUpdatedIndex.value > 0) return 'future';
  else if (myUpdatedIndex.value < 0) return 'past';
  else return 'active';
});

const customIcon = computed(() => {
  if (myUpdatedIndex.value > 0) {
    return new Icon({
      color: 'blue',
      accentColor: 'firebrick',
      content: myUpdatedIndex.value.toString(),
      contentColor: 'white',
      scale: 1,
      svg: PinCirclePanel,
    });
  } else if (myUpdatedIndex.value < 0) {
    return new Icon({
      color: 'black',
      accentColor: 'grey',
      content: myUpdatedIndex.value.toString(),
      contentColor: 'white',
      scale: 1,
      svg: PinCirclePanel,
    });
  } else {
    return new Icon({
      color: 'pink',
      accentColor: 'black',
      content: '*',
      contentColor: 'black',
      scale: 1,
      svg: PinStarPanel,
    });
  }
});

const iconElement = computed(() => {
  return customIcon.value.createIcon();
});

onMounted(() => {
  const update = () => {
    currentTime.value = new Date();
    timerId = requestAnimationFrame(update);
  };
  timerId = requestAnimationFrame(update);
});

const delayConverted = computed({
  get: () => {
    if (props.delay <= 260) {
      return props.delay;
    } else if (props.delay <= 3600) {
      return Math.floor(props.delay / 60);
    } else {
      return Math.floor(props.delay / 3600);
    }
  },
  set: (val) => {
    if (getDelayAttrs.value.units == 's') {
      simulationStore.updateLocationMark(props.loc_id, 'delay', val);
    } else if (getDelayAttrs.value.units == 'm') {
      simulationStore.updateLocationMark(props.loc_id, 'delay', val * 60);
    } else if (getDelayAttrs.value.units == 'h') {
      simulationStore.updateLocationMark(props.loc_id, 'delay', val * 3600);
    }
  },
});

const delayHhMmSs = computed({
  get: () => secondsToHhMmSs(props.delay),
  set: (val) => {
    const totalSeconds = val.split(':').reduce((acc, time) => 60 * acc + +time, 0);
    simulationStore.updateLocationMark(props.loc_id, 'delay', totalSeconds);
  },
});

const getDelayAttrs = computed(() => {
  if (props.delay <= 260) {
    return {
      units: 's',
      display: Math.floor((props.delay % 3600) / 60),
      step: 10,
      max: 80,
    } as const;
  } else if (props.delay <= 3600) {
    return {
      units: 'm',
      display: Math.floor((props.delay % 3600) / 60),
      step: 1,
      max: 80,
    } as const;
  } else {
    return {
      units: 'h',
      display: Math.floor(props.delay / 3600),
      step: 1,
      max: 12,
    } as const;
  }
});

/*
const delayMask = computed(() => {
  if (props.delay < 60) {
    return 'ss';
  }
  if (props.delay < 3600) {
    return 'mm:ss';
  } else return 'HH:mm:ss';
});

const delayInputMask = computed(() => {
  if (props.delay < 60) {
    return '##';
  }
  if (props.delay < 3600) {
    return '##:##';
  } else return '##:##:##';
});
*/

const displayDelay = computed(() => {
  return props.index > currentIndex.value;
});

const delayActive = computed(() => {
  return props.index === currentIndex.value + 1;
});

const canDrag = computed(() => {
  return props.index > currentIndex.value + 1;
});

onUnmounted(() => {
  cancelAnimationFrame(timerId);
});
</script>
<template>
  <div>
    <q-item
      v-if="displayDelay"
      :active="delayActive"
      :class="delayActive ? 'text-orange bg-dark' : ''"
      active-class="text-orange bg-dark"
    >
      <q-item-section class="flex flex-center">
        <q-input
          class="q-pt-md"
          filled
          v-model="delayHhMmSs"
          mask="fulltime"
          stack-label
          label="Delay"
          dense
          style="max-width: 150px"
        >
          <template v-slot:append> </template>
        </q-input>
        <q-slider
          v-model="delayConverted"
          :min="0"
          :step="getDelayAttrs.step"
          :max="getDelayAttrs.max"
          label
          switch-label-side
          :label-value="delayConverted + ' ' + getDelayAttrs.units"
          markers
          snap
          color="primary"
          style="max-width: 75%"
        />
      </q-item-section>
    </q-item>
    <q-separator inset spaced v-if="displayDelay" />
    <q-item
      v-ripple
      clickable
      :active="active"
      @click="itemClicked"
      :class="itemClass"
      active-class="text-orange bg-dark"
    >
      <q-item-section style="width: 70%">
        <q-item-label v-if="address">
          <FormattedAddress :address="props.address" />
          <q-tooltip> {{ latitude }}, {{ longitude }} </q-tooltip>
        </q-item-label>
        <q-item-label v-else> {{ latitude }}, {{ longitude }} </q-item-label>
        <q-item-label caption lines="1" v-if="start && simulationRunning">
          start: {{ humanReadableDateTime(start) }}
        </q-item-label>
        <q-item-label caption lines="1" v-if="end && simulationRunning">
          end: {{ humanReadableDateTime(end) }}
        </q-item-label>
        <q-item-label caption lines="1" v-if="!active && !end">
          delay: {{ delay }} seconds
        </q-item-label>
      </q-item-section>
      <q-item-section
        side
        style="
          padding: 30px 0 0 10px;
          height: 100%;
          width: 35%;
          display: flex;
          justify-content: flex-end;
          align-items: center;
        "
      >
        <q-icon :class="{ 'drag-handle': canDrag }" v-html="iconElement.outerHTML" />
        <q-item-label caption lines="1" v-if="simulationRunning">
          {{ calculateDeltaTime }}
        </q-item-label>
      </q-item-section>
    </q-item>
    <q-separator spaced inset v-if="!isLast" />
  </div>
</template>
<style lang="sass" scoped>
.past
  color: gray
</style>
