<script setup>
import { computed, ref, watch, reactive } from "vue";
import { useAlert } from "../../composables/alert";
import {
  useHostAgent,
  PAPER_SOURCE,
  BIT_DEPTH
} from "../../composables/hostAgent";
const alert = useAlert();
const host = useHostAgent();
const emit = defineEmits(["scan"]);
const props = defineProps({
  feeder: { type: Boolean, required: false, default: false },
  duplex: { type: Boolean, required: false, default: false },
  dpi: { type: Number, required: false, default: 200 },
  quality: { type: Number, required: false, default: 80 },
  color: { type: String, required: false, default: "color" },
  maxSize: { type: Number, required: false, default: 5 }
});
const scannerOptions = ref({
  dpi: props.dpi,
  quality: props.quality,
  paperSource: props.duplex ? PAPER_SOURCE.Duplex : props.feeder ? PAPER_SOURCE.Feeder : PAPER_SOURCE.Flatbed,
  bitDepth: props.color === "bw" ? BIT_DEPTH.BlackAndWhite : props.color === "grey" ? BIT_DEPTH.Grayscale : BIT_DEPTH.Color
});
watch(() => props.dpi, () => {
  if (props.dpi) scannerOptions.value.dpi = props.dpi;
});
watch(() => props.quality, () => {
  if (props.quality) scannerOptions.value.quality = props.quality;
});
const uiDuplex = computed({
  get: () => scannerOptions.value.paperSource === PAPER_SOURCE.Duplex,
  set(v) {
    if (v) {
      scannerOptions.value.paperSource = PAPER_SOURCE.Duplex;
    } else {
      if (scannerOptions.value.paperSource === PAPER_SOURCE.Duplex) {
        scannerOptions.value.paperSource = PAPER_SOURCE.Feeder;
      }
    }
  }
});
const uiFeeder = computed({
  get: () => scannerOptions.value.paperSource === PAPER_SOURCE.Feeder || scannerOptions.value.paperSource === PAPER_SOURCE.Duplex,
  set(v) {
    if (v) {
      scannerOptions.value.paperSource = uiDuplex.value ? PAPER_SOURCE.Duplex : PAPER_SOURCE.Feeder;
    } else {
      scannerOptions.value.paperSource = PAPER_SOURCE.Flatbed;
    }
  }
});
const uiColor = computed({
  get() {
    const b = scannerOptions.value.bitDepth;
    if (b === BIT_DEPTH.BlackAndWhite) return "bw";
    if (b === BIT_DEPTH.Grayscale) return "grey";
    return "color";
  },
  set(v) {
    const vv = (v || "color").toLowerCase();
    scannerOptions.value.bitDepth = vv === "bw" ? BIT_DEPTH.BlackAndWhite : vv === "grey" || vv === "gray" ? BIT_DEPTH.Grayscale : BIT_DEPTH.Color;
  }
});
watch(() => props.duplex, () => {
  uiDuplex.value = props.duplex;
});
watch(() => props.feeder, () => {
  uiFeeder.value = props.feeder;
});
watch(() => props.color, () => {
  if (props.color) uiColor.value = props.color;
});
function scanResultsToBase64Files(results) {
  return results.map((r, idx) => ({
    fileName: `scan_${idx + 1}.png`,
    base64String: r.base64String.startsWith("data:") ? r.base64String : `data:image/png;base64,${r.base64String}`
  }));
}
const isScanning = ref(false);
async function performScan() {
  try {
    isScanning.value = true;
    const results = await host.scan(scannerOptions.value);
    emit("scan", scanResultsToBase64Files(results || []));
  } catch (e) {
    const msg = e?.data?.detail || e?.data?.title || e?.message || "Scan failed";
    alert?.addAlert({ message: msg, alertType: "error" });
  } finally {
    isScanning.value = false;
  }
}
function fileToBase64(file) {
  const maxSize = props.maxSize * 1048576;
  return new Promise((resolve, reject) => {
    if (file.size > maxSize) reject(`File (${file.name}) size exceeds the ${props.maxSize} MB limit.`);
    const reader = new FileReader();
    reader.onload = (event) => {
      resolve({ fileName: file.name, base64String: event.target?.result });
    };
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}
function performFileUpload(files) {
  if (!files) return;
  const allFiles = Array.isArray(files) ? files : [files];
  const base64Promises = allFiles.map(fileToBase64);
  Promise.all(base64Promises).then((base64Strings) => emit("scan", base64Strings)).catch((error) => alert?.addAlert({ message: String(error), alertType: "error" }));
}
const scannerOptionsProps = computed(() => scannerOptions.value);
const configHelper = reactive({
  get feeder() {
    return uiFeeder.value;
  },
  set feeder(v) {
    uiFeeder.value = v;
  },
  get duplex() {
    return uiDuplex.value;
  },
  set duplex(v) {
    uiDuplex.value = v;
  },
  get color() {
    return uiColor.value;
  },
  set color(v) {
    uiColor.value = v;
  }
});
const operation = { performScan, performFileUpload, fileToBase64 };
</script>

<template>
  <div class="scanner">
    <slot :scannerOptions="scannerOptionsProps" :configHelper="configHelper" :operation="operation" :isScanning="isScanning">
      <v-card>
        <v-card-text>
          <form-pad v-model="scannerOptions">
            <template #default>
              <!-- Upload -->
              <v-row>
                <v-col cols="12">
                  <p>Upload a New Files</p>
                </v-col>

                <v-col cols="12">
                  <file-btn
                      @update:modelValue="performFileUpload"
                      block
                      multiple
                      variant="tonal"
                      rounded="xl"
                  >
                    <v-icon>mdi mdi-tray-arrow-up</v-icon>
                    Upload file
                  </file-btn>
                </v-col>
              </v-row>

              <!-- Divider -->
              <v-row>
                <v-col cols="12" style="text-align: center;">
                  <p>Or</p>
                </v-col>
              </v-row>

              <!-- Scan title -->
              <v-row>
                <v-col cols="12">
                  <p>Scan a New Files</p>
                </v-col>
              </v-row>

              <!-- Scan controls -->
              <v-row>
                <v-col cols="12" class="py-0">
                  <v-switch
                      color="primary"
                      v-model="uiFeeder"
                      label="Enable feeder"
                      hide-details
                      density="compact"
                  />
                </v-col>

                <v-col cols="12" class="py-0">
                  <v-switch
                      color="primary"
                      v-model="uiDuplex"
                      label="Enable duplex"
                      hide-details
                      density="compact"
                  />
                </v-col>

                <v-col cols="12">
                  <p>choose color mode</p>

                  <v-btn-toggle
                      v-model="uiColor"
                      variant="tonal"
                      mandatory
                  >
                    <v-btn value="color" prepend-icon="mdi mdi-palette-outline">
                      <span>Color</span>
                    </v-btn>

                    <v-btn value="grey" prepend-icon="mdi mdi-circle">
                      <span>Grayscale</span>
                    </v-btn>

                    <v-btn value="bw" prepend-icon="mdi mdi-circle-half-full">
                      <span>Black&amp;White</span>
                    </v-btn>
                  </v-btn-toggle>
                </v-col>

                <v-col cols="12">
                  <v-slider
                      v-model="scannerOptions.dpi"
                      :max="200"
                      :min="100"
                      :ticks="{ 100: 'Low', 150: 'Standard', 200: 'High' }"
                      show-ticks="always"
                      step="50"
                      tick-size="4"
                      label="Resolution"
                      hide-details
                  />
                </v-col>

                <v-col cols="12">
                  <v-slider
                      v-model="scannerOptions.quality"
                      :max="100"
                      :min="60"
                      :ticks="{ 60: 'Low', 80: 'Standard', 100: 'High' }"
                      show-ticks="always"
                      step="5"
                      tick-size="4"
                      label="Quality"
                      hide-details
                  />
                </v-col>

                <v-col cols="12">
                  <v-btn
                      @click="performScan"
                      :loading="isScanning"
                      :disabled="isScanning"
                      block
                      variant="tonal"
                      rounded="xl"
                  >
                    <v-icon>mdi mdi-scanner</v-icon>
                    Start Scanning
                  </v-btn>
                </v-col>
              </v-row>
            </template>
          </form-pad>
        </v-card-text>
      </v-card>
    </slot>
  </div>
</template>
