<template>
    <label
        :class="[buttonWrapperClasses, { 'has-error': errors.length > 0 }]"
        :for="buttonId"
        @mousedown.left="handleEventAction('click', $event)">
        <input
            :type="inputType"
            :id="buttonId"
            :key="buttonId"
            :name="groupName"
            :class="inputClasses"
            :aria-required="isRequired"
            :value="value"
            :checked="isChecked"
            @keypress.enter="handleEventAction('keypressSubmit', $event)"
            @change="handleEventAction('change', $event)" />

        <slot></slot>
    </label>
</template>

<script>
import { queryStrings } from "@/constants/query-strings";
import { useField } from "vee-validate";
import { toRef } from "vue";

export default {
    name: "base-input-button",
    emits: ["change"],
    model: {
        prop: "modelValue",
        event: "change",
    },
    props: {
        value: {
            type: [String, Number],
            required: true,
        },
        modelValue: {
            type: [Array, String, Number],
            required: true,
        },
        isMultiSelect: Boolean,
        isWide: Boolean,
        buttonImage: String,
        buttonImageId: String,
        buttonLabel: {
            type: String,
            required: true,
        },
        isRequired: {
            type: Boolean,
            required: true,
        },
        buttonLabelSubCopy: {
            type: String,
            required: true,
        },
        groupName: {
            type: String,
            required: true,
        },
        validationRules: {
            type: String,
            default: "",
        },
        buttonWrapperClasses: [String, Array, Object],
        inputClasses: [String, Array, Object],
        valueToLogType: String,
        selectOnKeypress: {
            type: Boolean,
            default: true,
        },
    },
    data() {
        return {
            valueToEmit: null,
        };
    },
    mounted() {
        if (this.isChecked) {
            this.handleChange(this.modelValue);
        }
    },
    methods: {
        handleEventAction(eventType, e) {
            const eventTypes = {
                CHANGE: "change",
                KEYPRESS_SUBMIT: "keypressSubmit",
                CLICK: "click",
            };

            if (this.isMultiSelect) {
                switch (eventType) {
                    case eventTypes.KEYPRESS_SUBMIT:
                        this.handleClick(e);
                        break;
                    case eventTypes.CHANGE:
                        this.selectOnKeypress
                            ? this.handleClick(e)
                            : this.handleSelectionChange(e);
                        break;
                }
            } else {
                switch (eventType) {
                    case eventTypes.CLICK:
                    case eventTypes.KEYPRESS_SUBMIT:
                        this.handleClick(e);
                        break;
                    case eventTypes.CHANGE:
                        this.selectOnKeypress
                            ? this.handleClick(e)
                            : this.handleSelectionChange(e);
                        break;
                }
            }
        },
        handleSelectionChange(e) {
            if (
                this.isMultiSelect &&
                (this.modelValue instanceof Array || this.modelValue == null)
            ) {
                let newValue = this.modelValue ? [...this.modelValue] : [];
                if (!newValue.includes(this.value)) {
                    newValue.push(this.value);
                } else {
                    newValue.splice(newValue.indexOf(this.value), 1);
                }

                this.valueToEmit = newValue;
            } else {
                this.valueToEmit = this.value;
            }

            this.handleChange(this.valueToEmit);
            this.pushClickEventToGA();
        },
        handleClick(e) {
            this.handleSelectionChange(e);
            this.$emit("change", this.valueToEmit);
        },
        pushClickEventToGA() {
            this.pushEventToGA(
                this.$route.query[queryStrings.FMG_PAGE],
                this.GaActions.CLICKED,
                this.value.toString(),
                true,
                this.valueToLogType
            );
        },
    },
    computed: {
        isChecked() {
            if (this.isMultiSelect || this.modelValue instanceof Array) {
                return this.modelValue.includes(this.value);
            }

            return this.modelValue == this.value;
        },
        inputType() {
            return this.isMultiSelect ? "checkbox" : "radio";
        },
        buttonId() {
            return `${this.groupName}-${JSON.stringify(this.value).replace(" ", "-")}`;
        },
    },
    setup(props) {
        const inputType = props.isMultiSelect ? "checkbox" : "radio";

        const fieldOptions = {
            type: inputType,
            validateOnValueUpdate: false,
            validateOnMount: false,
        };

        const { handleChange, meta, errors, value } = useField(
            toRef(props, "groupName"),
            toRef(props, "validationRules"),
            fieldOptions
        );

        return {
            handleChange,
            errors,
            meta,
            fieldOptions, // only need to expose this for unit test purposes
        };
    },
};
</script>

<style lang="scss" scoped>
input {
    opacity: 0;
    height: 0.1px; // NOTE: cannot be zero or Safari can't put focus on it
    width: 0;
}
</style>
