<script setup lang="ts">
import { computed, useAttrs } from 'vue'
import { ScrubInputRoot, ScrubInputField, ScrubInputDisplay, testId } from '@open-pencil/vue'
import { useEditorStore } from '@/app/editor/active-store'

const attrs = useAttrs()

const store = useEditorStore()

const rootTestId = computed(() => (attrs['data-test-id'] as string | undefined) ?? 'scrub-input')

const { modelValue, min, max, step, icon, label, suffix, sensitivity, placeholder } = defineProps<{
  modelValue: number | symbol
  min?: number
  max?: number
  step?: number
  icon?: string
  label?: string
  suffix?: string
  sensitivity?: number
  placeholder?: string
}>()

const emit = defineEmits<{
  'update:modelValue': [value: number]
  'editing-change': [editing: boolean]
  commit: [value: number, previous: number]
}>()

defineOptions({ inheritAttrs: false })
</script>

<template>
  <ScrubInputRoot
    v-slot="{ editing, actions, placeholder: ph }"
    :model-value="modelValue"
    :min="min"
    :max="max"
    :step="step"
    :sensitivity="sensitivity"
    :placeholder="placeholder"
    @update:model-value="emit('update:modelValue', $event)"
    @commit="(val: number, prev: number) => emit('commit', val, prev)"
    @editing-change="
      (editing: boolean) => {
        store.state.scrubInputFocused = editing
        emit('editing-change', editing)
      }
    "
  >
    <div
      v-bind="{ ...attrs, ...testId(rootTestId) }"
      :tabindex="editing ? undefined : 0"
      :class="[
        attrs.class,
        'group flex h-[26px] min-w-0 flex-1 items-center rounded border border-border bg-input focus-within:border-accent focus:border-accent'
      ]"
      :style="{ cursor: editing ? 'auto' : 'ew-resize' }"
      @pointerdown="
        !editing &&
        !($event.target as HTMLElement)?.closest?.('button') &&
        actions.startScrub($event)
      "
      @focus="!editing && actions.startEdit()"
    >
      <span v-if="attrs['data-test-id']" data-test-id="scrub-input" class="hidden" />
      <span
        class="flex shrink-0 items-center justify-center self-stretch px-[5px] text-muted select-none [&>*]:pointer-events-none"
      >
        <slot name="icon">
          <span v-if="icon" class="text-[11px] leading-none">{{ icon }}</span>
        </slot>
        <span v-if="label" class="text-[11px] leading-none">{{ label }}</span>
      </span>
      <ScrubInputField
        data-test-id="scrub-input-field"
        class="min-w-0 flex-1 cursor-text border-none bg-transparent pr-1.5 font-[inherit] text-xs text-surface outline-none"
        :min="min === -Infinity ? undefined : min"
        :max="max === Infinity ? undefined : max"
        :step="step"
      />
      <slot v-if="editing" name="suffix" />
      <ScrubInputDisplay
        class="flex flex-1 items-center truncate overflow-hidden text-xs select-none"
        :class="$slots.suffix ? 'pr-0' : 'pr-1.5'"
      >
        <template #default="{ value, isMixed: mixed }">
          <span v-if="mixed" class="flex-1 text-muted">{{ ph }}</span>
          <template v-else>
            <span class="flex-1 text-surface">{{ value }}</span>
            <span v-if="suffix" class="shrink-0 pr-1.5 text-muted">{{ suffix }}</span>
          </template>
          <slot name="suffix" />
        </template>
      </ScrubInputDisplay>
    </div>
  </ScrubInputRoot>
</template>
