<template>
  <FormWrapper
    class="space-input"
    v-bind="formProps"
    ref="elementRef"
  >
    <input
      ref="inputRef"
      class="grow h600 mask-input"
      :class="{ disabled: disabled }"
      :placeholder="placeholder"
      :disabled="disabled"
      @focus="$emit('focus')"
      :type="type"
      @keydown.enter="submit"
      v-focus-directive="focus"
      v-max-value-directive="maxValue"
      v-numeric-directive="numeric"
      v-max-length-directive="maxLength"
      v-digits-directive="digits"
    />
    <div class="input-icon">
      <slot />
    </div>
    <div class="icon input-icon" v-if="icon">
      <img :src="icon" />
    </div>
  </FormWrapper>
</template>

<script lang="ts">
import { defineComponent, onMounted, reactive, ref, toRefs, watch } from "vue";
import { NumericDirective } from "@/directives/numeric";
import { MaxValueDirective } from "@/directives/max-value";
import { DigitsDirective } from "@/directives/digits";
import { MaxLengthDirective } from "@/directives/max-length";
import { FocusDirective } from "@/directives/focus";
import FormWrapper from "../FormWrapper.vue";
import FormMixin from "@/mixins/FormMixin";
import IMask, { InputMask } from "imask";

export default defineComponent({
    mixins: [
        FormMixin
    ],
    emits: ['update:modelValue', 'focus'],
    props: {
      modelValue: {
        // type: [ String, Number, Object ],
        required: true,
      },
      numeric: {
        type: Boolean,
        default: false
      },
      digits: {
        type: Boolean,
        default: false
      },
      maxLength: {
        type: [Number, Boolean],
        default: false
      },
      maxValue: {
        type: [Number, Boolean],
        default: false
      },
      mask: {
        type: [String, Number, Object]
      },
      formatted: {
        type: Boolean,
      },
      disabled: {
        type: Boolean,
        default: false,
      },
    },
    components: { FormWrapper },
    directives: {
      NumericDirective,
      MaxValueDirective,
      DigitsDirective,
      MaxLengthDirective,
      FocusDirective
    },
    setup(props, { emit }) {
      const refs = reactive({
        inputRef: null
      });
      const elementRef = ref();
      const iMask = ref<InputMask<any> | null>(null);
      const currentValue = ref();
      const formatted = ref();

      const setValues = (): void => {
        const newVal =
          props.modelValue === null || typeof props.modelValue === "undefined"
            ? ""
            : props.modelValue.toString();
        currentValue.value = newVal;


        if (props.mask) {
          (iMask.value as InputMask<any>).value = newVal;
          (iMask.value as InputMask<any>).updateValue();
        } else {
          const el = refs.inputRef;
          if (el) el.value = newVal;
        }
      };
        
      const initMask = (maskOptions: any): void => {
        iMask.value = IMask(refs.inputRef, maskOptions);

        iMask.value.on("accept", () => {
          if (formatted.value) {
            currentValue.value = iMask.value.value;
          } else {
            currentValue.value = iMask.value.unmaskedValue;
          };

          emit("update:modelValue", currentValue.value);
        });
      };

      watch(
        () => props.modelValue,
        (newValue) => {
          currentValue.value = newValue;
          setValues();
        }
      );

      onMounted(() => {
        if (props.mask) {
          initMask(props.mask);
        };
        if (props.modelValue) {
          currentValue.value = props.modelValue;
          setValues();
        };
      });

      return {
        ...toRefs(refs),
        currentValue,
        elementRef,
      }
    }
});
</script>

<style scoped lang="scss">
.space-input {
  input {
    background-color: var(--background);
    border: 1px solid var(--border-color);
    padding: var(--form-side-padding);
    border-radius: var(--form-border-radius);
    color: var(--text-color);
    pointer-events: var(--pointer-events);
    height: var(--height);
    transition: var(--transition);
    width: 100%;

    &::placeholder {
      color: var(--form-placeholder-color);
    }

    &:focus {
      --border-color: var(--form-border-color-focus);
      box-shadow: var(--form-box-shadow);
    }
  }

  .input-icon {
    pointer-events: none;
    position: absolute;
    top: 50%;
    right: var(--form-side-padding);
    transform: translateY(-50%);
  }

  &.disabled {
    input {
      pointer-events: none;
    }
  }
}
</style>
