import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import get from 'lodash/get';
import findIndex from 'lodash/findIndex';
import values from 'lodash/values';
import first from 'lodash/first';

import { containerConnect } from 'Framework/ComponentContainer';
import { t } from 'Framework/i18n';

import { Services } from 'App/ServiceLocator';
import {
    getActiveDesignAreas,
    getSelectedDesignAreaProperties,
    getDesignDataColorAmounts,
    getDefaultDesignAreaIdentifierFromProductionMethod,
} from 'App/Reducers/DesignArea/Selectors';
import { createBackgroundWorkStateSelector } from 'App/Reducers/UI/Selectors';
import { getItem } from 'App/Reducers/Configurator/Selectors';

import CalculationWidget from '../Components/CalculationWidget';
import Notification from 'App/Shared/Components/Notification';
import PriceList from 'App/Shared/Components/PriceList';
import Progress from 'App/Shared/Components/Progress/Progress';
import { TotalPrice } from '../Components/TotalPrice/TotalPrice';

import { createPricePropsFromState, createAmountPropsFromState } from 'App/Shared/Containers/AmountPrice';
import { EventTypes } from 'App/Constant';
import { getConf } from 'App/configuration';
import createSelector from 'Utils/Function/createSelector';
import keys from 'lodash/keys';
import pickBy from 'lodash/pickBy';
import { selectDesignArea } from 'App/Reducers/DesignArea/Actions';
import { isConfigurationModeAvailable } from 'App/Reducers/ConfigurationMode/Selectors';

const onSelectableCalculationChange = (identifier, value) =>
    Services.configurator.setSelectedCalculation(identifier, value);

