import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import withWidth, { isWidthDown } from '@material-ui/core/withWidth';
import { t } from 'Framework/i18n';
import Grid from '@material-ui/core/Grid';
import AmountInput from '../AmountInput';
import isFunction from 'lodash/isFunction';
import get from 'lodash/get';
import find from 'lodash/find';
import sum from 'lodash/sum';
import isEmpty from 'lodash/isEmpty';
import upperFirst from 'lodash/upperFirst';
import ListItem from '@material-ui/core/ListItem';
import Button from '@material-ui/core/Button';
import Typography from '@material-ui/core/Typography';
import Icon from '@material-ui/core/Icon';
import BulkNames from '../../Containers/BulkNames';
import Image from './Image';

const styles = theme => ({
    ProductVariantRoot: {
        height: 'auto',
        alignItems: 'flex-start',
        paddingLeft: 0,
        [theme.breakpoints.down('xs')]: {
            paddingRight: 0,
        },
    },
    ButtonOutlinedRoot: {
        fontWeight: 'bold',
        textTransform: 'none',
        whiteSpace: 'nowrap',
        [theme.breakpoints.down('xs')]: {
            minWidth: 35,
            padding: 0,
        },
        [theme.breakpoints.up('sm')]: {
            display: 'block',
        },
    },
    ButtonOutlinedRootLabel: {
        fontWeight: 'bold',
    },
    ProductVariantImageItem: {
        width: 100,
        height: 100,
        marginRight: 16,
        maxWidth: 100,
    },
    ProductVariantImageItemSizeSelect: {
        marginRight: 16,
        maxWidth: 100,
    },
    productAmounts: {
        [theme.breakpoints.up('sm')]: {
            width: 200,
            maxWidth: 200,
            minWidth: 200,
        },
        [theme.breakpoints.down('sm')]: {
            maxWidth: 225,
        },
    },
    selectedCheck: {
        whiteSpace: 'nowrap',
        paddingBottom: 8,
    },
    TypographyBody1: {
        lineHeight: 2.5,
        display: 'flex',
        justifyContent: 'space-between',
    },
    ProductVariantImage: {
        width: '100px',
        height: '100px',
        maxWidth: 190,
        objectFit: 'contain',
    },
    ProductVariantImageSelected: {
        maxWidth: 210,
        width: '100px',
        height: '100px',
        objectFit: 'contain',
    },
    deleteIcon: {
        lineHeight: '1.3',
        '&:hover': {
            cursor: 'pointer',
        },
    },
    amountVariants: {
        '&.MuiFormControl-marginNormal': {
            marginTop: 4,
        },
        width: 95,
        [theme.breakpoints.down('xs')]: {
            width: 'calc(50% - 5px)',
        },
    },
    amountVariant: {
        width: 150,
        [theme.breakpoints.down('xs')]: {
            width: '100%',
        },
    },
    gridFlowList: ({ width, showReceiveOfferForm, amountData }) => ({
        position: 'relative',
        display: 'grid',
        width: '100%',
        gridAutoFlow: !showReceiveOfferForm && !isWidthDown('sm', width) ? 'column' : '',
        gridTemplateRows:
            !showReceiveOfferForm && !isWidthDown('sm', width)
                ? 'repeat(' + Math.round(amountData.length / 2) + ', auto)'
                : '',
    }),
    checkIcon: {
        lineHeight: '1.5',
    },
});

export const hasError = (identifier, errors) => {
    if (!errors) {
        return false;
    }

    const error = find(errors.errors, function(o) {
        return o.itemIdentifier === identifier;
    });

    return !!error;
};

class ProductVariant extends React.Component {
    static propTypes = {
        handleMultipleAmountInputsChange: PropTypes.func,
        deleteSelectedAmounts: PropTypes.func,
        classes: PropTypes.object,
        amountData: PropTypes.array,
        header: PropTypes.string,
        error: PropTypes.object,
        activeBulkNames: PropTypes.bool,
        showReceiveOfferForm: PropTypes.bool,
        width: PropTypes.string,
        handleChange: PropTypes.func,
        saveConfigurationBulkNames: PropTypes.func,
        BulkNamesComponent: PropTypes.elementType,
        initialWidth: PropTypes.string,
        amountMap: PropTypes.object,
        previewImages: PropTypes.object,
        variantListLoaderElement: PropTypes.element,
    };
    static defaultProps = {
        BulkNamesComponent: BulkNames,
        previewImages: {},
    };
    state = {
        activeItem: null,
        sizes: {},
        showBulkNameForm: false,
        activeVariantItem: {},
        activeSize: {},
    };

