import React from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux';
import bindAll from 'lodash.bindall';
import queryString from 'query-string';
import paper from '@scratch/paper';
import log from '../log/log';
import RtmClient from '../lib/rtm-client';

import {changeMode} from '../reducers/modes';
import {changeStrokeWidth} from '../reducers/stroke-width';
import {openStrokeColor, closeStrokeColor, openFillColor, closeFillColor} from '../reducers/modals';
import {changeGradientType} from '../reducers/fill-mode-gradient-type';
import {changeColorIndex} from '../reducers/color-index';
import {changeFillColor} from '../reducers/fill-color';
import {changeFillColor2} from '../reducers/fill-color-2';
import {changeColorHue,
    changeColorSaturation,
    changeColorBrightness} from '../reducers/color-picker';
import {changeStrokeColor} from '../reducers/stroke-color';
import {selectModeTool, setPaintName} from '../reducers/mode-tools';
import {updateViewBounds} from '../reducers/view-bounds';
import {changeFormat} from '../reducers/format';
import {changeBitBrushSize} from '../reducers/bit-brush-size';

import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items';
import {clearGradient} from '../reducers/selection-gradient-type';
// import {getSelectedLeafItems} from '../helper/selection';
import {activateEyeDropper, deactivateEyeDropper} from '../reducers/eye-dropper';
import {setZoomType} from '../reducers/paint-editor';


const params = queryString.parse(window.location.search);
const {uid, writable} = params;
const channelName = '20200520';

// http://localhost:8078/playground/?uid=18616378968&writable=true
// http://localhost:8078/playground/?uid=17311111111
class PaintSyncComponent extends React.Component {
    constructor (props) {
        super(props);
        bindAll(this, [
            'loginRTM',
            'joinRoom',
            'sendMessage',
            'parseMessage'

        ]);
    }

