import React from 'react';
import PropTypes from 'prop-types';
import isFunction from 'lodash/isFunction';
import upperFirst from 'lodash/upperFirst';
import uniqBy from 'lodash/uniqBy';
import { withStyles } from '@material-ui/core/styles';
import Grid from '@material-ui/core/Grid';
import Card from '@material-ui/core/Card';
import CardContent from '@material-ui/core/CardContent';
import Select from '@material-ui/core/Select';
import Input from '@material-ui/core/Input';
import MenuItem from '@material-ui/core/MenuItem';
import ListItemText from '@material-ui/core/ListItemText';
import FormControl from '@material-ui/core/FormControl';
import Typography from '@material-ui/core/Typography';
import TextField from '@material-ui/core/TextField';
import Icon from '@material-ui/core/Icon';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Switch from '@material-ui/core/Switch';
import CardActions from '@material-ui/core/CardActions';
import SearchIcon from '@material-ui/icons/Search';
import withWidth, { isWidthDown } from '@material-ui/core/withWidth';
import { t } from 'Framework/i18n';
import { isMobileDevice } from 'Framework/Helpers/isMobileDevice';
import { createSelectionRangeMemo } from 'Utils/Helper/createSelectionRangeMemo';
import MainButton from 'Shared/Components/MainButton';
import { withResizeDetectWrapper } from 'Shared/HOCs/ResizeDetect/ResizeDetect';
import AnalyticsWrapper from 'App/Shared/Components/Analytics/AnalyticsWrapper';
import { ColorPalettesSearch } from './ColorPalettesSearch';