const CalculationWidgetContainer = ({ containerProps, ...props }) => {
    const { isLoadingPrice, isLoadingCritical, amountProps, priceProps, vatNotice } = containerProps;
    const {
        CalculationWidgetComponent,
        PriceListComponent,
        ProgressComponent,
        NotificationComponent,
        TotalPriceComponent,
    } = props;
    const { error } = priceProps;
    const errors = get(error, 'errors', []);
    const showPriceList = priceProps.priceList.length > 0;

    const { defaultDesignArea, activeDesignAreas, toggleDesignArea } = props;

    useEffect(() => {
        defaultDesignArea &&
            findIndex(values(activeDesignAreas)) === -1 &&
            toggleDesignArea(defaultDesignArea, true);
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    return (
        <CalculationWidgetComponent
            priceListComponent={
                <div style={{ position: 'relative' }}>
                    <ProgressComponent loading={isLoadingPrice} />
                    {showPriceList && (
                        <React.Fragment>
                            <PriceListComponent
                                amount={amountProps.amount}
                                list={priceProps.priceList}
                                totalPrice={priceProps.priceFormatted}
                                taxNote={vatNotice}
                                onSelectableChanged={onSelectableCalculationChange}
                            />
                            <TotalPriceComponent totalPrice={priceProps.priceFormatted} taxNote={vatNotice} />
                        </React.Fragment>
                    )}
                </div>
            }
            loaderComponent={<ProgressComponent loading={isLoadingCritical} />}
            notificationComponent={errors.map((errorItem, key) => (
                <NotificationComponent
                    priceList={priceProps.priceList}
                    key={key}
                    icon="error"
                    color="error"
                    notification={t('amountPrice.minimumAmountError', {
                        minimumAmount: errorItem.minimumAmount,
                        itemTitle: errorItem.itemTitle,
                        selectedAmount: errorItem.selectedAmount,
                    })}
                />
            ))}
            {...props}
        />
    );
};

CalculationWidgetContainer.propTypes = {
    containerProps: PropTypes.object,
    PriceListComponent: PropTypes.elementType,
    ProgressComponent: PropTypes.elementType,
    NotificationComponent: PropTypes.elementType,
    CalculationWidgetComponent: PropTypes.elementType,
    TotalPriceComponent: PropTypes.elementType,
    toggleDesignArea: PropTypes.func,
    defaultDesignArea: PropTypes.string,
    activeDesignAreas: PropTypes.object,
};

CalculationWidgetContainer.defaultProps = {
    CalculationWidgetComponent: CalculationWidget,
    PriceListComponent: PriceList,
    ProgressComponent: Progress,
    NotificationComponent: Notification,
    TotalPriceComponent: TotalPrice,
    defaultDesignArea: null,
    activeDesignAreas: {},
};

const getSavingState = createBackgroundWorkStateSelector('saveConfiguration');
const getDefaultDesignAreaIdentifier = createSelector(
    ({ filteredDesignAreas }) => filteredDesignAreas,
    filteredDesignAreas => {
        let defaultDesignArea = null;
        if (filteredDesignAreas.length > 0) {
            defaultDesignArea =
                getDefaultDesignAreaIdentifierFromProductionMethod(Services.store.state) ||
                first(filteredDesignAreas).identifier;
        }
        return defaultDesignArea;
    }
);
const mapStateToProps = state => {
    const {
        filteredDesignAreas,
        designProductionMethod,
        selectedDesignArea,
    } = getSelectedDesignAreaProperties(state);

    const designAreas = filteredDesignAreas.map(da => ({
        ...da,
        name: da.title,
    }));
    const designProductionMethods = (selectedDesignArea.designProductionMethods || []).map(dpm => ({
        ...dpm,
        name: dpm.title,
    }));

    const colorAmountList = [];
    const maxColorAmount = get(designProductionMethod, 'options.maxColorAmount');
    if (maxColorAmount) {
        for (let i = 1; i <= maxColorAmount; i++) {
            colorAmountList.push({
                identifier: i,
                name: i + (i === 1 ? t('designAreaControlbox.color') : t('designAreaControlbox.colors')),
            });
        }
    }

    const priceProps = createPricePropsFromState(state.configurator);
    const amountProps = createAmountPropsFromState(state.configurator);
    const isLoadingPrice = get(state.api, 'sources.calculation.isFetching', false);
    const isInitialLoadingInProgress = !getItem(state.configurator).identifier && state.api.isFetching;
    const isLoadingCritical = getSavingState(state.ui) || isInitialLoadingInProgress;
    const isSaveButtonEnabled = isConfigurationModeAvailable(state) && !isLoadingPrice && !priceProps.error;
    const activeDesignAreas = getActiveDesignAreas(state);
    const colorAmounts = getDesignDataColorAmounts(state);
    const vatNotice = !getConf('displayNetPrices', false)
        ? t('amountPrice.vatNotice')
        : t('amountPrice.vatNoticeNet');
    const defaultDesignArea = getDefaultDesignAreaIdentifier(state.designArea);
    const hasGlobalErrors = get(state, 'ui.error');
    return {
        Component: defaultDesignArea || hasGlobalErrors ? CalculationWidgetContainer : () => null,

        containerProps: {
            isLoadingPrice,
            amountProps,
            priceProps,
            isLoadingCritical,
            vatNotice,
        },

        colorAmountList: colorAmountList,
        designProductionMethods: designProductionMethods,
        amountValue: amountProps.amount,
        designAreas: designAreas,
        currentDesignProductionMethod: designProductionMethod,
        colorAmounts: colorAmounts,
        selectedDesignArea: selectedDesignArea,
        isSaveButtonEnabled,
        activeDesignAreas,
        defaultDesignArea,
    };
};

const mapDispatchToProps = () => ({
    onChangeAmount: amount => {
        Services.configurator.skipNextCalculationAutoResolve();
        Services.configurator.setSelectedAmount(false, amount);
    },
    handleChangeDesignArea: identifier => Services.store.dispatch(selectDesignArea(identifier)),
    handleChangeDesignProductionMethod: identifier => {
        Services.designData.setDesignProductionMethod(identifier);
    },
    handleChangeSelectedColorAmount: (designAreaIdentifier, value) => {
        Services.designData.getSampleCanvasEditorForDesignArea(designAreaIdentifier).setColorAmount(value);
    },
    toggleDesignArea: (designAreaIdentifier, active) => {
        Services.designData.getSampleCanvasEditorForDesignArea(designAreaIdentifier).toggleSampleText(active);
        Services.analytics.triggerEvent(
            active ? EventTypes.widget_add_design_area : EventTypes.widget_remove_design_area,
            designAreaIdentifier
        );
    },
    addPlaceholderImage: (
        active,
        designAreaIdentifiers = keys(pickBy(getActiveDesignAreas(Services.store.state)))
    ) => {
        Services.designData.addSampleImageForDesignAreas(designAreaIdentifiers, active);
    },
    onClickSaveConfiguration: () => Services.interaction.saveWidgetConfigurationAndOpenConfigurator(),
    onClickPrintConfiguration: () => Services.interaction.saveWidgetConfigurationAndOpenPdf(),
});

export default containerConnect(mapStateToProps, mapDispatchToProps);
