import React from 'react';
import PropTypes from 'prop-types';
import { t } from 'Framework/i18n';
import FileDrop from 'react-file-drop';
import { withStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import ImageIcon from '@material-ui/icons/Image';
import CheckCircleIcon from '@material-ui/icons/CheckCircle';
import ErrorIcon from '@material-ui/icons/Error';
import LoopIcon from '@material-ui/icons/Loop';
import Checkbox from '@material-ui/core/Checkbox';
import FormGroup from '@material-ui/core/FormGroup';
import Button from '@material-ui/core/Button';
import MainButton from 'Shared/Components/MainButton';
import { Services } from 'App/ServiceLocator';
import withWidth, { isWidthDown } from '@material-ui/core/withWidth';
import { getConf } from '../../../../configuration';
import { calculateImageBrightness } from '../../../../Services/DesignDataService';

const styles = theme => ({
    imagePreview: {
        maxWidth: 400,
        maxHeight: 200,
        [theme.breakpoints.down('sm')]: {
            maxWidth: 300,
            maxHeight: 160,
        },
        resizeMode: 'contain',
        boxShadow: theme.shadows[4],
    },
    imageUploadDropZone: {
        background: 'white',
        height: 335,
        width: 450,
        border: '1px dashed #ccc',
        borderRadius: 4,
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        [theme.breakpoints.down('sm')]: {
            width: 'auto',
        },
        [theme.breakpoints.down('xs')]: {
            height: 300,
        },
    },
    imageUploadContainer: {
        background: 'white',
        width: '100%',
        margin: 30,
        borderRadius: 4,
        [theme.breakpoints.down('xs')]: {
            margin: 16,
        },
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
    },
    imageUploadIcon: {
        fontSize: 30,
        marginRight: 5,
        color: theme.palette.primary.darkText,
    },
    imageUploadIconError: {
        fontSize: 50,
        marginBottom: 5,
        color: 'red',
    },
    imageUploadIconSuccess: {
        color: '#4FC36D',
    },
    imageUploadButton: {
        fontSize: 15,
        [theme.breakpoints.down('xs')]: {
            padding: '0 24px',
            height: 56,
        },
        '& input': {
            position: 'absolute',
            top: 0,
            left: 0,
            bottom: 0,
            right: 0,
            opacity: 0,

            '&:hover': {
                cursor: 'pointer',
            },
        },
    },
    imageUploadOwnership: {
        padding: '20px 0px 20px 12px',
        maxWidth: 450,
        minHeight: 65,
        '& span': {
            fontSize: 15,
        },
        [theme.breakpoints.down('sm')]: {
            width: 'auto',
        },
    },
    imageUploadOwnershipCheckbox: {
        marginBottom: 'auto',
        padding: '0 12px',
    },
    colorChecked: {
        '& svg': {
            color: theme.palette.primary.main,
        },
    },
    imageUploadChangeImageButton: {
        textTransform: 'none',
        fontWeight: 'bold',
    },
    imageUploadText: {
        margin: '0 100px',
        marginBottom: 10,
        overflow: 'hidden',
        textOverflow: 'ellipsis',
        textAlign: 'center',
        width: '100%',
        [theme.breakpoints.down('sm')]: {
            marginLeft: 0,
            marginRight: 0,
        },
    },
    imageUploadTextError: {
        color: 'red',
        margin: '0 45px 20px',
    },
    imageUploadTextSuccess: {
        overflow: 'hidden',
        textOverflow: 'ellipsis',
        textAlign: 'left',
        [theme.breakpoints.down('sm')]: {
            marginLeft: 0,
            marginRight: 0,
        },
        color: '#4FC36D',
        fontWeight: 'bold',
    },
    termsAndConditionsLink: {
        color: 'black',
    },
    ownershipError: {
        color: '#f00',
        paddingLeft: 36,
        textAlign: 'initial',
    },
    uploadTextIconContainer: {
        flexDirection: 'row',
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center',
        marginTop: 10,
        marginBottom: 10,
        width: '100%',
        alignSelf: 'center',
    },
    checkerBackground: {
        backgroundImage:
            'linear-gradient(45deg, #F0F0F0 25%, transparent 25%), ' +
            'linear-gradient(-45deg, #F0F0F0 25%, transparent 25%), ' +
            'linear-gradient(45deg, transparent 75%, #F0F0F0 75%), ' +
            'linear-gradient(-45deg, transparent 75%, #F0F0F0 75%)',
        backgroundSize: '20px 20px',
        backgroundPosition: '0 0, 0 10px, 10px -10px, -10px 0px',
    },
});

class ImageEditDialog extends React.Component {
    static propTypes = {
        classes: PropTypes.object,
        uploadSize: PropTypes.number,
        onValidate: PropTypes.func,
        onUploadFinished: PropTypes.func,
        width: PropTypes.string,
        checkOwnership: PropTypes.bool,
        imageIcon: PropTypes.element,
        checkIcon: PropTypes.element,
        errorIcon: PropTypes.element,
        loopIcon: PropTypes.element,
    };

    static defaultProps = {
        checkOwnership: true,
    };

    constructor(props) {
        super(props);

        this.state = {
            selectedFile: null,
            ownershipChecked: false,
            ownershipErrorVisible: false,
            error: null,
            imageData: null,
            uploadDelayed: false,
        };
        this.ownershipGroup = React.createRef();
        this.dropZone = React.createRef();
    }

    handleInputChange = evt => this.updateFile(evt.target.files[0]);

    handleDrop = files => this.updateFile(files[0]);

    handleUpload = async image => {
        return await calculateImageBrightness(image);
    };

    updateFile = file => {
        if (!file) {
            return;
        }

        const { uploadSize, onValidate } = this.props;
        let error = null;

        if (file.size > uploadSize) {
            const maxUploadSize = parseFloat(
                (uploadSize / Math.pow(1024, Math.floor(Math.log(uploadSize) / Math.log(1024)))).toFixed(2)
            );

            error = t('fileUpload.uploadSizeError', { uploadSize: maxUploadSize });
        }

        const extension = file.name.toLowerCase().match(/\.([0-9a-z]+)$/i)[1];

        const allowedFormats = getConf('designer.allowedImageUploadFormats').split(',');
        if (allowedFormats.indexOf(extension) === -1) {
            error = t('fileUpload.uploadFormatError', { formats: allowedFormats.join(', ').toUpperCase() });
        }
        onValidate && onValidate({ isValid: !error, error });

        this.setState({
            ownershipErrorVisible: false,
            selectedFile: file,
            error,
            imageData: null,
        });
        const renderableFormats = ['jpg', 'jpeg', 'svg', 'png', 'bmp', 'gif'];
        const isRenderable = renderableFormats.indexOf(extension) !== -1;
        if (isRenderable && file.type && file.type.match('image.*')) {
            const reader = new FileReader();
            reader.onload = async e => {
                let image = new Image();
                image.onload = async () => {
                    image = await this.handleUpload(image);
                    this.setState({ imageData: image });
                };
                image.src = e.target.result;
            };
            reader.readAsDataURL(file);
        }
    };

    handleImageOwnershipChange = (event, checked) => {
        this.setState({
            ownershipErrorVisible: false,
            ownershipChecked: checked,
        });
    };

    uploadFile = async () => {
        const { ownershipChecked, selectedFile } = this.state;
        const { checkOwnership } = this.props;

        if (!selectedFile) {
            return;
        }

        if (checkOwnership && !ownershipChecked) {
            this.setState({
                ownershipErrorVisible: true,
            });
            if (
                this.ownershipGroup &&
                this.ownershipGroup.current &&
                typeof this.ownershipGroup.current.scrollIntoView === 'function'
            ) {
                this.ownershipGroup.current.scrollIntoView();
            }
            return;
        }

        // reset the error before the next upload
        this.setState({
            error: null,
        });

        try {
            await Services.designer.uploadFile(selectedFile);

            if (
                this.dropZone.current &&
                this.dropZone.current &&
                typeof this.dropZone.current.scrollIntoView === 'function'
            ) {
                this.dropZone.current.scrollIntoView();
            }
            const { onUploadFinished } = this.props;
            onUploadFinished && onUploadFinished();
        } catch (e) {
            // eslint-disable-next-line no-console
            console.error(e);
            this.setState({
                error: t('fileUpload.processingFailed'),
            });
        }
    };

    getAllowedImageFormats = () => {
        const formats = getConf('designer.allowedImageUploadFormats').split(',');
        return formats ? formats.map(format => `.${format}`) : 'image/*';
    };

    render() {
        const { classes, width, checkOwnership, imageIcon, checkIcon, errorIcon, loopIcon } = this.props;
        const { ownershipChecked, ownershipErrorVisible, selectedFile, error, imageData } = this.state;

        return (
            <FileDrop
                onDrop={this.handleDrop}
                draggingOverTargetClassName={'draggingOverDropZone'}
                accept="image/jpeg,image/jpg,image/tiff,image/gif"
                multiple={false}
            >
                <div className={classes.imageUploadDropZone} ref={this.dropZone}>
                    <div className={classes.imageUploadContainer}>
                        {selectedFile === null && (
                            <React.Fragment>
                                {imageIcon ?? <ImageIcon className={classes.imageUploadIcon} />}
                                <Typography className={classes.imageUploadText} variant="body2">
                                    {t(
                                        isWidthDown('sm', width)
                                            ? 'fileUpload.uploadFiles'
                                            : 'fileUpload.dragDropFiles'
                                    )}
                                </Typography>
                                <MainButton
                                    onClick={() => {}}
                                    variant="contained"
                                    className={classes.imageUploadButton}
                                >
                                    {t('fileUpload.chooseImage')}
                                    <input
                                        type="file"
                                        accept={this.getAllowedImageFormats()}
                                        onChange={this.handleInputChange}
                                    />
                                </MainButton>
                            </React.Fragment>
                        )}
                        {selectedFile !== null && (
                            <React.Fragment>
                                {imageData && (
                                    <img
                                        className={`${classes.imagePreview} ${
                                            imageData.isBright ? classes.checkerBackground : ''
                                        }`}
                                        alt={selectedFile.name}
                                        src={imageData.src}
                                    />
                                )}
                                {error === null ? (
                                    <div className={classes.uploadTextIconContainer}>
                                        {checkIcon ?? (
                                            <CheckCircleIcon
                                                className={`
                                                ${classes.imageUploadIcon}
                                                ${classes.imageUploadIconSuccess}
                                            `}
                                            />
                                        )}
                                        <Typography
                                            variant="body2"
                                            className={classes.imageUploadTextSuccess}
                                        >
                                            {selectedFile.name}
                                        </Typography>
                                    </div>
                                ) : (
                                    <React.Fragment>
                                        {errorIcon ?? <ErrorIcon className={classes.imageUploadIconError} />}
                                        <Typography
                                            variant="body2"
                                            className={`
                                                        ${classes.imageUploadText}
                                                        ${classes.imageUploadTextError}
                                             `}
                                        >
                                            {error}
                                        </Typography>
                                    </React.Fragment>
                                )}
                                <Typography variant="body2" className={classes.imageUploadText}>
                                    {t(
                                        isWidthDown('sm', width)
                                            ? 'fileUpload.changeFiles'
                                            : 'fileUpload.dragDropFiles'
                                    )}
                                </Typography>
                                <Button
                                    onClick={() => {}}
                                    variant="text"
                                    className={`${classes.imageUploadButton} ${classes.imageUploadChangeImageButton}`}
                                >
                                    {loopIcon ?? <LoopIcon />} {t('fileUpload.changeImage')}
                                    <input
                                        type="file"
                                        accept={this.getAllowedImageFormats()}
                                        onChange={this.handleInputChange}
                                    />
                                </Button>
                            </React.Fragment>
                        )}
                    </div>
                </div>
                {checkOwnership && (
                    <FormGroup classes={{ root: classes.imageUploadOwnership }} ref={this.ownershipGroup}>
                        <FormControlLabel
                            control={
                                <Checkbox
                                    classes={{
                                        root: classes.imageUploadOwnershipCheckbox,
                                        checked: classes.colorChecked,
                                    }}
                                    checked={ownershipChecked}
                                    onChange={this.handleImageOwnershipChange}
                                    disabled={false}
                                />
                            }
                            label={
                                <span
                                    dangerouslySetInnerHTML={{
                                        __html: t('fileUpload.confirmImageOwnership'),
                                    }}
                                />
                            }
                        />
                        {ownershipErrorVisible && (
                            <Typography variant="body2" className={classes.ownershipError}>
                                {t('fileUpload.imageOwnershipError')}
                            </Typography>
                        )}
                    </FormGroup>
                )}
            </FileDrop>
        );
    }
}

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