<!--
Champs de saisie de texte, à placer dans un composant `UiForm`

@see https://vuetifyjs.com/en/components/text-fields/
-->

<template>
  <v-text-field
    ref="input"
    :model-value="modelValue"
    :label="label || field ? $t(label ?? field) : undefined"
    :rules="rules"
    :disabled="readonly"
    :type="type === 'password' && show ? 'text' : type"
    :error="error || !!fieldViolations"
    :error-messages="
      errorMessage || (fieldViolations ? $t(fieldViolations) : '')
    "
    :append-icon="type === 'password' ? (show ? 'mdi-eye' : 'mdi-eye-off') : ''"
    :variant="variant"
    @click:append="show = !show"
    @update:model-value="onUpdate($event)"
    @change="onChange($event)"
  />

  <!--  v-cleave="mask"-->
</template>

<script setup lang="ts">
import { type Ref, ref } from '@vue/reactivity'
import { useFieldViolation } from '~/composables/form/useFieldViolation'
import type { PropType } from '@vue/runtime-core'

const props = defineProps({
  /**
   * v-model
   */
  modelValue: {
    type: [String, Number] as PropType<string | number | null>,
    required: false,
    default: null,
  },
  /**
   * Nom de la propriété d'une entité lorsque l'input concerne cette propriété
   * - Utilisé par la validation
   * - Laisser null si le champ ne s'applique pas à une entité
   */
  field: {
    type: String,
    required: false,
    default: null,
  },
  /**
   * Label du champ
   * Si non défini, c'est le nom de propriété qui est utilisé
   */
  label: {
    type: String,
    required: false,
    default: null,
  },
  /**
   * Type d'input HTML
   * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/button
   */
  type: {
    type: String,
    required: false,
    default: null,
  },
  /**
   * Définit si le champ est en lecture seule
   */
  readonly: {
    type: Boolean,
    required: false,
    default: false,
  },
  /**
   * Règles de validation
   * @see https://vuetify.cn/en/components/forms/#validation-with-submit-clear
   */
  rules: {
    type: Array as PropType<any[]>,
    required: false,
    default: () => [],
  },
  /**
   * Le champ est-il actuellement en état d'erreur
   */
  error: {
    type: Boolean,
    required: false,
    default: false,
  },
  /**
   * Si le champ est en état d'erreur, quel est le message d'erreur?
   */
  errorMessage: {
    type: String,
    required: false,
    default: null,
  },
  /**
   * Masque de saisie
   * @see https://github.com/nosir/cleave.js/
   */
  mask: {
    type: [Array, Boolean],
    required: false,
    default: false,
  },
  /**
   * @see https://vuetifyjs.com/en/api/v-autocomplete/#props-variant
   */
  variant: {
    type: String as PropType<
      | 'filled'
      | 'outlined'
      | 'plain'
      | 'underlined'
      | 'solo'
      | 'solo-inverted'
      | 'solo-filled'
      | undefined
    >,
    required: false,
    default: 'filled',
  },
})

const input = ref(null)

const { fieldViolations, updateViolationState } = useFieldViolation(props.field)

const show: Ref<boolean> = ref(false)

const emit = defineEmits(['update:model-value', 'change'])

const onUpdate = (event: string) => {
  emit('update:model-value', event)
}

const onChange = (event: Event | undefined) => {
  updateViolationState(event)
  emit('change', event)
}
</script>

<style scoped lang="scss">
input:read-only {
  color: rgb(var(--v-theme-neutral));
}
</style>