const styles = theme => ({
    container: {
        pointerEvents: 'all', // catch the pointer events again
    },
    containerInPortraitMode: {
        width: '40%',
        position: 'fixed',
        bottom: 0,
        paddingBottom: 20,
        left: 16,
    },
    card: {
        height: '100%',
        borderTop: '7px solid ' + theme.palette.primary.main,
        position: 'relative',

        [theme.breakpoints.down('xs')]: {
            boxShadow: 'none',
        },
    },
    colorCardActions: {
        padding: '0 16px 16px 16px',

        [theme.breakpoints.down('xs')]: {
            padding: '0 16px',
            display: 'flex',
            height: 56,
            bottom: 16,
            right: 0,
            left: 0,
            position: 'fixed',
            background: 'white',
        },
    },
    cardUnboxed: {
        height: '100%',
        borderTop: 'none',
        boxShadow: 'none',

        [theme.breakpoints.down('xs')]: {
            boxShadow: 'none',
        },
    },
    customColorGrid: {
        textAlign: 'center',
        margin: 'auto',
    },
    alignTypo: {
        marginBottom: '16px',
        [theme.breakpoints.down('xs')]: {
            marginBottom: '9px',
        },
    },
    colorPaletteTitle: {},
    arrowNone: {
        display: 'none !important',
    },
    colorPaletteColors: {
        border: '1px solid ' + theme.palette.secondary.light,
        borderRadius: '50%',
        width: 32,
        height: 32,
        minWidth: 32,
        minHeight: 32,
        cursor: 'pointer',
    },
    colorPaletteWrapper: ({ heightColorPaletteWrapper, width, isCustomColorChecked }) => ({
        maxHeight: isWidthDown('xs', width)
            ? isCustomColorChecked
                ? heightColorPaletteWrapper - 90
                : heightColorPaletteWrapper
            : 290,
        padding: '0 16px',
        display: 'flex',
        flexWrap: 'wrap',
        marginBottom: 16,
        overflowY: 'auto',
    }),
    switchBaseSpacing: {
        padding: 9,
    },
    colorPaletteSearchWrapper: {
        marginBottom: 16,
    },
    colorPaletteDisabled: {
        color: theme.palette.secondary.lighter,
    },
    colorWrapper: {
        height: 40,
        display: 'flex',
        alignItems: 'center',
        marginTop: 11,
        marginBottom: 5,
        width: 'calc(100% / 2)',
        '&:hover': {
            cursor: 'pointer',
        },
    },
    usedColorWrapper: {
        display: 'inline-flex',
        padding: 12,
    },
    searchPaletteGrid: {
        padding: 0,
    },
    selectedColorText: {
        '& span': {
            fontSize: '12px',
            fontWeight: 'bold',
            fontStyle: 'italic',
            textDecoration: 'underline',
        },
    },
    selectColorMenu: {
        '& div': {
            '& span': {
                fontSize: 14,
                padding: '0 16px',
            },
        },
    },
    colorPaletteButton: {
        marginTop: 24,
        padding: 8,
        [theme.breakpoints.down('sm')]: {
            marginTop: '0',
        },
        [theme.breakpoints.down('xs')]: {
            height: 56,
        },
    },

    selectedColorGrid: {
        margin: '0 auto',
    },
    cardContentRoot: {},
    gridColorContent: {
        maxHeight: '100%',
    },
    RootListItem: {
        margin: '0 16px',
        padding: 0,
        overflow: 'hidden',
        textOverflow: 'ellipsis',
        display: 'flex',
        alignItems: 'center',
        '& span': {
            fontSize: '15px',
            maxWidth: 80,
            maxHeight: 45,
            lineHeight: 1.5,
            webkitLineClamp: 2,
            webkitBoxOrient: 'vertical',
            overflow: 'hidden',
            textOverflow: 'ellipsis',
            display: 'block',
        },
        [theme.breakpoints.between('xs', 'sm')]: {
            width: '100%',
        },
    },
    selectedColorField: {
        padding: '15px 14px',
        fontSize: 15,
    },
    selectedColorLabel: {
        fontSize: 15,
    },
    disabledColorWrap: {
        cursor: 'unset',
        background: theme.palette.secondary.lighter + ' !important',
        border: '1px solid ' + theme.palette.secondary.lighter,
    },
    disabledColorText: {
        '& span': {
            color: theme.palette.secondary.lighter + ' !important',
        },
    },
    selectedColorWrap: {
        border: 'solid 1px ' + theme.palette.secondary.light,
        boxShadow: '3px 2px 5px ' + theme.palette.secondary.light,
        borderRadius: '50%',
    },
    DialogCloseIcon: {
        position: 'absolute',
        right: 16,
        top: 20,

        '&:hover': {
            cursor: 'pointer',
        },
    },
    searchColorIcon: {
        left: 15,
        top: 6,
        position: 'relative',
        color: theme.palette.primary.darkText,

        '&:hover': {
            cursor: 'pointer',
        },
    },
    iconColorWrap: {
        height: 24,
        [theme.breakpoints.down('sm')]: {
            height: 34,
        },
    },
    formControlCustomColor: {
        marginLeft: -8,
        [theme.breakpoints.down('sm')]: {
            paddingLeft: 16,
            paddingTop: 12,
        },
    },
    underlineInputText: {
        marginBottom: 8,
        //https://github.com/mui-org/material-ui/issues/12192#issuecomment-406182809
        '&&&&:hover:before': {
            borderBottom: '1px solid rgba(0, 0, 0, 0.42)',
        },
        '&:after': {
            borderBottom: '1px solid transparent',
        },
    },
    outlinedInput: {
        fontSize: 15,
        height: 40,
        padding: '0 0 0 16px',
        cursor: 'default',
        lineHeight: '40px',
    },
    underlineSelectItem: {
        '&:after': {
            borderBottom: '2px solid ' + theme.palette.primary.main,
        },
    },
});

const selectionRangeMemo = createSelectionRangeMemo();
// height of header footer = 283
// height of one color element = 58
const heightColorPalette = () => Math.floor((window.innerHeight - (225 + 58)) / 58) * 58;

const ColorPaletteColorsWrapper = withStyles(styles, {
    name: 'ColorPaletteColorsWrapper',
})(({ palette, classes, isSearchActive, renderColors }) => (
    <div className={classes.colorPaletteWrapper}>{!isSearchActive && renderColors(palette)}</div>
));
class ColorPalettes extends React.Component {
    static propTypes = {
        boxed: PropTypes.bool,
        classes: PropTypes.object,
        size: PropTypes.object,
        colorPaletteIdentifier: PropTypes.string,
        width: PropTypes.string,
        colorPalettes: PropTypes.array,
        closeColorPalettes: PropTypes.func.isRequired,
        selectedColor: PropTypes.object,
        colorSelectClick: PropTypes.func,
        colorPaletteChange: PropTypes.func,
        usedColors: PropTypes.array,
        palette: PropTypes.object,
        isPortraitMode: PropTypes.bool,
    };

