import React, { useEffect, useMemo, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';
import { connect } from 'react-redux';

import RadioGroup from '@material-ui/core/RadioGroup';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Radio from '@material-ui/core/Radio';
import Switch from '@material-ui/core/Switch';
import Grid from '@material-ui/core/Grid';
import FormControl from '@material-ui/core/FormControl';
import { withStyles } from '@material-ui/core/styles';

import MainButton from '../../../Shared/Components/MainButton';
import { T } from '../../../Framework/i18n';
import { getMaxUploadSize } from '../../Reducers/DesignArea/Selectors';
import { getPreviewUrlFromImageData } from '../../Reducers/ImageGallery/Selectors';
import { getEditDataFromOperations } from '../../Reducers/DesignData/Modifiers';
import { editImage, WN_UPLOAD_IMAGE } from '../../Reducers/ImageGallery/Actions';
import { createBackgroundWorkStateSelector } from '../../Reducers/UI/Selectors';
import ImageUpload from '../../Modules/Designer/Components/ImageEditDialog/ImageUpload';
import ColorPicker from '../../Modules/Designer/Components/ImageColorPicker/ImageColorPicker';
import { getRasterURL } from '../../Modules/Designer/Utils/Transformers';
import Progress from '../../Shared/Components/Progress/Progress';
import DefaultThemeProvider from '../Configurator/ThemeProvider';
import { createDesignerProductPreviewManager } from './DesignerProductPreviewManager';
import { defaultClippingColor, loaderKey } from './Constants';
import { createCheckerBoardBackground } from '../../../Utils/Styles/createCheckerBoardBackground';
import Typography from '@material-ui/core/Typography';
import Icon from '@material-ui/core/Icon';
import colorizeIcon from '../../Modules/Designer/Components/ImageEditDialog/res/baseline_colorize_black_24dp.png';

const manager = createDesignerProductPreviewManager();

const Steps = {
    upload: 1,
    removeBackground: 2,
};

const ClippingModes = {
    flood: 'flood',
    replace: 'replace',
};

const styles = theme => ({
    root: {
        overflowX: 'hidden',
        position: 'absolute',
        top: 0,
        left: 0,
        right: 0,
        padding: theme.spacing(1),
        minHeight: 522,
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'space-between',
        boxSizing: 'border-box',
    },
    colorPickerRoot: {
        width: '100%',
        maxWidth: '100%',
        height: '100vh',
        minHeight: '20vh',
        maxHeight: '50vh',
        textAlign: 'center',
        display: 'flex',
        overflow: 'hidden',
        '& canvas': {
            margin: 'auto',
            // use the colorize icon as cursor directly
            cursor: `url(${colorizeIcon}) 2 21, auto`,
        },
    },
    checkerBoard: {
        ...createCheckerBoardBackground(),
    },
    imageUploadDropZone: {
        maxHeight: '50vh',
        minHeight: 266,
    },
    colorPickerInfo: {
        color: '#757575',
        display: 'flex',
        alignItems: 'center',
        marginTop: theme.spacing(1),
    },
    colorPickerInfoText: {
        marginLeft: theme.spacing(1),
        fontStyle: 'italic',
    },
    backgroundRemovalTools: {
        flex: 'auto',
        padding: '12px 0px 12px 12px',
    },
});

const DesignerProductPreviewScreen = props => {
    const {
        // Components
        ThemeProvider,
        ProgressComponent,
        uploadSize,
        imageData,
        editFile,
        classes,
        loading,
    } = props;

    const [step, setStep] = useState(Steps.upload);
    const [uploadValidation, setUploadValidation] = useState({ isValid: false });
    const [editParams, setEditParams] = useState({});
    const [applied, setApplied] = useState(false);
    const imageUploadRef = useRef(null);
    const operations = (imageData && imageData.operations) || null;

    useEffect(() => {
        operations && setEditParams(operations);
    }, [operations]);

    useEffect(() => {
        manager.init({
            onRestoreImage: () => {
                setStep(Steps.removeBackground);
                setApplied(true);
            },
        });
    }, []);

    useEffect(() => {
        if (step === Steps.upload) {
            setEditParams({});
            setUploadValidation({ isValid: false });
        }
    }, [step]);

    useEffect(() => {
        setApplied(false);
    }, [editParams]);

    const previewSrc = useMemo(() => {
        return imageData && `${getRasterURL(getPreviewUrlFromImageData(imageData.preview))}?${Math.random()}`;
    }, [imageData]);

    const nextAction = async () => {
        switch (step) {
            case Steps.upload:
                imageUploadRef.current.uploadFile();
                break;
            case Steps.removeBackground:
                await editFile({ ...editParams, vectorize: true }, imageData);
                manager.useImage();
                setApplied(true);
                break;
        }
    };

    const updateParams = params => {
        setEditParams(params);

        editFile({ ...params, vectorize: false }, imageData);
    };

    const onColorChange = color => {
        const params = { ...editParams, clippingColor: color.hex };

        if (!params.clipping) {
            params.clipping = ClippingModes.replace;
        }

        updateParams(params);
    };

    const toggleBackgroundRemoval = () =>
        updateParams({
            ...editParams,
            clipping: editParams.clipping ? null : ClippingModes.replace,
            clippingColor: editParams.clippingColor || defaultClippingColor,
        });

    const onClippingChange = ({ target: { value: clipping } }) =>
        updateParams({
            ...editParams,
            clipping,
        });

    const clippingEnabled = !!editParams.clipping;

    return (
        <ThemeProvider>
            <div className={classes.root}>
                {step === Steps.upload && (
                    <ImageUpload
                        innerRef={imageUploadRef}
                        uploadSize={uploadSize}
                        onUploadFinished={() => setStep(Steps.removeBackground)}
                        onValidate={setUploadValidation}
                        classes={{
                            imageUploadDropZone: classes.imageUploadDropZone,
                        }}
                    />
                )}
                {step === Steps.removeBackground && (
                    <>
                        <ColorPicker
                            src={previewSrc}
                            onChange={onColorChange}
                            wrapperClassName={clsx(classes.colorPickerRoot, classes.checkerBoard)}
                        />
                        <FormControl component="fieldset" className={classes.backgroundRemovalTools}>
                            <FormControlLabel
                                control={
                                    <Switch
                                        checked={clippingEnabled}
                                        onChange={toggleBackgroundRemoval}
                                        color="primary"
                                    />
                                }
                                label={T('fileUpload.removeBackground')}
                            />
                            <RadioGroup value={editParams.clipping || ''} onChange={onClippingChange}>
                                <FormControlLabel
                                    disabled={!clippingEnabled}
                                    value={ClippingModes.flood}
                                    control={<Radio color="primary" />}
                                    label={T('fileUpload.removeBackgroundFromBorder')}
                                />
                                <FormControlLabel
                                    disabled={!clippingEnabled}
                                    value={ClippingModes.replace}
                                    control={<Radio color="primary" />}
                                    label={T('fileUpload.removeBackgroundEverywhere')}
                                />
                            </RadioGroup>
                            {clippingEnabled && (
                                <Typography variant="caption" className={classes.colorPickerInfo}>
                                    <Icon>colorize</Icon>
                                    <span className={classes.colorPickerInfoText}>
                                        {T('fileUpload.chooseColorForRemove')}
                                    </span>
                                </Typography>
                            )}
                        </FormControl>
                    </>
                )}
                <Grid container justify="space-between">
                    <Grid item>
                        {step === Steps.removeBackground && (
                            <MainButton onClick={() => setStep(Steps.upload)} variant="contained">
                                {T('fileUpload.changeImage')}
                            </MainButton>
                        )}
                    </Grid>
                    <Grid item>
                        <MainButton
                            onClick={nextAction}
                            variant="contained"
                            disabled={
                                (step === Steps.upload && !uploadValidation.isValid) ||
                                (step === Steps.removeBackground && applied)
                            }
                        >
                            {T('fileUpload.continue')}
                        </MainButton>
                    </Grid>
                </Grid>
                <ProgressComponent loading={loading} />
            </div>
        </ThemeProvider>
    );
};

DesignerProductPreviewScreen.propTypes = {
    // Components
    ThemeProvider: PropTypes.elementType,
    ProgressComponent: PropTypes.elementType,
    imageData: PropTypes.object,
    uploadSize: PropTypes.number.isRequired,
    editFile: PropTypes.func.isRequired,
    classes: PropTypes.object.isRequired,
    loading: PropTypes.bool.isRequired,
};

DesignerProductPreviewScreen.defaultProps = {
    // Components
    ThemeProvider: DefaultThemeProvider,
    ProgressComponent: Progress,
};

// Export the non connected Screen
export default DesignerProductPreviewScreen;

const getLoadingState = createBackgroundWorkStateSelector(WN_UPLOAD_IMAGE);

const mapStateToProps = state => {
    const selectedDesignArea = state.designArea.selectedDesignArea;
    const uploadSize = getMaxUploadSize(state);
    const imageData = state.imageGallery.selectedImage;
    const loading = !!(getLoadingState(state.ui) || state.ui.visibilityMap[loaderKey]);

    return {
        selectedDesignArea,
        uploadSize,
        imageData,
        loading,
    };
};

const mapDispatchToProps = dispatch => ({
    editFile: (operations, imageData) => {
        const editData = getEditDataFromOperations(imageData.fileName, operations);
        return dispatch(editImage(editData, { ...imageData, operations }));
    },
});

export const ConnectedDesignerProductPreviewScreen = connect(
    mapStateToProps,
    mapDispatchToProps
)(withStyles(styles, { name: 'DesignProductionPreviewScreen' })(DesignerProductPreviewScreen));