    componentDidUpdate(prevProps, prevState) {
        const { amountMap } = this.props;
        const { activeItem } = this.state;
        if (amountMap !== prevProps.amountMap || activeItem !== prevState.activeItem) {
            this.setState({ sizes: amountMap });
        }
    }

    handleChange = (variant, size) => value => {
        //variant sizes length should be > 1 because the button for saving is then visible
        if (variant && variant.sizes && variant.sizes.length > 1 && size && size.identifier) {
            this.setState(state => ({
                sizes: { ...state.sizes, [size.identifier]: value },
            }));
        } else {
            if (isFunction(this.props.handleChange)) {
                this.props.handleChange(variant, size, value);
            }
        }
    };

    handleFocus = event => {
        // select text async for mac os safari
        const target = event.target;
        setTimeout(() => target.select(), 0);
    };

    handleOpenSizeClick = activeItem => () => {
        this.setState({ activeItem });
    };

    handleBulkNameForm = (variant, size) => () => {
        const { activeBulkNames } = this.props;
        if (!activeBulkNames) {
            return;
        }

        this.setState({
            showBulkNameForm: true,
            activeVariantItem: variant,
            activeSize: size || this.state.activeSize,
        });
    };

    handleBulkNamesFormClose = () => {
        this.setState({ showBulkNameForm: false });
    };

    handleBulkNamesSave = (identifier, bulkNamesData) => {
        if (isFunction(this.props.saveConfigurationBulkNames)) {
            this.props.saveConfigurationBulkNames(identifier, bulkNamesData);
        }
    };

    handleConfirmSize = variant => {
        if (isFunction(this.props.handleMultipleAmountInputsChange)) {
            this.props.handleMultipleAmountInputsChange(variant, this.state.sizes);
        }
        this.setState({ activeItem: null });
    };

    deleteAllSelectedAmount = variant => {
        if (isFunction(this.props.deleteSelectedAmounts)) {
            this.props.deleteSelectedAmounts(variant, this.state.sizes);
        }
    };