    constructor(props) {
        super(props);

        const { selectedColor } = this.props;
        let selectedColorData = selectedColor && selectedColor.identifier ? selectedColor.identifier : {};
        try {
            selectedColorData = JSON.parse(selectedColorData);
        } catch (e) {
            //No action required
        }
        const customColor = selectedColorData.custom ? selectedColorData.color : '';
        const isCustomColorChecked = !!selectedColorData.custom;
        this.state = {
            customColor,
            customColorError: null,
            isCustomColorChecked,
            isSearchActive: false,
            searchText: '',
            heightColorPaletteWrapper: heightColorPalette(),
        };
        selectionRangeMemo.save();
    }

    textInputRef = React.createRef();

    componentDidUpdate(prevProps, prevState) {
        const { selectedColor } = this.props;
        if (selectedColor.identifier.custom !== prevProps.selectedColor.identifier.custom) {
            this.setState({ isCustomColorChecked: selectedColor.identifier.custom });
            if (selectedColor.identifier.custom) {
                this.setState({ customColor: selectedColor.identifier.color });
            }
        }
        const { isCustomColorChecked } = this.state;
        // set focus to custom color field when toggling
        if (isCustomColorChecked && !prevState.isCustomColorChecked) {
            this.textInputRef.current.focus();
        }
        if (this.props.size !== prevProps.size) {
            this.setState({ heightColorPaletteWrapper: heightColorPalette() });
        }
    }

    colorSelectChange = (evt, color, paletteIdentifier, isCustomColorChecked) => {
        if (isCustomColorChecked) {
            return;
        }
        if (!isMobileDevice()) {
            // only for desktop to prevent losing the focus
            evt.preventDefault();
        }
        selectionRangeMemo.restore();
        if (isFunction(this.props.colorSelectClick)) {
            this.props.colorSelectClick(color.hex_value, color.identifier, paletteIdentifier, false);
        }
        selectionRangeMemo.save();
        if (isMobileDevice()) {
            // on mobile the soft keyboard is opened by the selection restore step
            // so it has to be closed again by removing the ranges
            window.getSelection().removeAllRanges();
        }
    };

    onColorPaletteChange = evt => {
        this.props.colorPaletteChange(evt.target.value);
    };

    onCustomColorChange = evt => {
        this.setState({
            customColor: evt.target.value,
            customColorError: null,
        });
    };

    onApplyColor = () => {
        const customColor = this.state.customColor;
        if (!customColor) {
            this.setState({ customColorError: t('colorPalettes.emptyColorCode') });
            return;
        }
        this.props.closeColorPalettes();
        selectionRangeMemo.restore();
        this.props.colorSelectClick(customColor, customColor, null, true);
    };

    toggleCustomColor = event => {
        this.setState({ isCustomColorChecked: event.target.checked });
    };

    changeText = event => {
        this.setState({ searchText: event.target.value });
    };

    activateSearch = () => {
        this.setState({ isSearchActive: true });
    };

    closeSearch = () => {
        this.setState({ isSearchActive: false });
        this.setState({ searchText: '' });
    };

    searchPaletteColors = palettes => {
        const colorsArray = palettes.map(({ identifier, colors }) =>
            colors.map(color => ({ ...color, paletteIdentifier: identifier }))
        );
        let searchColors = [].concat(...colorsArray);
        return {
            colors: uniqBy(searchColors, 'identifier'),
        };
    };

