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

import FormClient from "~/components/formClient.vue";

type optionalMap<Optional, type> = Optional extends true ? undefined | type : type;

type typeMap = {
  "text": string,
  "password": string,
  "number": number,
  "boolean": boolean,
  "none": undefined,
  "client": `${bigint}`
};

export type fieldDefinition<Optional extends boolean = boolean, type extends keyof typeMap = keyof typeMap> = {
  key: string,
  label?: string,
  type: type,
  optional?: Optional,
  value?: optionalMap<Optional, typeMap[type]>,
}

const props = defineProps<{
  fields: Array<fieldDefinition>,
}>();

// eslint-disable-next-line func-call-spacing
const emit = defineEmits<{
  (e: "update:modelValue", value: any): void,
  (e: "updateSubModelValue", key: fieldDefinition["key"], value: fieldDefinition["value"]): void,
}>();

const modelValue = ref<{[key: string]: string | number | boolean | undefined}>({});

for (const i of props.fields) {
  modelValue.value[i.key] = i.value;
  emit("updateSubModelValue", i.key, i.value);
}

function updateModel(key: string, v: any) {
  modelValue.value[key] = v;
  emit("update:modelValue", modelValue.value);
  emit("updateSubModelValue", key, v);
}

emit("update:modelValue", modelValue.value);
</script>

<template>
  <div v-for="i of fields" :key="i.key">
    <VTextField
      v-if="i.type == 'text'"
      :model-value="modelValue[i.key]"
      :label="i.label"
      type="text"
      @update:model-value="v => updateModel(i.key, v)"
    />
    <VTextField
      v-if="i.type == 'password'"
      :model-value="modelValue[i.key]"
      :label="i.label"
      type="password"
      @update:model-value="v => updateModel(i.key, v)"
    />
    <VTextField
      v-if="i.type == 'number'"
      :model-value="modelValue[i.key]"
      :label="i.label"
      type="number"
      @update:model-value="v => updateModel(i.key, Number(v))"
    />
    <v-checkbox
      v-if="i.type == 'boolean'"
      :label="i.label"
      :model-value="modelValue[i.key]"
      @update:model-value="v => updateModel(i.key, Boolean(v))"
    />
    <p v-if="i.type == 'none'">
      {{ i.label }}
    </p>
    <FormClient
      v-if="i.type == 'client'"
      :model-value="modelValue[i.key] as `${bigint}`"
      :label="i.label"
      :optional="i.optional"
      @update:model-value="v => updateModel(i.key, v)"
    />
  </div>
</template>
