<script setup lang="ts">
import { computed, ref, watch } from "vue";

const props = defineProps<{
  onAddText: () => void;
  onAddCircle: () => void;
  onAddRectangle: () => void;
  onClear: () => void;
  onImportImage: (file: File) => Promise<void>;
  onFillChange: (fill: string) => void;
  onStrokeChange: (stroke: string) => void;
  activeFill: string | null;
  activeStroke: string | null;
  canStyleSelection: boolean;
  zoom: number;
  minZoom: number;
  maxZoom: number;
  onZoomChange: (zoom: number) => void;
  onZoomIn: () => void;
  onZoomOut: () => void;
  onZoomReset: () => void;
}>();

const emit = defineEmits<{
  (e: "request-image"): void;
}>();

const fileInput = ref<HTMLInputElement | null>(null);
const fillValue = ref(props.activeFill ?? "#111827");
const strokeValue = ref(props.activeStroke ?? "#3b82f6");
const zoomSliderValue = ref(Math.round(props.zoom * 100));

watch(
  () => props.activeFill,
  (next) => {
    fillValue.value = next ?? "#111827";
  }
);

watch(
  () => props.activeStroke,
  (next) => {
    strokeValue.value = next ?? "#3b82f6";
  }
);

watch(
  () => props.zoom,
  (next) => {
    zoomSliderValue.value = Math.round(next * 100);
  }
);

const openFilePicker = () => {
  if (!fileInput.value) {
    return;
  }
  fileInput.value.value = "";
  fileInput.value.click();
};

const handleFileChange = async (event: Event) => {
  const input = event.target as HTMLInputElement;
  const files = input.files;
  if (!files || !files.length) {
    return;
  }
  const [file] = files;
  if (!file) {
    return;
  }
  await props.onImportImage(file);
};

const stylingDisabled = computed(() => !props.canStyleSelection);

const handleFillChange = (event: Event) => {
  const input = event.target as HTMLInputElement;
  const value = input.value;
  fillValue.value = value;
  props.onFillChange(value);
};

const handleStrokeChange = (event: Event) => {
  const input = event.target as HTMLInputElement;
  const value = input.value;
  strokeValue.value = value;
  props.onStrokeChange(value);
};

const handleZoomInput = (event: Event) => {
  const input = event.target as HTMLInputElement;
  const value = Number(input.value);
  if (Number.isNaN(value)) {
    return;
  }
  zoomSliderValue.value = value;
  props.onZoomChange(value / 100);
};

const zoomLabel = computed(() => `${Math.round(props.zoom * 100)}%`);
</script>

