<script lang="ts" setup>
    import { computed, ref, watch } from 'vue';
    import { mask } from 'maska';

    const props = withDefaults(
        defineProps<{
            value?: string | number;
            maska: string | any[];
            masked?: boolean;
            tokens?: any;
            id: string;
            isAllowSameValues?: boolean;
        }>(),
        {
            value: '',
            masked: false,
            tokens: () => ({}),
            id: '',
            isAllowSameValues: false,
        },
    );

    const emit = defineEmits<{
        input: [any];
        'update:model-value': [any];
        blur: [any];
        focus: [any];
    }>();

    const lastValue = ref<string | null>(null);
    const display = ref(props.value);

    const config = computed(() => ({
        mask: props.maska,
        tokens: Object.assign(
            props.tokens,
            {
                '#': { pattern: /\d/ },
                p: { pattern: /\d|\// },
                F: {
                    pattern: /[0-9АВЕКМНОРСТУХавекмнорстухABEKMHOPCTYXabekmhopctyx]/,
                    transform: (v: string) => v.toUpperCase(),
                },
                f: {
                    pattern: /[АВЕКМНОРСТУХавекмнорстухABEKMHOPCTYXabekmhopctyx]/,
                    transform: (v: string) => v.toUpperCase(),
                },
                A: {
                    pattern: /[0-9ABCDEFGHJKLMNPRSTUVWXYZabcdefghjklmnprstuvwxyz]/,
                    transform: (v: string) => v.toUpperCase(),
                },
                K: {
                    pattern: /[А-Яа-я]/,
                    transform: (v: string) => v.toUpperCase(),
                },
                S: {
                    pattern: /[А-Яа-яA-Za-z0-9]/,
                    transform: (v: string) => v.toUpperCase(),
                },
            },
            props.tokens,
        ),

        masked: props.masked,
    }));

    const refresh = (val: any) => {
        display.value = val;
        const value = mask(val, config.value.mask, config.value.tokens, config.value.masked);
        if (value !== lastValue.value || props.isAllowSameValues) {
            lastValue.value = value;
            emit('input', value);
            emit('update:model-value', value);
        }
    };

    watch(
        () => props.value,
        (newValue) => {
            if (newValue !== lastValue.value) {
                display.value = newValue;
            }
        },
    );

    watch(
        () => props.masked,
        () => {
            refresh(display.value);
        },
    );

    const onInput = (evt: any) => {
        refresh(evt.target.value);
    };
</script>

<template>
    <input
        :id="id"
        v-maska="config"
        :value="display"
        @maska="onInput"
        @blur="emit('blur', $event)"
        @focus="emit('focus', $event)"
    />
</template>
