<template>
    <Form
        ref="contact-details-form"
        v-slot="{ meta }"
        @submit="onSubmit"
        @invalidSubmit="onInvalidSubmit">
        <div class="fade-on-route-transition">
            <div class="justify-content-center">
                <siteHeader
                    ref="siteHeader"
                    :cmsWidgetName="widget.siteHeader" />
            </div>
            <div class="iss-heritage-container-width">
                <div class="contact-details-container iss-heritage-content-container-width">
                    <siteSubHeader
                        id="sub-header"
                        ref="siteSubHeader"
                        class="subheader"
                        :cmsWidgetName="widget.siteSubHeader" />
                    <!-- TO DO: Use MSR appointment information for MSR -->
                    <alert
                        ref="appointmentInformationAlert"
                        isCollapsible
                        alertClass="alert-warning"
                        :cmsWidgetName="widget.appointmentInformation" />
                    <checkbox
                        v-if="showSameAsPolicyAddressQuestion"
                        ref="sameAsPolicyAddressQuestion"
                        v-model="isSameAsPolicyAddress"
                        checkboxName="sameAsPolicyAddress"
                        buttonID="sameAsPolicyAddress"
                        class="form-group same-address-checkbox"
                        :checkboxLabel="sameAsPolicyAddressQuestionText" />
                    <textboxQuestion
                        ref="addressQuestion"
                        v-model="address"
                        inputId="address"
                        class="form-group"
                        :cmsWidgetName="widget.streetAddressQuestion"
                        isRequired
                        :validationRules="'street-address-required'" />
                    <textboxQuestion
                        ref="address2Question"
                        v-model="address2"
                        inputId="address2"
                        class="form-group"
                        :cmsWidgetName="widget.apartmentQuestion" />
                    <textboxQuestion
                        ref="cityQuestion"
                        v-model="city"
                        inputId="city"
                        class="form-group"
                        :cmsWidgetName="widget.cityQuestion"
                        isRequired
                        :validationRules="'city-required'" />
                    <dropdownQuestion
                        ref="stateQuestion"
                        v-model="state"
                        inputId="state"
                        class="form-group"
                        :cmsWidgetName="widget.stateQuestion"
                        :options="getStates"
                        isDisabled />
                    <textboxQuestion
                        ref="zipCodeQuestion"
                        v-model="zipCode"
                        inputId="zipCode"
                        class="form-group"
                        :cmsWidgetName="widget.zipCodeQuestion"
                        isDisabled />
                    <alert
                        ref="changeZipCodeAlert"
                        class="zip-alert"
                        isCollapsible
                        alertClass="alert-warning"
                        :startCollapsed="true"
                        :cmsWidgetName="widget.changeZipCodeAlert" />
                    <buttonQuestion
                        ref="vehicleProtectedQuestion"
                        v-model="isVehicleProtected"
                        inputId="vehicleProtected"
                        class="form-group"
                        isRequired
                        groupName="vehicleProtectedQuestion"
                        :questionText="vehicleProtectedQuestionText"
                        :answers="vehicleProtectedQuestionAnswers"
                        :buttonTypeString="'listButtonHorizontal'" />
                    <textBlock
                        ref="clearanceText"
                        class="clearance-text"
                        :cmsWidgetName="widget.clearanceText" />
                    <textareaQuestion
                        ref="notesQuestion"
                        v-model="notesForTechnician"
                        inputId="technicianNotes"
                        class="form-group"
                        :isDisabled="false"
                        :isRequired="false"
                        :cmsWidgetName="widget.notesQuestion"
                        maxLength="150"
                        :inputRows="4" />
                    <siteFooter
                        ref="siteFooter"
                        :cmsWidgetName="widget.siteFooter"
                        :isForwardActionDisabled="!meta.valid"
                        @forwardClicked="forwardButtonAction"
                        @backClicked="navigateBack" />
                </div>
            </div>
        </div>
    </Form>
</template>
<script>
// Components
import siteHeader from '@/iss-components/site-header/site-header.vue';
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
import textboxQuestion from '@/digital-components/textbox-question/textbox-question.vue';
import checkbox from '@/ux-components/checkbox/checkbox.vue';
import textareaQuestion from '@/digital-components/textarea-question/textarea-question.vue';
import alert from '@/ux-components/alert/alert.vue';
import dropdownQuestion from '@/digital-components/dropdown-question/dropdown-question.vue';
import textBlock from '@/digital-components/text-block/text-block.vue';
import buttonQuestion from '@/digital-components/button-question/button-question.vue';

