<template>
    <div
        class="textbox-question"
        :class="[
            ((errors && errors.length) || hasError) ? 'has-error' : '',
            (meta?.valid && meta?.touched && !((errors && errors.length) || hasError)) ? 'has-success' : ''
        ]">
        <label
            v-if="displayQuestionText"
            :for="inputId"
            :aria-label="questionTextForAria"
            class="form-label"
            :class="[questionAlignment === 'center' ? 'text-center w-100 mb-5' : '']"
            v-html="questionText"></label>
        <div
            class="input-wrapper"
            :class="[
                includeSearchIcon ? 'has-search-icon' : '',
                includeSelectIcon ? 'has-select-icon' : '',
                hasTextButton ? 'has-text-button' : ''
            ]">
            <input
                :id="inputId"
                :ref="inputId"
                v-model.trim="value"
                v-maska
                :data-maska="getMaskFromProp"
                :data-maska-tokens="getTokensFromProp"
                class="form-control"
                :type="type"
                :name="inputId"
                :placeholder="placeholderText"
                :aria-disabled="isDisabled"
                :disabled="isDisabled"
                :aria-required="isRequired"
                :aria-label="questionTextForAria"
                :min="min"
                :max="max"
                :required="isRequired"
                :class="[
                    hasIcon ? 'has-icon' : '',
                    iconRight ? 'icon-right' : '',
                    cornerStyle === 'rounded' ? 'rounded-pill' : ''
                ]"
                :validationRules="validationRules"
                :maxlength="maxLength ? maxLength : '999'"
                :data-bs-toggle="includeSelectIcon ? 'modal' : ''"
                :data-bs-target="'#' + cmsWidgetName"
                @change="handleChange"
                @blur="handleChange"
                @focus="$emit('focus', $event.target.value)"
                @paste="trimOnPaste"
                @drop="trimOnPaste" />
            <button
                v-if="includeSearchIcon"
                type="submit"
                aria-label="Search button"
                @click="clickedSearch" />
            <button
                v-if="includeSelectIcon"
                type="submit"
                data-bs-toggle="modal"
                :data-bs-target="'#' + cmsWidgetName"
                aria-label="Select button" />
            <buttonMain
                v-if="hasTextButton"
                ref="buttonMain"
                variant="primary"
                :buttonText="buttonText"
                @clickEvent="clickedTextButton">
            </buttonMain>
        </div>
        <div
            v-show="errorMessage"
            ref="errorMessageDiv"
            class="row my-1 form-test-error">
            <span
                class="d-inline-flex mt-0"
                role="alert">{{ errorMessage }}</span>
        </div>
    </div>
</template>

<script>
import { useField, validate } from 'vee-validate';
import { extractSpanText } from '@/helpers/text-helper';
import buttonMain from '@/ux-components/button-main/button-main.vue';

export default {
    name: 'textbox-question',
    components: {
        buttonMain
    },
    props: {
        type: {
            type: String,
            default: 'text'
        },
        placeholderText: {
            type: String,
            default: ''
        },
        displayQuestionText: {
            type: Boolean,
            default: true
        },
        modelValue: String,
        inputId: {
            type: String,
            required: true
        },
        isDisabled: Boolean,
        isRequired: Boolean,
        hasIcon: Boolean, // If input has an icon
        iconRight: Boolean, // Place icon on right side of text input, otherwise default is left if hasIcon prop is used
        hasError: Boolean,
        mask: {
            type: [String, Object],
            default: ''
        },
        validationRules: String,
        cmsWidgetName: {
            type: String,
            default: ''
        },
        maxLength: String,
        questionAlignment: String, // Left or center. Left is default.
        cornerStyle: String, // Rounded or square. Square is default.
        includeSearchIcon: Boolean,
        includeSelectIcon: Boolean,
        min: String,
        max: String,
        disableAutoFill: Boolean,
        buttonCallback: {
            type: Function,
            default: () => {}
        }
    },
    emits: ['focus', 'update:modelValue', 'textboxQuestionEvent.inputIdAssigned', 'click-event'],
    setup(props) {
        const propsClone = { ...props };
        const { modelValue } = propsClone;
        let initialValue;

        switch (typeof modelValue) {
            case 'number':
                initialValue = modelValue;
                break;
            default:
                initialValue = modelValue && modelValue.length > 0 ? modelValue : '';
                break;
        }

        const fieldOptions = {
            type: 'text',
            value: modelValue,
            initialValue
        };

        // eslint-disable-next-line no-shadow
        const { errorMessage, handleBlur, handleChange, meta, validate, errors } =
            useField(props.inputId, props.validationRules, fieldOptions);

        return {
            errorMessage,
            handleBlur,
            handleChange,
            validate,
            meta,
            errors
        };
    },
    computed: {
        questionText() {
            return this.getCmsContent(this.cmsWidgetName, 'QuestionText');
        },
        questionTextForAria() {
            return extractSpanText(this.getCmsContent(this.cmsWidgetName, 'QuestionText'));
        },
        buttonText() {
            return this.getCmsContent(this.cmsWidgetName, 'ButtonText');
        },
        hasTextButton() {
            return this.buttonText && this.buttonText.length > 0;
        },
        value: {
            get() {
                return this.modelValue;
            },
            set(newValue) {
                this.$emit('update:modelValue', newValue);
            }
        },
        getMaskFromProp() {
            if (this.mask) {
                if (this.mask.mask) {
                    return this.mask.mask;
                }
                return this.mask;
            }
            return null;
        },
        getTokensFromProp() {
            if (this.mask?.tokens) {
                return `{ '${this.mask.tokens.token}': { 'pattern': '${this.mask.tokens.pattern}' }}`;
            }
            return null;
        }
    },
    watch: {
        async value(newValue) {
            const result = await validate(newValue, this.validationRules); // do a test validation check, without triggering full validation
            if (result.valid) {
                this.handleChange(newValue); // trigger full validation on this field only
            }
        }
    },
    mounted() {
        this.$emit('textboxQuestionEvent.inputIdAssigned', this.inputId);
    },
    methods: {
        trimOnPaste(evt) {
            evt.stopPropagation();
            evt.preventDefault();

            const input = document.getElementById(evt.srcElement.id);
            const originalValue = input.value;
            const startPosition = input.selectionStart;
            const endPosition = input.selectionEnd;
            const selectionLength = endPosition - startPosition;

            let data = null;
            if (evt.type === 'paste') {
                data = evt.clipboardData || window.clipboardData;
            } else {
                data = evt.dataTransfer;
            }

            const textValue = data.getData('Text');

            // Insert the pasted/dropped string at the index position
            const arrOriginalString = originalValue.split('');
            arrOriginalString.splice(startPosition, selectionLength, textValue);
            const blendedString = arrOriginalString.join('');

            this.$emit('update:modelValue', blendedString);
        },
        clickedSearch() {
            if (this.meta.valid) {
                this.$emit('click-event');
            }
        },
        async clickedTextButton() {
            const result = await validate(this.value, this.validationRules);
            if (result.valid) {
                this.handleChange(this.value);
                this.$emit('click-event');
            }
        }
    }
};
</script>

