/**
 * React EChart组件
 * User: bjyangxiuwu
 * Date: 2018/09/20
 * Time: 15:18
 */
import React from 'react';
import PropTypes from 'prop-types';
import echarts from 'echarts';
import elementResizeEvent from 'element-resize-event';

class ReactECharts extends React.Component {
    constructor(props) {
        super(props);
        // chart对象
        this.echartsInstance = echarts;
        // chart dom节点
        this.eChartsElement = null;
    }

    componentDidMount() {
        const eChartObj = this.renderEChartDom();
        const { onEvents } = this.props || {};
        this.bindEvents(eChartObj, onEvents);

        // 注册chart随窗口大小改变事件
        elementResizeEvent(this.eChartsElement, () => {
            eChartObj.resize();
        })
    }

    shouldComponentUpdate(nextPropsParam, nextStateParam) {
        const thisProps = this.props || {};
        const thisState = this.state || {};

        const nextState = nextStateParam || {};
        const nextProps = nextPropsParam || {};

        if (Object.keys(thisProps).length !== Object.keys(nextProps).length ||
            Object.keys(thisState).length !== Object.keys(nextState).length) {
            return true;
        }

        if (JSON.stringify(thisProps) !== JSON.stringify(nextProps)) {
            return true;
        }

        if (JSON.stringify(thisState) !== JSON.stringify(nextState)) {
            return true;
        }

        return false;
    }

    componentDidUpdate() {
        this.renderEChartDom();
    }

    componentWillUnmount() {
        if (this.eChartsElement) {
            // 注销elementResizeEvent
            if (typeof elementResizeEvent.unbind === 'function') {
                elementResizeEvent.unbind(this.eChartsElement)
            }
            this.echartsInstance.dispose(this.eChartsElement)
        }
    }

    getEChartsInstance = () => {
        const { theme } = this.props;
        return this.echartsInstance.getInstanceByDom(this.eChartsElement) ||
                this.echartsInstance.init(this.eChartsElement, theme);
    }

    renderEChartDom = () => {
        // 初始化图表实例
        const eChartObj = this.getEChartsInstance();

        // 完善eCharts.setOption()方法能力，增加`notMerge`, `lazyUpdate`参数
        // notMerge 可选，是否不跟之前设置的option进行合并，默认为false，即合并
        // lazyUpdate 可选，在设置完option后是否不立即更新图表，默认为false，即立即更新
        const { option, notMerge, lazyUpdate, showLoading, loadingOption } = this.props;
        eChartObj.setOption(option, notMerge || false, lazyUpdate || false);

        // 实现加载动画效果，当数据量大或者异步的时候，显示Loading
        if (showLoading) {
            eChartObj.showLoading(loadingOption || null);
        } else {
            eChartObj.hideLoading();
        }

        return eChartObj;
    };

    bindEvents = (instance, events) => {
        const loopEvent = (eventName) => {
            if (typeof eventName === 'string' && typeof events[eventName] === 'function') {
                instance.off(eventName);
                instance.on(eventName, (param) => {
                    // 触发回调
                    events[eventName](param);
                });
            }
        };

        const eventKeys = Object.keys(events || []) || [];
        for (let i = 0; i < eventKeys.length; i+=1) {
            const eventName = eventKeys[i];
            if (Object.prototype.hasOwnProperty.call(events, eventName)) {
                loopEvent(eventName);
            }
        }
    };

    render() {
        const { style, className } = this.props || {style: {
                height: '300px'
            }};

        return (
            <div
                ref={(e) => { this.eChartsElement = e }}
                style={style}
                className={className}
                />
        )
    }
}

ReactECharts.propTypes = {
    option: PropTypes.objectOf.isRequired,
    notMerge: PropTypes.bool,
    lazyUpdate: PropTypes.bool,
    theme: PropTypes.string,
    showLoading: PropTypes.bool,
    loadingOption: PropTypes.objectOf
};

ReactECharts.defaultProps = {
    notMerge: false,
    lazyUpdate: false,
    theme: null,
    showLoading: false,
    loadingOption: null
};
export default ReactECharts;