    componentDidMount () {
        RtmClient.on('ChannelMessage', ({channel, args}) => {
            log.info('ChannelMessage : ', channel);
            const [message, memberId] = args;
            if (memberId !== uid) {
                log.info('channel ', channelName, ', messsage: ', message.text, ', memberId: ', memberId);
                if (message.text && message.text.length > 0 && message.text !== '{}') {
                    // store.state = _.merge(store.state, JSON.parse(message.text))
                    // store.dispatch(updateState(message.text));
                    this.parseMessage(message.text);
                }
            }
        });

        this.loginRTM();
    }
    componentWillReceiveProps (nextProps) {
        if (!writable) return;
        if (nextProps.mode !== this.props.mode) {
            this.sendMessage({type: 'mode', value: nextProps.mode});
        } else if (nextProps.strokeWidth !== this.props.strokeWidth) {
            this.sendMessage({type: 'stroke-width', value: nextProps.strokeWidth});
        } else if (nextProps.strokeColorModalVisible !== this.props.strokeColorModalVisible) {
            this.sendMessage({type: 'stroke-color-modal', value: nextProps.strokeColorModalVisible});
        } else if (nextProps.fillColorModalVisible !== this.props.fillColorModalVisible) {
            this.sendMessage({type: 'fill-color-modal', value: nextProps.fillColorModalVisible});
        } else if (nextProps.gradientType !== this.props.gradientType) {
            this.sendMessage({type: 'gradient-type', value: nextProps.gradientType});
        } else if (nextProps.fillModeGradientType !== this.props.fillModeGradientType) {
            this.sendMessage({type: 'fill-mode-gradient-type', value: nextProps.fillModeGradientType});
        } else if (nextProps.bitBrushSize !== this.props.bitBrushSize) {
            this.sendMessage({type: 'bit-brush-size', value: nextProps.bitBrushSize});
        }

        if (nextProps.colorIndex !== this.props.colorIndex) {
            this.sendMessage({type: 'color-index', value: nextProps.colorIndex});
        }
        if (nextProps.fillColor2 !== this.props.fillColor2) {
            this.sendMessage({type: 'fill-color-2', value: nextProps.fillColor2});
        }
        if (nextProps.fillColor !== this.props.fillColor) {
            this.sendMessage({type: 'fill-color', value: nextProps.fillColor});
        }
        if (nextProps.hue !== this.props.hue) {
            this.sendMessage({type: 'color-picker-hue', value: nextProps.hue});
        }
        if (nextProps.saturation !== this.props.saturation) {
            this.sendMessage({type: 'color-picker-saturation', value: nextProps.saturation});
        }
        if (nextProps.brightness !== this.props.brightness) {
            this.sendMessage({type: 'color-picker-brightness', value: nextProps.brightness});
        }

        if (nextProps.strokeColor !== this.props.strokeColor) {
            this.sendMessage({type: 'stroke-color', value: nextProps.strokeColor});
        }
        if (nextProps.selectedItems !== this.props.selectedItems) {
            this.sendMessage({type: 'selected-items', value: nextProps.selectedItems});
        }
        if (nextProps.isEyeDropping !== this.props.isEyeDropping) {
            this.sendMessage({type: 'is-eye-dropping', value: nextProps.isEyeDropping});
        }
    }
    parseMessage (message) {
        if (writable) return;
        // {"type":"mode","value":"BRUSH"}
        // keyboard-event
        const data = JSON.parse(message);
        if (data.type === 'mouse-event') {
            const evt = new MouseEvent(data.value.type, data.value);
            const canvas = document.getElementById('view-0');
            if (canvas) canvas.dispatchEvent(evt);
        } else if (data.type === 'keyboard-event') {
            const typeArg = data.value.type === 'keypress' ? 'keydown' : data.value.type;
            const evt = new KeyboardEvent(typeArg, Object.assign(data.value, {view: window}));
            log.info('keyboard-event', evt);
            const textareas = document.getElementsByTagName('textarea');
            if (textareas && textareas[0]) {
                document.dispatchEvent(evt);
            }
        } else if (data.type === 'input-event') {
            if (!data.value.inputType || data.value.inputType === 'insertCompositionText') return;
            if (!data.value.data === null && data.value.inputType.length <= 0) return;
            const evt = new InputEvent(data.value.type, data.value);
            log.info('input-event', data.value);
            const textareas = document.getElementsByTagName('textarea');
            if (textareas && textareas[0]) {
                log.info('textareas[0]', textareas[0].className);
                // const value = !data.value.data && data.value.inputType === 'insertLineBreak' ? '\r\n' : data.value.data;
                // textareas[0].value = textareas[0].value + value;
                textareas[0].value = data.value.text;
                textareas[0].dispatchEvent(evt);
            }
        } else if (data.type === 'menu-event'){
            this.props.selectModeTool(data.value.menu);
        } else if (data.type === 'update-name-event'){
            this.props.setPaintName(data.value.name);
        } else if (data.type === 'zoom-event'){
            this.props.setZoomType(data.value.zoom);
        } else if (data.type === 'scroll-event'){
            if (data.value.matrix) {
                const matrix = new paper.Matrix(data.value.matrix[1],
                    data.value.matrix[2],
                    data.value.matrix[3],
                    data.value.matrix[4],
                    data.value.matrix[5],
                    data.value.matrix[6]);
                this.props.updateViewBounds(matrix);
            }

        } else if (data.type === 'format-switch-event'){
            this.props.changeFormat(data.value.format);
        } else if (data.type === 'mode') {
            this.props.changeMode(data.value);
        } else if (data.type === 'stroke-width') {
            this.props.changeStrokeWidth(data.value);
        } else if (data.type === 'stroke-color-modal') {
            data.value ? this.props.openStrokeColor() : this.props.closeStrokeColor();
        } else if (data.type === 'fill-color-modal') {
            data.value ? this.props.openFillColor() : this.props.closeFillColor();
        } else if (data.type === 'gradient-type') {
            this.props.changeGradientType(data.value);
        } else if (data.type === 'fill-mode-gradient-type') {
            this.props.changeGradientType(data.value);
        } else if (data.type === 'fill-color') {
            this.props.changeFillColor(data.value, 0);
        } else if (data.type === 'fill-color-2') {
            this.props.changeFillColor(data.value, 1);
        } else if (data.type === 'color-index') {
            this.props.changeColorIndex(data.value);
        } else if (data.type === 'color-picker-hue') {
            this.props.changeColorHue(data.value);
        } else if (data.type === 'color-picker-saturation') {
            this.props.changeColorSaturation(data.value);
        } else if (data.type === 'color-picker-brightness') {
            this.props.changeColorBrightness(data.value);
        } else if (data.type === 'stroke-color') {
            this.props.changeStrokeColor(data.value);
        } else if (data.type === 'selected-items') {
            if (this.props.mode === 'SELECT') {
                // this.props.setSelectedItems(data.value);
            }
        } else if (data.type === 'is-eye-dropping') {
            data.value ? this.props.activateEyeDropper() : this.props.deactivateEyeDropper();
        } else if (data.type === 'bit-brush-size') {
            this.props.changeBitBrushSize(data.value);
        }


    }
    loginRTM () {
        try {
            RtmClient.init('2071eeb90454440b9abfb992135a3403');
            RtmClient.login(uid, null).then(() => {
                console.log('login');
                RtmClient._logined = true;
                this.joinRoom();
            })
                .catch(err => {
                    console.error(err);
                });
        } catch (err) {
            console.error(err);
        }
    }
    joinRoom () {

        RtmClient.joinChannel(channelName).then(() => {
            RtmClient.channels[channelName].joined = true;
        })
            .catch(err => {
                console.error(err);
            });
    }
    sendMessage (data) {
        if (!writable) return;
        const message = JSON.stringify(data);
        if (RtmClient.channels[channelName] && !RtmClient.channels[channelName].joined) return;
        RtmClient.sendChannelMessage(message, channelName).then(() => {
            console.log('sendChannelMessage : ', message);
        })
            .catch(err => {
                console.error(err);
            });
    }