<style lang="scss" scoped>
@import "@/styles/ux-variables-svg-strings.scss";
input[type='date']::-webkit-inner-spin-button {
    display: none;
}

input[type='date']::-webkit-calendar-picker-indicator {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    right: 1px;
    background-image: url($svg-calendar-picker);
    background-repeat: no-repeat;
    background-position: center;
    width: 16px; // check this
    height: 16px;
    display: flex;
    border-radius: 0 7px 7px 0;
    background-color: #e4f1f7;
    &:hover {
        cursor: pointer;
    }
    padding: 15px 0;
    min-width: 48px;
}

input::-webkit-date-and-time-value {
    text-align: left !important;
}

.textbox-question {
    label {
        color: $black;
        font-weight: 600;
    }
    span {
        font-weight: 400;
        font-size: 0.875rem;
        color: #4d5151;
    }
    .form-test-error span {
        color: $red;
        font-size: 1rem;
        font-weight: 400;
    }

    .input-wrapper {
        position: relative;
        &.has-search-icon {
            input[type='text'] {
                border-radius: $border-radius;
            }
            button[type='submit'] {
                position: absolute;
                top: 50%;
                transform: translateY(-50%);
                right: 0;
                background-image: url($svg-search-icon);
                background-repeat: no-repeat;
                background-position: center;
                border-radius: 0 $border-radius-lg $border-radius-lg 0;
                background-color: $blue-100;
                width: 2.75rem;
                height: 100%;
                border: 1px solid $gray-500;
                border-left: none;
                display: flex;
            }
        }
        &.has-select-icon {
            button[type='submit'] {
                position: absolute;
                top: 50%;
                transform: translateY(-50%);
                right: 1rem;
                background-image: url($svg-select-icon);
                background-repeat: no-repeat;
                background-position: center;
                background-color: transparent;
                width: 1rem;
                height: 100%;
                border: 0px;
                border-left: none;
                display: flex;
            }
        }
        &.has-text-button {
            display: flex;
            input[type='text'] {
                border-radius: 1.5rem;
                border-top-right-radius: 0;
                border-bottom-right-radius: 0;
            }
            button {
                border-top-left-radius: 0;
                border-bottom-left-radius: 0;
                min-width: 6.875rem;
            }
        }
    }
    input {
        &.has-icon {
            background-image: url(~@/assets/img/icons/location-pin.svg);
            background-repeat: no-repeat;
            background-position: 0.75rem 50%;
            background-size: auto 1rem;
            padding: 0 0.75rem 0 2.5rem;
            &.icon-right {
                background-position: calc(100% - 0.75rem) 50%;
                padding: 0 2.5rem 0 0.75rem;
            }
        }
    }
    .form-label {
        margin-bottom: 0.25rem;
    }
    .form-control {
        border: $border-input;
        border-radius: $border-radius;
        min-height: 2.8125rem;
        max-height: 2.8125rem;
        padding: 0.75rem 1rem;
        letter-spacing: inherit;
        box-shadow: $box-shadow-input;
        &::placeholder {
            color: $gray-500;
        }
        &:focus, &:focus-within {
            border: $border-input-focus;
        }
        &:disabled,
        &.disabled {
            background-color: $gray-100;
        }
    }
    p {
        display: none;
    }
}
</style>
