<script setup lang="ts">
import { useCameraSettingsStore } from "@/stores/settings/CameraSettingsStore";
import {
  type ActivePipelineSettings,
  PipelineType,
  ContourSortMode,
  ContourTargetOrientation,
  ContourGroupingMode,
  ContourIntersection,
  ContourShape
} from "@/types/PipelineTypes";
import PvRangeSlider from "@/components/common/pv-range-slider.vue";
import PvSelect from "@/components/common/pv-select.vue";
import PvSlider from "@/components/common/pv-slider.vue";
import { computed } from "vue";
import { useStateStore } from "@/stores/StateStore";
import { useDisplay } from "vuetify";

// TODO fix pipeline typing in order to fix this, the store settings call should be able to infer that only valid pipeline type settings are exposed based on pre-checks for the entire config section
// Defer reference to store access method
const currentPipelineSettings = computed<ActivePipelineSettings>(
  () => useCameraSettingsStore().currentPipelineSettings
);

// TODO fix pv-range-slider so that store access doesn't need to be deferred
const contourArea = computed<[number, number]>({
  get: () => Object.values(useCameraSettingsStore().currentPipelineSettings.contourArea) as [number, number],
  set: (v) => (useCameraSettingsStore().currentPipelineSettings.contourArea = v)
});
const contourRatio = computed<[number, number]>({
  get: () => Object.values(useCameraSettingsStore().currentPipelineSettings.contourRatio) as [number, number],
  set: (v) => (useCameraSettingsStore().currentPipelineSettings.contourRatio = v)
});
const contourFullness = computed<[number, number]>({
  get: () => Object.values(useCameraSettingsStore().currentPipelineSettings.contourFullness) as [number, number],
  set: (v) => (useCameraSettingsStore().currentPipelineSettings.contourFullness = v)
});
const contourPerimeter = computed<[number, number]>({
  get: () =>
    currentPipelineSettings.value.pipelineType === PipelineType.ColoredShape
      ? (Object.values(currentPipelineSettings.value.contourPerimeter) as [number, number])
      : ([0, 0] as [number, number]),
  set: (v) => {
    if (currentPipelineSettings.value.pipelineType === PipelineType.ColoredShape) {
      currentPipelineSettings.value.contourPerimeter = v;
    }
  }
});
const contourRadius = computed<[number, number]>({
  get: () =>
    currentPipelineSettings.value.pipelineType === PipelineType.ColoredShape
      ? (Object.values(currentPipelineSettings.value.contourRadius) as [number, number])
      : ([0, 0] as [number, number]),
  set: (v) => {
    if (currentPipelineSettings.value.pipelineType === PipelineType.ColoredShape) {
      currentPipelineSettings.value.contourRadius = v;
    }
  }
});
const { mdAndDown } = useDisplay();
const interactiveCols = computed(() =>
  mdAndDown.value && (!useStateStore().sidebarFolded || useCameraSettingsStore().isDriverMode) ? 8 : 7
);
</script>

