import { getConf, SaveTypes, WidgetAfterSaveMethods } from '../configuration';
import { Services } from '../ServiceLocator';
import AbstractInteractionService from '../../Framework/Services/AbstractInteractionService';
import Api from '../../Framework/Api';
import { t } from 'Framework/i18n';
import { getConfiguration } from '../Reducers/Configurator/Selectors';
import { EventTypes } from '../Constant';
import { METHOD_CONFIGURATION_SAVED, METHOD_REQUEST_OFFER_FORM_SENT } from '../Utils/createMessageInterface';

export default class InteractionService extends AbstractInteractionService {
    constructor() {
        super();
    }

    init() {
        Services.store.observeStore(
            state => state.i18n.locale,
            language => {
                Services.interaction.doLanguageSwitch(language);
            }
        );
    }

    postMessageToContainer(data, options) {
        const conf = {
            targetOrigin: '*',
            ...options,
        };
        const wnd = conf.window || window;
        if (wnd.parent.postMessage !== undefined) {
            const { targetOrigin } = conf;
            wnd.parent.postMessage(data, targetOrigin);
        }
    }

    async saveConfiguration() {
        const { ui, configurator } = Services;

        ui.dismissError();
        ui.beginWork('saveConfiguration');
        ui.hide('optionlist');
        ui.show('saveConfiguration');

        try {
            await configurator.captureAndSaveConfiguration(SaveTypes.USER);
            const { code } = configurator.state.configuration;
            this.postMessageToContainer({
                method: METHOD_CONFIGURATION_SAVED,
                code,
            });
        } catch (e) {
            // eslint-disable-next-line no-console
            console.error(e);
            ui.reportError(t('saveConfiguration.error.savingFailed'));
        } finally {
            ui.endWork('saveConfiguration');
        }
    }

    async shareConfiguration() {
        const { ui, configurator } = Services;

        ui.dismissError();
        ui.beginWork('shareConfiguration');
        ui.hide('optionlist');
        ui.show('shareConfiguration');

        try {
            await configurator.captureAndSaveConfiguration(SaveTypes.SHARE);
        } catch (e) {
            // eslint-disable-next-line no-console
            console.error(e);
            ui.reportError(t('shareConfiguration.error.savingFailed'));
        } finally {
            ui.endWork('shareConfiguration');
        }
    }

    async mailConfiguration() {
        const { ui, configurator } = Services;

        ui.dismissError();
        ui.beginWork('mailConfiguration');
        ui.hide('optionlist');
        ui.show('mailConfiguration');
        ui.show('globalLoader');
        try {
            await configurator.captureAndSaveConfiguration(SaveTypes.MAIL);
        } catch (e) {
            // eslint-disable-next-line no-console
            console.error(e);
            ui.reportError(t('mailConfiguration.error.savingFailed'));
        } finally {
            ui.hide('globalLoader');
            ui.endWork('mailConfiguration');
        }
    }

    async printConfiguration() {
        const { ui, configurator } = Services;

        ui.dismissError();
        ui.beginWork('printConfiguration');
        ui.hide('optionlist');
        ui.show('printConfiguration');
        ui.show('globalLoader');

        try {
            await configurator.captureAndSaveConfiguration(SaveTypes.PRINT);
        } catch (e) {
            // eslint-disable-next-line no-console
            console.error(e);
            ui.reportError(t('printConfiguration.error.savingFailed'));
        } finally {
            ui.endWork('printConfiguration');
            ui.hide('globalLoader');
        }
    }

    loadConfiguration(clearLoadCode = true) {
        if (clearLoadCode) {
            Services.configurator.setLoadCode();
        }
        Services.ui.dismissError();
        Services.ui.show('loadConfiguration');
    }

    async adminSaveConfiguration(saveType) {
        const { ui, configurator } = Services;

        ui.dismissError();
        ui.beginWork('adminSaveConfiguration');
        ui.hide('optionlist');

        try {
            const configuration = configurator.prepareConfigurationForSave(true);
            await configurator.createMediaDataForConfiguration(configuration);
            return Services.adminArea.saveConfiguration(configuration, saveType);
        } catch (e) {
            // eslint-disable-next-line no-console
            console.error(e);
            ui.reportError(t('saveConfiguration.error.savingFailed'));
        } finally {
            ui.endWork('adminSaveConfiguration');
        }
    }

    async adminGetConfiguration() {
        const { ui, configurator } = Services;

        const work = ui.beginWork('adminGetConfiguration');

        ui.dismissError();
        ui.hide('optionlist');

        try {
            const configuration = configurator.prepareConfigurationForSave(true);
            await configurator.createMediaDataForConfiguration(configuration);
            return configuration;
        } catch (e) {
            // eslint-disable-next-line no-console
            console.error(e);
            ui.reportError(t('saveConfiguration.error.savingFailed'));
        } finally {
            work.done();
        }
    }

    async addToCart() {
        const { ui, configurator } = Services;

        ui.dismissError();
        ui.beginWork('addToCart');
        ui.hide('optionlist');
        ui.show('addToCartPopUpLoader');

        try {
            const overwriteConfiguration = getConf('fromBasket', false);

            const extraData = overwriteConfiguration
                ? { code: Services.configurator.state.configuration.code }
                : {};

            const result = await configurator.captureAndSaveConfiguration(SaveTypes.CART, extraData);
            Services.configurator.addToCartCallback(result.data);
        } catch (e) {
            // eslint-disable-next-line no-console
            console.error(e);
            ui.reportError(t('saveConfiguration.error.savingFailed'));
            throw e;
        } finally {
            ui.endWork('addToCart');
            ui.hide('addToCartPopUpLoader');
        }
    }

