<template>
  <span class="input-wrapper" :class="classes">
    <template class="field__input-label">
      <slot name="label"></slot>
    </template>
    <span class="field__input-icon field__input-icon--start">
      <slot name="icon-start"></slot>
    </span>
    <input
      ref="input"
      role="input"
      :type="type"
      :value="modelValue"
      :placeholder="placeholder"
      :required="required"
      :disabled="disabled"
      :max="max"
      :min="min"
      :step="computedStep"
      :minlength="minlength"
      :maxlength="maxlength"
      @blur="$emits('blur')"
      @input="onInput"
      @focus="$emits('focus')"
      @click="$emits('click')"
    />
    <span class="field__input-icon field__input-icon--end">
      <slot name="icon-end"></slot>
    </span>
  </span>
</template>

<script lang="ts" setup>
import { computed, Ref, ref } from 'vue';
import { InputType } from '@/models';
import { FieldComponentProps } from '@/plugins/field/field-component.model';

export interface Props extends FieldComponentProps {
  modelValue: string | number;
  placeholder?: string;
  focus?: boolean;
  min?: number;
  max?: number;
  minlength?: number;
  maxlength?: number;
  step?: number;
  type?:
    | InputType.TEXT
    | InputType.NUMBER
    | InputType.DATE
    | InputType.DATETIME
    | InputType.TIME;
}

const props = withDefaults(defineProps<Props>(), {
  type: InputType.TEXT,
  required: false,
  disabled: false,
  focus: false,
  step: 0,
});
const input: Ref<HTMLElement | null> = ref(null);

const computedStep = computed(() => {
  if (
    [
      InputType.TIME,
      InputType.DATE,
      InputType.DATETIME,
      InputType.NUMBER,
    ].includes(props.type)
  ) {
    return props.step || 0;
  }
  return 0;
});

const $emits = defineEmits<{
  'update:modelValue': [value: string];
  blur: [];
  focus: [];
  click: [];
}>();

const setFocus = () => {
  if (input.value) {
    input.value.focus();
  }
};

defineExpose({
  setFocus,
});

const onInput = (e: Event) => {
  if (!props.disabled)
    $emits('update:modelValue', (e?.target as HTMLInputElement).value);
};

const classes = computed(() => {
  return {
    'is-error': props.errors?.length,
    'is-disabled': props.disabled,
    'is-small': props.small,
  };
});
</script>

<style scoped lang="scss">
.input-wrapper {
  display: flex;
  align-items: center;

  width: 100%;
  border-radius: var(--bms-border-radius);
  border: 1px solid var(--field-border-color);
  background-color: var(--input-background-color);

  padding: var(--field-padding);
  height: var(--field-height);

  &:hover {
    --field-border-color: var(--bms-grey-100);
  }

  &:has(input:focus) {
    box-shadow: 0 0 4px 4px light-dark(var(--bms-main-25), var(--bms-main-140));
    --field-border-color: var(--field-border-color-active);
  }

  &.is-error {
    --field-border-color: var(--bms-red-100);
    --input-background-color: var(--bms-red-25);
  }

  &.is-disabled {
    --field-border-color: var(--bms-field-disabled-border-color);
    --input-background-color: var(--bms-field-disabled-background);
    color: var(--bms-field-disabled-text-color);
    input {
      cursor: text;
      opacity: 1;
      -webkit-text-fill-color: currentColor;
    }
  }

  .field__input-label {
    display: block;
    color: var(--bms-grey-50);
    font-size: 12px;
    line-height: 0.2em;
    margin-top: 6px;
    margin-bottom: 4px;
  }
  .field__input-icon {
    display: flex;

    &--start {
      margin-right: 0.5em;
    }

    &--end {
      margin-left: 0.5em;
    }

    :deep(svg) {
      width: 1em;
      height: 1em;
      display: block;
    }

    &:empty {
      display: none;
    }
  }

  input {
    outline: none;
    appearance: none;
    border: 0;
    padding: 0;
    margin: 0;
    font: inherit;
    color: inherit;
    height: 24px;
    line-height: 1;
    width: 100%;
    background-color: transparent;
  }
}
</style>