<template>
  <section class="rounded-2xl border border-slate-800/60 bg-slate-900/80 p-4 shadow-lg shadow-slate-950/30">
    <div class="flex items-center justify-between">
      <h3 class="text-sm font-semibold uppercase tracking-wide text-slate-400">
        Canvas Tools
      </h3>
      <button
        type="button"
        class="rounded-lg border border-red-500/40 px-3 py-1 text-xs font-medium text-red-300 transition hover:bg-red-500/10"
        @click="props.onClear"
      >
        Clear Canvas
      </button>
    </div>
    <div class="mt-4 grid grid-cols-2 gap-3 md:grid-cols-4">
      <button
        type="button"
        class="flex flex-col items-center justify-center rounded-xl border border-slate-700/60 bg-slate-800/80 px-4 py-6 text-sm font-medium text-slate-100 transition hover:border-sky-500/70 hover:bg-sky-500/10 hover:text-sky-200"
        @click="props.onAddText"
      >
        <span class="mb-2 text-3xl font-semibold">T</span>
        <span class="text-xs uppercase tracking-wide">Add Text</span>
      </button>
      <button
        type="button"
        class="flex flex-col items-center justify-center rounded-xl border border-slate-700/60 bg-slate-800/80 px-4 py-6 text-sm font-medium text-slate-100 transition hover:border-sky-500/70 hover:bg-sky-500/10 hover:text-sky-200"
        @click="props.onAddCircle"
      >
        <span class="mb-2 text-3xl font-semibold">●</span>
        <span class="text-xs uppercase tracking-wide">Add Circle</span>
      </button>
      <button
        type="button"
        class="flex flex-col items-center justify-center rounded-xl border border-slate-700/60 bg-slate-800/80 px-4 py-6 text-sm font-medium text-slate-100 transition hover:border-sky-500/70 hover:bg-sky-500/10 hover:text-sky-200"
        @click="props.onAddRectangle"
      >
        <span class="mb-2 text-3xl font-semibold">▭</span>
        <span class="text-xs uppercase tracking-wide">Add Rectangle</span>
      </button>
      <button
        type="button"
        class="flex flex-col items-center justify-center rounded-xl border border-slate-700/60 bg-slate-800/80 px-4 py-6 text-sm font-medium text-slate-100 transition hover:border-sky-500/70 hover:bg-sky-500/10 hover:text-sky-200"
        @click="openFilePicker"
      >
        <span class="mb-2 text-3xl font-semibold">⇪</span>
        <span class="text-xs uppercase tracking-wide">Upload Image</span>
      </button>
    </div>
    <input
      ref="fileInput"
      type="file"
      accept="image/png,image/jpeg,image/webp,image/svg+xml"
      class="hidden"
      @change="handleFileChange"
    />
    <div class="mt-5 rounded-xl border border-slate-800/60 bg-slate-900/70 p-4">
      <div class="flex items-center justify-between gap-3">
        <h4 class="text-xs font-semibold uppercase tracking-wide text-slate-400">
          Styling
        </h4>
        <span
          v-if="stylingDisabled"
          class="text-[11px] font-medium uppercase tracking-wide text-slate-500"
        >
          Select an object
        </span>
      </div>
      <div class="mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2">
        <label class="flex flex-col gap-2 text-xs font-semibold uppercase tracking-wide text-slate-400">
          Fill
          <input
            type="color"
            class="h-10 w-full cursor-pointer rounded-lg border border-slate-700/70 bg-slate-800/80 p-1"
            :disabled="stylingDisabled"
            :value="fillValue"
            @input="handleFillChange"
          />
        </label>
        <label class="flex flex-col gap-2 text-xs font-semibold uppercase tracking-wide text-slate-400">
          Stroke
          <input
            type="color"
            class="h-10 w-full cursor-pointer rounded-lg border border-slate-700/70 bg-slate-800/80 p-1"
            :disabled="stylingDisabled"
            :value="strokeValue"
            @input="handleStrokeChange"
          />
        </label>
      </div>
    </div>
    <div class="mt-5 rounded-xl border border-slate-800/60 bg-slate-900/70 p-4">
      <div class="flex items-center justify-between gap-3">
        <h4 class="text-xs font-semibold uppercase tracking-wide text-slate-400">
          View
        </h4>
        <span class="text-[11px] font-medium uppercase tracking-wide text-slate-300">
          {{ zoomLabel }}
        </span>
      </div>
      <div class="mt-4 flex items-center gap-3">
        <button
          type="button"
          class="flex h-10 w-10 items-center justify-center rounded-lg border border-slate-700/60 bg-slate-800/80 text-lg font-bold text-slate-100 transition hover:border-sky-500/70 hover:bg-sky-500/10"
          @click="props.onZoomOut"
        >
          –
        </button>
        <input
          type="range"
          class="flex-1 accent-sky-500"
          :min="Math.round(props.minZoom * 100)"
          :max="Math.round(props.maxZoom * 100)"
          step="5"
          :value="zoomSliderValue"
          @input="handleZoomInput"
        />
        <button
          type="button"
          class="flex h-10 w-10 items-center justify-center rounded-lg border border-slate-700/60 bg-slate-800/80 text-lg font-bold text-slate-100 transition hover:border-sky-500/70 hover:bg-sky-500/10"
          @click="props.onZoomIn"
        >
          +
        </button>
      </div>
      <button
        type="button"
        class="mt-3 w-full rounded-lg border border-slate-700/60 px-3 py-2 text-xs font-semibold uppercase tracking-wide text-slate-200 transition hover:border-sky-500/70 hover:bg-sky-500/10 hover:text-sky-200"
        @click="props.onZoomReset"
      >
        Reset Zoom
      </button>
    </div>
  </section>
</template>