// Supporting files
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper.js';
import { defineRule, Form } from 'vee-validate';
import BaseFormMixin from '@/mixins/base-form-mixin.js';
import { useMainStore } from '@/store/index.js';
import MaskaFormattedMasks from '@/constants/maska-masks';
import errorMessages from '@/constants/error-messages';
import { required } from '@/helpers/validation-rules';
import widgetFields from '@/constants/cms-widget-fields';
import states from '@/constants/states';
import applicationConfig from '@/constants/application-config';

// DEFINE VALIDATION RULES
defineRule('street-address-required', required(errorMessages.SERVICE_ADDRESS_REQUIRED));
defineRule('city-required', required(errorMessages.SERVICE_CITY_REQUIRED));

export default {
    name: 'contact-details',
    components: {
        siteHeader,
        siteSubHeader,
        textboxQuestion,
        checkbox,
        textareaQuestion,
        siteFooter,
        Form,
        alert,
        buttonQuestion,
        dropdownQuestion,
        textBlock
    },
    mixins: [BaseFormMixin],
    async beforeRouteEnter(to, from, next) {
        const cmsContent = await fetchCmsContentForPage(to.query.issPage);

        next(async (vm) => {
            vm.setCmsContent(cmsContent);
            await vm.setupAddressLookup();
        });
    },
    data() {
        const {
            notesForTechnician
        } = useMainStore().contactInfo;
        const {
            address,
            address2,
            city,
            state,
            zipCode,
            isVehicleProtected
        } = useMainStore().serviceLocation;
        return {
            notesForTechnician,
            address,
            address2,
            city,
            state,
            zipCode,
            isVehicleProtected: isVehicleProtected ?? '',
            isSameAsPolicyAddress: false,
            widget: {
                siteHeader: 'SiteHeaderWidget',
                siteSubHeader: 'SiteSubHeaderWidget',
                appointmentInformation: 'AppointmentInformationAlertWidget',
                MSRAppointmentInformation: 'MSRAppointmentInformationAlertWidget',
                sameAsPolicyAddressQuestion: 'SameAsPolicyAddressQuestionWidget',
                streetAddressQuestion: 'StreetAddressQuestionWidget',
                apartmentQuestion: 'ApartmentQuestionWidget',
                emailQuestion: 'EmailQuestionWidget',
                cityQuestion: 'CityQuestionWidget',
                stateQuestion: 'StateQuestionWidget',
                zipCodeQuestion: 'ZipCodeQuestionWidget',
                changeZipCodeAlert: 'ChangeZipCodeAlertWidget',
                vehicleProtectedQuestion: 'VehicleProtectedQuestionWidget',
                clearanceText: 'ClearanceTextWidget',
                notesQuestion: 'NotesQuestionWidget',
                siteFooter: 'SiteFooterWidget'
            },
            states
        };
    },
    computed: {
        phoneMask() {
            return MaskaFormattedMasks.PHONE_NUMBER;
        },
        showSameAsPolicyAddressQuestion() {
            return this.zipCode === useMainStore().customerData.addressQuestions.zipCode;
        },
        sameAsPolicyAddressQuestionText() {
            return this.getCmsContent(this.widget.sameAsPolicyAddressQuestion, widgetFields.INPUT_QUESTION_WIDGET.QUESTION_TEXT);
        },
        vehicleProtectedQuestionText() {
            return this.getCmsContent(this.widget.vehicleProtectedQuestion, widgetFields.INPUT_QUESTION_WIDGET.QUESTION_TEXT);
        },
        vehicleProtectedQuestionAnswers() {
            return this.getCmsContent(this.widget.vehicleProtectedQuestion, widgetFields.INPUT_QUESTION_WIDGET.ANSWERS) || [];
        },
        getStates() {
            return Object.keys(states).reduce((acc, key) => {
                acc[key] = states[key].toUpperCase();
                return acc;
            }, {});
        },
    },
    watch: {
        isSameAsPolicyAddress(newValue) {
            this.pushEventToGA("mobile_location", "same_as_policy_address", newValue ? "checked" : "unchecked", true);
            if (newValue) {
                this.copyPolicyAddressToServiceLocation();
            } else {
                this.clearAddressFields();
            }
        },
        isVehicleProtected(newValue) {
            this.pushEventToGA("mobile_location", "is_vehicle_protected", newValue, true);
        }
    },
    methods: {
        /**
         * @summary Steps to perform when forward button clicked.
         */
        async forwardButtonAction() {
            const contactInfo = {
                notesForTechnician: this.notesForTechnician
            };
            useMainStore().updateContactInfo(contactInfo);

            const provider = useMainStore().serviceLocation.provider;

            await this.geocodeAddress();

            useMainStore().updateServiceLocation({
                address: this.address,
                address2: this.address2,
                city: this.city,
                isVehicleProtected: this.isVehicleProtected || 'false',
                provider
            });

            this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD, this.$route);
        },
        copyPolicyAddressToServiceLocation() {
            const { addressQuestions } = useMainStore().customerData;
            this.address = addressQuestions.streetAddress;
            this.address2 = addressQuestions.streetAddress2;
            this.city = addressQuestions.city;
        },
        clearAddressFields() {
            this.address = '';
            this.address2 = '';
            this.city = '';
        },
        async setupAddressLookup() {
            const apiKey = applicationConfig.GOOGLE_PLACES_API_KEY;

            await this.$loadScript(`https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=places&callback=Function.prototype`)
                .catch(() => {
                    // Failed to fetch script
                    window.console.warn('Unable to load Google Places API script');
                });
        },
        geocodeAddress() {
            const autoCompletePromise = new Promise((resolve, reject) => {
                try {
                // Get Autocomplete Service
                    const acService = new window.google.maps.places.AutocompleteService();
                    // Get Places Service, needs pseudo element (or a map)
                    const placeService = new window.google.maps.places.PlacesService(document.createElement('div'));
                    // Create Autocomplete Session token, multiple requests one pricing hit
                    const acSessionToken = new window.google.maps.places.AutocompleteSessionToken();

                    const addressValue = `${this.address}, ${this.city}, ${this.state} ${this.zipCode}`;
                    acService.getPlacePredictions(
                        {
                            input: addressValue,
                            type: ['geocode'],
                            componentRestrictions: { country: ['us'] },
                            sessionToken: acSessionToken
                        },
                        (predictions) => {
                            if (predictions && predictions.length > 0) {
                                const firstPrediction = predictions[0];
                                if (firstPrediction.place_id) {
                                    placeService.getDetails(
                                        {
                                            placeId: firstPrediction.place_id,
                                            fields: ['address_components'],
                                            sessionToken: acSessionToken
                                        },
                                        (details) => {
                                            this.fillInAddress(details);
                                            resolve();
                                        }
                                    );
                                } else {
                                    resolve();
                                }
                            } else {
                                resolve();
                            }
                        }
                    );
                } catch (error) {
                    window.console.warn('Error initializing Google Places API services', error);
                    resolve();
                }
            });

            return autoCompletePromise;
        },
        async fillInAddress(googlePlace) {
            let processedStreetAddress = false;
            let processedRoute = false;
            for (const component of googlePlace.address_components) {
                const componentType = component.types[0];

                switch (componentType) {
                    case 'street_number': {
                        if (processedRoute) {
                            this.address = `${component.long_name} ${this.address}`;
                        } else {
                            this.address = component.long_name;
                        }

                        processedStreetAddress = true;
                        break;
                    }
                    case 'route': {
                        if (processedStreetAddress) {
                            this.address += ` ${component.short_name}`;
                        } else {
                            this.address = component.short_name;
                        }

                        processedRoute = true;
                        break;
                    }
                    case 'locality': {
                        this.city = component.long_name;
                        break;
                    }
                    default:
                }
            }
        },
    }
};
</script>

<style lang="scss" scoped>
.iss-heritage-container-width {
    .contact-details-container {
        position: relative;
        min-height: 1px;
        padding-left: .9375rem;
        padding-right: .9375rem;
    }
}
.zip-alert {
    :deep(a) {
        padding: 0;
        border-bottom: 1.5px solid #125b7e;
        color: #125b7e;
        &:hover, &:focus {
            border-color: transparent;
            color: $heritage-blue-secondary;
            text-decoration: none;
        }
    }
}
.textbox-question {
    :deep(.form-label:has(strong)) {
        font-weight: $font-weight-normal;
        color: $darker-gray;
        strong {
            font-weight: 600;
            color: $black;
        }
    }
}
.subheader {
    margin: 1.25rem 0;
}
.form-group {
    margin-bottom: 1.25rem;
}
.same-address-checkbox {
    :deep(.form-check-input) {
        &:checked + label p,
        & + label p {
            font-size: 1rem;
            font-weight: $font-weight-normal;
            color: $darker-gray;
        }
    }
}
.clearance-text {
    font-size: .875rem;
    line-height: 1.25rem;
    margin-top: 0rem;
    margin-bottom: .3125rem;
}
</style>