    async sendReceiveOfferRequest(formData) {
        if (formData.hasError) {
            return false;
        }

        try {
            Services.ui.show('addToCartPopUpLoader');
            await Services.configurator.captureAndSaveConfiguration(SaveTypes.OFFERREQUEST);
            Services.analytics.triggerEvent(EventTypes.selected_amounts);
        } catch (e) {
            Services.ui.reportError(t('receiveOfferForm.sentError'));

            return false;
        } finally {
            Services.ui.hide('addToCartPopUpLoader');
        }

        const { configuration } = Services.configurator.state;

        const data = {
            configurationCode: configuration.code,
            emailAddress: formData.email,
            name: formData.name,
            company: formData.company,
            phoneNumber: formData.phonenumber,
            street: formData.street,
            zip: formData.zip,
            city: formData.city,
            country: formData.country,
        };

        try {
            await Api.request({ url: 'receiveoffers/request', method: 'post', data: data });
            this.postMessageToContainer({
                method: METHOD_REQUEST_OFFER_FORM_SENT,
                code: configuration.code,
            });
        } catch (error) {
            Services.ui.reportError(t('receiveOfferForm.sentError'));

            return false;
        }

        Services.ui.reportError(t('receiveOfferForm.sentOk'));

        return true;
    }

    doLanguageSwitch(language) {
        if (Api.setLanguage(language) === 1) {
            // if newly set, save and load the configuration
            return Services.configurator.saveAndReloadConfiguration(SaveTypes.LANGUAGESWITCH);
        }
    }

    setChannel(channel) {
        if (Api.setChannel(channel) === 1) {
            // if newly set, save and load the configuration
            if (getConf('setChannelReloadOnly')) {
                return Services.configurator.loadInitialConfiguration();
            } else {
                return Services.configurator.saveAndReloadConfiguration(SaveTypes.CHANNELSWITCH);
            }
        }
    }

    async saveWidgetConfiguration() {
        const { ui, configurator } = Services;

        ui.dismissError();
        ui.beginWork('saveConfiguration');

        try {
            await configurator.prepareAndSaveConfiguration(SaveTypes.WIDGET);
        } catch (e) {
            // eslint-disable-next-line no-console
            console.error(e);
            ui.reportError(t('saveConfiguration.error.savingFailed'));
        } finally {
            ui.endWork('saveConfiguration');
        }
    }

    openConfigurator(configuration = getConfiguration(Services.configurator.state), options = {}) {
        const conf = {
            targetOrigin: '*',
            ...(getConf('openConfigurator') || {}),
            ...options,
        };
        const { code } = configuration;
        const wnd = conf.window || window;
        switch (conf.method) {
            case WidgetAfterSaveMethods.PostMessage: {
                if (wnd.parent.postMessage !== undefined) {
                    const { targetOrigin } = conf;
                    wnd.parent.postMessage({ method: 'openConfigurator', code }, targetOrigin);
                }
                break;
            }
            case WidgetAfterSaveMethods.OpenNewWindow: {
                wnd.open(`/code:${code}${wnd.location.search}`);
                break;
            }
        }
    }

    async createPdfUrl(
        documentType = 'user',
        configuration = getConfiguration(Services.configurator.state),
        queryParams = {}
    ) {
        const params = { ...Api.getGETParameters(), ...queryParams };
        const customKeys = Object.keys(queryParams);
        const keys = ['_language', '_client', '_channel', '_display_net_prices', '_share_url'];
        const mergedKeys = keys.concat(customKeys);
        const query = new URLSearchParams(location.search);
        let queryString = Object.keys(params)
            .filter(key => mergedKeys.indexOf(key) !== -1)
            .map(key =>
                key === '_share_url' ? key + '=' + encodeURIComponent(params[key]) : key + '=' + params[key]
            )
            .join('&');
        if (query.has('_hide_prices')) {
            queryString = queryString.concat('&_hide_prices=' + query.get('_hide_prices'));
        }
        if (query.has('_cta_element')) {
            queryString = queryString.concat('&_cta_element=' + query.get('_cta_element'));
        }
        return `${getConf('network.baseURL', '/')}configurations/pdf/${documentType}/${
            configuration.code
        }?${queryString}`;
    }

    async printConfigurationAndOpenPdf() {
        await this.printConfiguration();
        Services.interaction.showPdfDownloadDialog();
    }

    async saveWidgetConfigurationAndOpenPdf() {
        await this.saveWidgetConfiguration();
        const pdfUrl = await this.createPdfUrl('widget');
        window.open(pdfUrl);
    }

    async saveWidgetConfigurationAndOpenConfigurator() {
        await this.saveWidgetConfiguration();
        this.openConfigurator();
    }

    showLoadConfigurationDialog() {
        Services.ui.show('loadConfiguration');
    }

    showSendEmailDialog() {
        Services.ui.show('sendEmail');
    }

    showPdfDownloadDialog() {
        Services.ui.show('pdfDownload');
    }
}