    render() {
        const {
            classes,
            amountData,
            header,
            error,
            BulkNamesComponent,
            activeBulkNames,
            previewImages,
            variantListLoaderElement,
        } = this.props;

        const { showBulkNameForm, activeVariantItem, activeSize } = this.state;

        if (!amountData || amountData.length === 0) {
            return null;
        }
        const bulkNameVariant = isEmpty(activeSize) ? activeVariantItem : activeSize;
        return (
            <Grid container>
                {header && (
                    <Typography variant="body1">
                        <b>{header}</b>
                    </Typography>
                )}
                <div className={classes.gridFlowList}>
                    {variantListLoaderElement}

                    {amountData.map((variant, i) => {
                        if (variant.isDisabled === true) {
                            return null;
                        }

                        const isSelected = this.state.activeItem
                            ? variant.identifier === this.state.activeItem.identifier
                            : variant === this.state.activeItem;
                        const variantAmountSum = sum(
                            variant.sizes.map(variantSize => Number(variantSize.amount))
                        );
                        const rootProps =
                            variant.sizes.length > 1 ? classes.amountVariants : classes.amountVariant;

                        const imageSrc = get(previewImages, variant.identifier) || variant.url;

                        return (
                            <ListItem
                                key={i}
                                value={variant.title}
                                aria-label={variant.title}
                                className={classes.ProductVariantRoot}
                            >
                                <Grid
                                    item
                                    xs={isSelected ? 4 : 5}
                                    classes={{
                                        item: !isSelected
                                            ? classes.ProductVariantImageItem
                                            : classes.ProductVariantImageItemSizeSelect,
                                    }}
                                >
                                    {imageSrc && (
                                        <Image
                                            src={imageSrc}
                                            alt={variant.title}
                                            aria-label={variant.title}
                                            className={
                                                isSelected
                                                    ? classes.ProductVariantImageSelected
                                                    : classes.ProductVariantImage
                                            }
                                        />
                                    )}
                                </Grid>
                                <Grid item xs={8} className={classes.productAmounts}>
                                    <Typography variant="body1" classes={{ root: classes.TypographyBody1 }}>
                                        <b> {upperFirst(variant.title)}</b>
                                    </Typography>
                                    {!isSelected && variant.sizes.length > 1 && (
                                        <React.Fragment>
                                            {variantAmountSum > 0 && (
                                                <Typography
                                                    variant="body1"
                                                    className={classes.selectedCheck}
                                                    classes={{ root: classes.TypographyBody1 }}
                                                >
                                                    <Icon className={classes.checkIcon}>check</Icon>
                                                    <b>{t('productVariant.amountChosen')}</b>
                                                    {variantAmountSum > 0 && variantAmountSum}
                                                    <Icon
                                                        className={classes.deleteIcon}
                                                        onClick={() => this.deleteAllSelectedAmount(variant)}
                                                    >
                                                        delete_forever
                                                    </Icon>
                                                </Typography>
                                            )}
                                            <Button
                                                variant="outlined"
                                                onClick={this.handleOpenSizeClick(variant)}
                                                classes={{ root: classes.ButtonOutlinedRoot }}
                                                fullWidth
                                            >
                                                {t(
                                                    variant.amount > 0
                                                        ? 'productVariant.adaptSizes'
                                                        : 'productVariant.chooseSize'
                                                )}
                                            </Button>
                                        </React.Fragment>
                                    )}
                                    {(isSelected || variant.sizes.length === 1) && (
                                        <React.Fragment>
                                            {variant.sizes.map(size => (
                                                <AmountInput
                                                    value={size.amount}
                                                    amountLabel={size.label.split(' ').pop()}
                                                    key={size.size}
                                                    onChange={this.handleChange(variant, size)}
                                                    onClick={this.handleBulkNameForm(variant, size)}
                                                    error={hasError(size.identifier, error)}
                                                    disabled={variant.isDisabled}
                                                    onChangeDebounceWait={0}
                                                    readOnly={activeBulkNames}
                                                    rootProps={rootProps}
                                                    onFocus={this.handleFocus}
                                                />
                                            ))}
                                            {variant.sizes.length > 1 && (
                                                <Button
                                                    fullWidth
                                                    variant="outlined"
                                                    onClick={() => this.handleConfirmSize(variant)}
                                                    classes={{
                                                        root: classes.ButtonOutlinedRoot,
                                                        label: classes.ButtonOutlinedRootLabel,
                                                    }}
                                                >
                                                    {t('productVariant.confirmSelection')}
                                                </Button>
                                            )}
                                        </React.Fragment>
                                    )}
                                    {get(variant, 'sizes.length', 0) === 0 && (
                                        <AmountInput
                                            value={variant.amount + ' ' + t('amountSelection.amount')}
                                            hasValueLabel={true}
                                            amountLabel={t('productVariant.amountLabel')}
                                            onChange={this.handleChange(variant)}
                                            onClick={this.handleBulkNameForm(variant)}
                                            error={hasError(variant.identifier, error)}
                                            disabled={variant.isDisabled}
                                            readOnly={activeBulkNames}
                                            onChangeDebounceWait={0}
                                            rootProps={rootProps}
                                            onFocus={this.handleFocus}
                                        />
                                    )}
                                </Grid>
                            </ListItem>
                        );
                    })}
                    {showBulkNameForm && (
                        <BulkNamesComponent
                            selectedAmount={amountData}
                            selectedVariant={activeVariantItem}
                            activeSizeVariant={activeSize}
                            amountLabel={t('productVariant.amountLabel')}
                            handleChange={this.handleChange(bulkNameVariant)}
                            onClose={this.handleBulkNamesFormClose}
                            handleSave={this.handleBulkNamesSave}
                            showBulkNameForm={showBulkNameForm}
                        />
                    )}
                </div>
            </Grid>
        );
    }
}

export default withWidth({ initialWidth: 'lg' })(
    withStyles(styles, { name: 'ProductVariant' })(ProductVariant)
);