    // handleMouseDown (event) {
    //     if (event.event.button > 0) return; // only first mouse button
    //     console.log('handleMouseDown : ', event.event);
    //
    // }
    // handleMouseDrag (event) {
    //     if (event.event.button > 0 || !this.active) return; // only first mouse button
    //     console.log('handleMouseDrag : ', event.event);
    //
    // }
    // handleMouseUp (event) {
    //     if (event.event.button > 0 || !this.active) return; // only first mouse button
    //     console.log('handleMouseUp : ', event.event);
    //
    // }
    // handleMouseMove (event) {
    //     console.log('handleMouseMove : ', event.event);
    // }
    render () {
        return (
            <div />
        );
    }
}

PaintSyncComponent.propTypes = {
    changeFormat: PropTypes.func,
    // mode: PropTypes.oneOf(Object.keys(Modes)).isRequired
    mode: PropTypes.string

};

const mapStateToProps = state => ({
    bitBrushSize: state.scratchPaint.bitBrushSize,
    color: state.scratchPaint.color.fillColor,
    mode: state.scratchPaint.mode,
    strokeWidth: state.scratchPaint.color.strokeWidth,
    strokeColorModalVisible: state.scratchPaint.modals.strokeColor,
    fillColorModalVisible: state.scratchPaint.modals.fillColor,
    gradientType: state.scratchPaint.color.gradientType,
    fillModeGradientType: state.scratchPaint.fillMode.gradientType,
    colorIndex: state.scratchPaint.fillMode.colorIndex,
    fillColor: state.scratchPaint.color.fillColor,
    fillColor2: state.scratchPaint.color.fillColor2,
    hue: state.scratchPaint.colorPickerHSB.hue,
    saturation: state.scratchPaint.colorPickerHSB.saturation,
    brightness: state.scratchPaint.colorPickerHSB.brightness,
    strokeColor: state.scratchPaint.color.strokeColor,
    selectedItems: state.scratchPaint.selectedItems,
    viewBounds: state.scratchPaint.viewBounds,
    isEyeDropping: state.scratchPaint.color.eyeDropper.active
});


const mapDispatchToProps = dispatch => ({
    clearSelectedItems: () => {
        dispatch(clearSelectedItems());
    },
    clearGradient: () => {
        dispatch(clearGradient());
    },
    changeMode: mode => {
        dispatch(changeMode(mode));
    },
    changeStrokeWidth: width => {
        dispatch(changeStrokeWidth(width));
    },
    openStrokeColor: () => {
        dispatch(openStrokeColor());
    },
    closeStrokeColor: () => {
        dispatch(closeStrokeColor());
    },
    openFillColor: () => {
        dispatch(openFillColor());
    },
    closeFillColor: () => {
        dispatch(closeFillColor());
    },
    changeGradientType: type => {
        dispatch(changeGradientType(type));
    },
    changeColorIndex: index => {
        dispatch(changeColorIndex(index));
    },
    changeFillColor: (fillColor, index) => {
        if (index === 0) {
            dispatch(changeFillColor(fillColor));
        } else if (index === 1) {
            dispatch(changeFillColor2(fillColor));
        }
    },
    changeColorHue: hue => {
        dispatch(changeColorHue(hue));
    },
    changeColorSaturation: saturation => {
        dispatch(changeColorSaturation(saturation));
    },
    changeColorBrightness: brightness => {
        dispatch(changeColorBrightness(brightness));
    },
    changeStrokeColor: color => {
        dispatch(changeStrokeColor(color));
    },
    setSelectedItems: items => {
        dispatch(setSelectedItems(items, false /* bitmapMode */));
    },
    selectModeTool: menu => {
        dispatch(selectModeTool(menu));
    },
    setPaintName: name => {
        dispatch(setPaintName(name));
    },
    activateEyeDropper: () => {
        dispatch(activateEyeDropper());
    },
    deactivateEyeDropper: () => {
        dispatch(deactivateEyeDropper());
    },
    setZoomType: type => {
        dispatch(setZoomType(type));
    },
    updateViewBounds: matrix => {
        dispatch(updateViewBounds(matrix));
    },
    changeFormat: format => {
        dispatch(changeFormat(format));
    },
    changeBitBrushSize: size => {
        dispatch(changeBitBrushSize(size));
    }
});

export default connect(mapStateToProps, mapDispatchToProps)(PaintSyncComponent);