<template>
  <div>
    <pv-select
      v-model="useCameraSettingsStore().currentPipelineSettings.contourTargetOrientation"
      label="Target Orientation"
      tooltip="Used to determine how to calculate target landmarks, as well as aspect ratio"
      :items="[
        { value: ContourTargetOrientation.Portrait, name: 'Portrait' },
        { value: ContourTargetOrientation.Landscape, name: 'Landscape' }
      ]"
      :select-cols="interactiveCols"
      @update:modelValue="
        (value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourTargetOrientation: value }, false)
      "
    />
    <pv-select
      v-model="useCameraSettingsStore().currentPipelineSettings.contourSortMode"
      label="Target Sort"
      tooltip="Chooses the sorting mode used to determine the 'best' targets to provide to user code"
      :select-cols="interactiveCols"
      :items="[
        { value: ContourSortMode.Largest, name: 'Largest' },
        { value: ContourSortMode.Smallest, name: 'Smallest' },
        { value: ContourSortMode.Highest, name: 'Highest' },
        { value: ContourSortMode.Lowest, name: 'Lowest' },
        { value: ContourSortMode.Rightmost, name: 'Rightmost' },
        { value: ContourSortMode.Leftmost, name: 'Leftmost' },
        { value: ContourSortMode.Centermost, name: 'Centermost' }
      ]"
      @update:modelValue="
        (value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourSortMode: value }, false)
      "
    />
    <pv-range-slider
      v-model="contourArea"
      label="Area"
      :min="0"
      :max="100"
      :slider-cols="interactiveCols"
      :step="0.01"
      @update:modelValue="
        (value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourArea: value }, false)
      "
    />
    <pv-range-slider
      v-if="useCameraSettingsStore().currentPipelineType !== PipelineType.ColoredShape"
      v-model="contourRatio"
      label="Ratio (W/H)"
      tooltip="Min and max ratio between the width and height of a contour's bounding rectangle"
      :min="0"
      :max="100"
      :slider-cols="interactiveCols"
      :step="0.1"
      @update:modelValue="
        (value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourRatio: value }, false)
      "
    />
    <pv-range-slider
      v-if="useCameraSettingsStore().currentPipelineType === PipelineType.ColoredShape"
      v-model="contourFullness"
      label="Fullness"
      tooltip="Min and max ratio between a contour's area and its bounding rectangle"
      :min="0"
      :max="100"
      :slider-cols="interactiveCols"
      @update:modelValue="
        (value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourFullness: value }, false)
      "
    />
    <pv-range-slider
      v-if="currentPipelineSettings.pipelineType === PipelineType.ColoredShape"
      v-model="contourPerimeter"
      label="Perimeter"
      tooltip="Min and max perimeter of the shape, in pixels"
      :min="0"
      :max="4000"
      :slider-cols="interactiveCols"
      @update:modelValue="
        (value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourPerimeter: value }, false)
      "
    />
    <pv-slider
      v-model="useCameraSettingsStore().currentPipelineSettings.contourSpecklePercentage"
      label="Speckle Rejection"
      tooltip="Rejects contours whose average area is less than the given percentage of the average area of all the other contours"
      :min="0"
      :max="100"
      :slider-cols="interactiveCols"
      @update:modelValue="
        (value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourSpecklePercentage: value }, false)
      "
    />
    <template v-if="currentPipelineSettings.pipelineType === PipelineType.Reflective">
      <pv-slider
        v-model="currentPipelineSettings.contourFilterRangeX"
        label="X Filter Tightness"
        tooltip="Rejects contours whose center X is further than X standard deviations left/right of the mean X location"
        :min="0.1"
        :max="4"
        :step="0.1"
        :slider-cols="interactiveCols"
        @update:modelValue="
          (value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourFilterRangeX: value }, false)
        "
      />
      <pv-slider
        v-model="currentPipelineSettings.contourFilterRangeY"
        label="Y Filter Tightness"
        tooltip="Rejects contours whose center Y is further than X standard deviations above/below the mean Y location"
        :min="0.1"
        :max="4"
        :step="0.1"
        :slider-cols="interactiveCols"
        @update:modelValue="
          (value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourFilterRangeY: value }, false)
        "
      />
      <pv-select
        v-model="useCameraSettingsStore().currentPipelineSettings.contourGroupingMode"
        label="Target Grouping"
        tooltip="Whether or not every two targets are paired with each other (good for e.g. 2019 targets)"
        :select-cols="interactiveCols"
        :items="[
          { value: ContourGroupingMode.Single, name: 'Single' },
          { value: ContourGroupingMode.Dual, name: 'Dual' },
          { value: ContourGroupingMode.TwoOrMore, name: 'Two or More' }
        ]"
        @update:modelValue="
          (value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourGroupingMode: value }, false)
        "
      />
      <pv-select
        v-model="useCameraSettingsStore().currentPipelineSettings.contourIntersection"
        label="Target Intersection"
        tooltip="If target grouping is in dual mode it will use this dropdown to decide how targets are grouped with adjacent targets"
        :select-cols="interactiveCols"
        :items="[
          { value: ContourIntersection.None, name: 'None' },
          { value: ContourIntersection.Up, name: 'Up' },
          { value: ContourIntersection.Down, name: 'Down' },
          { value: ContourIntersection.Left, name: 'Left' },
          { value: ContourIntersection.Right, name: 'Right' }
        ]"
        :disabled="useCameraSettingsStore().currentPipelineSettings.contourGroupingMode === 0"
        @update:modelValue="
          (value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourIntersection: value }, false)
        "
      />
    </template>
    <template v-else-if="currentPipelineSettings.pipelineType === PipelineType.ColoredShape">
      <pv-select
        v-model="currentPipelineSettings.contourShape"
        label="Target Shape"
        tooltip="The shape of targets to look for"
        :select-cols="interactiveCols"
        :items="[
          { value: ContourShape.Circle, name: 'Circle' },
          { value: ContourShape.Polygon, name: 'Polygon' },
          { value: ContourShape.Triangle, name: 'Triangle' },
          { value: ContourShape.Quadrilateral, name: 'Quadrilateral' }
        ]"
        @update:modelValue="
          (value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourShape: value }, false)
        "
      />
      <pv-slider
        v-if="currentPipelineSettings.contourShape >= 1"
        v-model="currentPipelineSettings.accuracyPercentage"
        :disabled="currentPipelineSettings.contourShape < 1"
        label="Shape Simplification"
        tooltip="How much we should simply the input contour before checking how many sides it has"
        :min="0"
        :max="100"
        :slider-cols="interactiveCols"
        @update:modelValue="
          (value) => useCameraSettingsStore().changeCurrentPipelineSetting({ accuracyPercentage: value }, false)
        "
      />
      <pv-slider
        v-if="currentPipelineSettings.contourShape === 0"
        v-model="currentPipelineSettings.circleDetectThreshold"
        :disabled="currentPipelineSettings.contourShape !== 0"
        label="Circle match distance"
        tooltip="How close the centroid of a contour must be to the center of a circle in order for them to be matched"
        :min="1"
        :max="100"
        :slider-cols="interactiveCols"
        @update:modelValue="
          (value) => useCameraSettingsStore().changeCurrentPipelineSetting({ circleDetectThreshold: value }, false)
        "
      />
      <pv-slider
        v-if="currentPipelineSettings.contourShape === 0"
        v-model="currentPipelineSettings.maxCannyThresh"
        :disabled="currentPipelineSettings.contourShape !== 0"
        label="Max Canny Threshold"
        :min="1"
        :max="100"
        :slider-cols="interactiveCols"
        @update:modelValue="
          (value) => useCameraSettingsStore().changeCurrentPipelineSetting({ maxCannyThresh: value }, false)
        "
      />
      <pv-slider
        v-if="currentPipelineSettings.contourShape === 0"
        v-model="currentPipelineSettings.circleAccuracy"
        :disabled="currentPipelineSettings.contourShape !== 0"
        label="Circle Accuracy"
        :min="1"
        :max="100"
        :slider-cols="interactiveCols"
        @update:modelValue="
          (value) => useCameraSettingsStore().changeCurrentPipelineSetting({ circleAccuracy: value }, false)
        "
      />
      <pv-range-slider
        v-if="currentPipelineSettings.contourShape === 0"
        v-model="contourRadius"
        :disabled="currentPipelineSettings.contourShape !== 0"
        label="Radius"
        :min="0"
        :max="100"
        :slider-cols="interactiveCols"
        @update:modelValue="
          (value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourRadius: value }, false)
        "
      />
    </template>
  </div>
</template>