    renderColors = palette => {
        const { classes, selectedColor } = this.props;
        const { isCustomColorChecked } = this.state;
        const selectedColorData = { ...selectedColor };
        try {
            selectedColorData.identifier = JSON.parse(selectedColorData.identifier);
        } catch (e) {
            //No action required
        }
        const classesColorWrapSelected = classes.colorPaletteColors + ' ' + classes.selectedColorWrap;
        const classesDisabledColorWrap = classes.colorPaletteColors + ' ' + classes.disabledColorWrap;
        return (
            palette &&
            palette.colors &&
            palette.colors.map((color, colorIndex) => (
                <div
                    key={colorIndex}
                    className={classes.colorWrapper}
                    onMouseDown={evt =>
                        this.colorSelectChange(
                            evt,
                            color,
                            palette.identifier ? palette.identifier : color.paletteIdentifier,
                            isCustomColorChecked
                        )
                    }
                >
                    <div
                        className={
                            !isCustomColorChecked
                                ? selectedColorData &&
                                  selectedColorData.identifier &&
                                  selectedColorData.identifier.color === color.identifier
                                    ? classesColorWrapSelected
                                    : classes.colorPaletteColors
                                : classesDisabledColorWrap
                        }
                        style={{ background: '#' + color.hex_value }}
                        aria-label={color.title}
                        key={color.identifier}
                    />
                    <ListItemText
                        className={
                            !isCustomColorChecked
                                ? selectedColorData &&
                                  selectedColorData.identifier &&
                                  selectedColorData.identifier.color === color.identifier
                                    ? classes.selectedColorText
                                    : 'variant-list'
                                : classes.disabledColorText
                        }
                        classes={{ root: classes.RootListItem }}
                        primary={upperFirst(color.title)}
                    />
                </div>
            ))
        );
    };
    render() {
        const {
            boxed,
            classes,
            colorPalettes,
            closeColorPalettes,
            selectedColor,
            width,
            palette,
            usedColors,
            isPortraitMode,
        } = this.props;
        const {
            customColor,
            customColorError,
            isCustomColorChecked,
            isSearchActive,
            searchText,
            heightColorPaletteWrapper,
        } = this.state;
        const multiplePalettes = colorPalettes.length > 1;
        const arrowVisible = !multiplePalettes ? classes.arrowNone : '';
        const classesColorWrap = classes.colorPaletteColors;
        const classesDisabledColorWrap = classes.colorPaletteColors + ' ' + classes.disabledColorWrap;

        return (
            <Grid
                container
                className={
                    classes.container +
                    ' ' +
                    (isPortraitMode && width !== 'xs' ? classes.containerInPortraitMode : '')
                }
            >
                <Grid item xs={12} md={12}>
                    <Card className={boxed ? classes.card : classes.cardUnboxed}>
                        <CardContent className={classes.cardContentRoot}>
                            <Grid container>
                                <Grid item xs={12} md={12} lg={12}>
                                    <Typography
                                        variant="h5"
                                        className={classes.alignTypo + ' ' + classes.colorPaletteTitle}
                                    >
                                        <b>{t('colorPalettes.title')}</b>
                                        <Icon
                                            className={classes.DialogCloseIcon}
                                            onClick={closeColorPalettes}
                                        >
                                            close
                                        </Icon>
                                    </Typography>
                                </Grid>
                                <Grid item xs={12} md={12} lg={12}>
                                    {usedColors &&
                                        usedColors.map((color, colorIndex) => (
                                            <div
                                                key={colorIndex}
                                                className={classes.usedColorWrapper}
                                                onMouseDown={evt =>
                                                    this.colorSelectChange(
                                                        evt,
                                                        color,
                                                        color.palette ? color.palette : palette.identifier,
                                                        isCustomColorChecked
                                                    )
                                                }
                                            >
                                                <div
                                                    className={
                                                        isCustomColorChecked
                                                            ? classesDisabledColorWrap
                                                            : classesColorWrap
                                                    }
                                                    style={{ background: color.value || color.identifier }}
                                                    key={color.identifier}
                                                />
                                            </div>
                                        ))}
                                </Grid>
                                <Grid className={classes.gridColorContent} item xs={12} md={12} lg={12}>
                                    <Grid container>
                                        {!isSearchActive ? (
                                            <React.Fragment>
                                                <Grid item xs={10}>
                                                    <FormControl fullWidth className={classes.formControl}>
                                                        {colorPalettes.length > 1 ? (
                                                            <Select
                                                                value={palette && palette.identifier}
                                                                onChange={this.onColorPaletteChange}
                                                                input={
                                                                    <Input
                                                                        id="colorPaletteInput"
                                                                        readOnly={!multiplePalettes}
                                                                        classes={{
                                                                            underline:
                                                                                classes.underlineSelectItem,
                                                                        }}
                                                                    />
                                                                }
                                                                classes={{
                                                                    selectMenu: classes.selectColorMenu,
                                                                    icon: arrowVisible,
                                                                }}
                                                            >
                                                                {colorPalettes.map(
                                                                    (colorPalette, colorPaletteIndex) => (
                                                                        <MenuItem
                                                                            key={colorPaletteIndex}
                                                                            value={colorPalette.identifier}
                                                                            aria-label={colorPalette.title}
                                                                        >
                                                                            <ListItemText
                                                                                primary={colorPalette.title}
                                                                            />
                                                                        </MenuItem>
                                                                    )
                                                                )}
                                                            </Select>
                                                        ) : (
                                                            colorPalettes.map(
                                                                (colorPalette, colorPaletteIndex) => (
                                                                    <TextField
                                                                        key={colorPaletteIndex}
                                                                        readOnly
                                                                        inputProps={{ readOnly: true }}
                                                                        fullWidth={true}
                                                                        value={colorPalette.title}
                                                                        translate="no"
                                                                        InputProps={{
                                                                            classes: {
                                                                                input: classes.outlinedInput,
                                                                                underline:
                                                                                    classes.underlineInputText,
                                                                            },
                                                                        }}
                                                                    />
                                                                )
                                                            )
                                                        )}
                                                    </FormControl>
                                                </Grid>
                                                <Grid item xs={2}>
                                                    <SearchIcon
                                                        className={classes.searchColorIcon}
                                                        onClick={this.activateSearch}
                                                    />
                                                </Grid>
                                            </React.Fragment>
                                        ) : (
                                            <Grid item xs={12} className={classes.searchPaletteGrid}>
                                                <ColorPalettesSearch
                                                    heightColorPaletteWrapper={
                                                        isCustomColorChecked
                                                            ? heightColorPaletteWrapper - 150 // 135 height of custom fields
                                                            : heightColorPaletteWrapper - 50 // 35 height of search clear button
                                                    }
                                                    onSearch={this.onSearch}
                                                    closeSearch={this.closeSearch}
                                                    isSearchActive={isSearchActive}
                                                    searchText={searchText}
                                                    changeText={this.changeText}
                                                    searchPalette={this.searchPaletteColors(colorPalettes)}
                                                    renderColors={this.renderColors}
                                                    width={width}
                                                />
                                            </Grid>
                                        )}
                                    </Grid>
                                    <ColorPaletteColorsWrapper
                                        palette={palette}
                                        heightColorPaletteWrapper={heightColorPaletteWrapper}
                                        isCustomColorChecked={isCustomColorChecked}
                                        isSearchActive={isSearchActive}
                                        renderColors={this.renderColors}
                                        width={width}
                                    />
                                    <FormControlLabel
                                        classes={{ root: classes.formControlCustomColor }}
                                        control={
                                            <Switch
                                                classes={{ switchBase: classes.switchBaseSpacing }}
                                                checked={this.state.isCustomColorChecked}
                                                onChange={this.toggleCustomColor}
                                                value={t('colorPalettes.ownColorRequest')}
                                                color="primary"
                                            />
                                        }
                                        label={t('colorPalettes.ownColorRequest')}
                                    />
                                    {isCustomColorChecked && (
                                        <React.Fragment>
                                            <Typography variant="body2" className={classes.alignTypo}>
                                                {t('colorPalettes.description')}
                                            </Typography>
                                            <Grid item xs={12} md={12} lg={12}>
                                                <Grid
                                                    className={classes.customColorGrid}
                                                    item
                                                    xs={12}
                                                    md={12}
                                                    lg={12}
                                                >
                                                    <TextField
                                                        inputRef={this.textInputRef}
                                                        value={customColor}
                                                        onChange={this.onCustomColorChange}
                                                        variant="outlined"
                                                        label={t('colorPalettes.colorCode')}
                                                        placeholder={t('colorPalettes.colorSpecify')}
                                                        translate="no"
                                                        fullWidth
                                                        InputProps={{
                                                            classes: {
                                                                input: classes.selectedColorField,
                                                            },
                                                        }}
                                                        InputLabelProps={{
                                                            classes: {
                                                                formControl: classes.selectedColorLabel,
                                                            },
                                                        }}
                                                        error={!!customColorError}
                                                        helperText={customColorError}
                                                    />
                                                </Grid>
                                            </Grid>
                                        </React.Fragment>
                                    )}
                                </Grid>
                            </Grid>
                        </CardContent>
                        <CardActions className={classes.colorCardActions}>
                            <Grid className={classes.customColorGrid} item xs={12} md={12} lg={12}>
                                <AnalyticsWrapper
                                    targetId="text_color"
                                    data={!isCustomColorChecked ? selectedColor : customColor}
                                >
                                    <MainButton
                                        fullWidth
                                        onClick={
                                            !isCustomColorChecked ? closeColorPalettes : this.onApplyColor
                                        }
                                        className={classes.colorPaletteButton}
                                        size="medium"
                                        variant="contained"
                                    >
                                        {t('colorPalettes.apply')}
                                    </MainButton>
                                </AnalyticsWrapper>
                            </Grid>
                        </CardActions>
                    </Card>
                </Grid>
            </Grid>
        );
    }
}

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