'use strict';
/**
 * d2recharts module
 * @module d2recharts
 * @see module:index
 * @see https://github.com/hustcc/echarts-for-react/blob/master/src/echarts-for-react.js
 */
const React = require('react');
const echarts = require('echarts');
const elementResizeEvent = require('element-resize-event');
const _ = require('lodash');
const update = require('immutability-helper');
const propTypes = require('./prop-types');
const util = require('../util/index');

class Recharts extends React.Component {
  componentDidMount() {
    setTimeout(() => {
      // first add
      const me = this;
      const echartObj = me.renderEchartDom();
      const props = me.props;
      const onEvents = props.onEvents || [];

      _.forIn(onEvents, (eventFunc, eventName) => {
        // ignore the event config which not satisfy
        if (_.isString(eventName) && _.isFunction(eventFunc)) {
          // binding event
          echartObj.on(eventName, (param) => {
            eventFunc(param, me, echartObj);
          });
        }
      });
      this.silent = true;
      echartObj.on('updated', () => {
        if (this.silent) return;
        // 坐标轴最后一段文字
        // const f = _.findLast(echartObj._zr.storage.getDisplayList(true), v => v.type === 'text')
        // console.debug('event', f)
        // f.position[0] = 170;
        // this.silent = true;
      })

      // on chart ready
      if (_.isFunction(props.onChartReady)) {
        props.onChartReady(me, echartObj);
      }

      // on resize
      elementResizeEvent(me.wrapper, () => {
        echartObj.resize();
      });

      // on css width/height change
      if (MutationObserver) {
        // 监听样式容器高度变化，重置图表大小
        if (this.observer && this.observer.disconnect) {
          this.observer.disconnect();
        }
        this.observer = new MutationObserver((mutations) => {
          mutations.forEach(item => {
            if (item.type === 'attributes' && item.attributeName === 'style') {
              echartObj.resize();
            }
          });
        });
        this.observer.observe(me.wrapper, {
          attributes: true,
          attributeFilter : ['style']
        });
      }

      if (window.navigator.userAgent.indexOf('Mobile') > -1) {
        // 解决移动端滚动时，tootips 不消失的问题
        document.body.onscroll = _.debounce(() => {
          echartObj.dispatchAction({
            type: 'hideTip'
          })
        }, 200);
      }
    }, 0);
  }

  componentDidUpdate(prevProps) {
    // update
    const omitKeys = ['height', 'width'];
    if (
      JSON.stringify(_.omit(prevProps.option, omitKeys))
      !==
      JSON.stringify(_.omit(this.props.option, omitKeys))
    ) {
      this.renderEchartDom();
    }
  }

  componentWillUnmount() {
    // remove
    echarts.dispose(this.wrapper);
    if (this.observer && this.observer.disconnect) {
      this.observer.disconnect();
    }
  }

  extendXaxis(u = {}) {
    // 需要感知宽度以后的设置
    const echartObj = this.getEchartsInstance();
    const { option } = this.props;
    const opt = {};
    let lineWidth = 78;

    if (!_.isPlainObject(_.get(option, 'xAxis'))){
      // 如果没有xAxis，则不做处理
      // update不能为undefined设置值
      return;
    }

    const dimension = _.get(option, '["data-columns"].0');
    const dimensionMeta = _.get(option, `["data-sourceResMeta"].meta.${dimension}`);
    const isString = _.get(dimensionMeta, 'type') === 'string';

    if (isString) {
      // 文本类型全部展示
      opt.interval = 0;
      const xData = _.get(option, 'xAxis.data') || [];
      let isOverflowed = false;
      if (xData.length) {
        // 横着放存在覆盖情况，0.8是推测值
        const maxWidth = 0.8 * echartObj.getWidth() / xData.length;
        isOverflowed = xData.some(v => util.guessTextWidth(v.slice(0, 7)) > maxWidth);
      }
      if (isOverflowed) {
        // 斜过来以后最多展示4个字
        lineWidth = 12 * 4;
        opt.rotate = 45;
        // 补丁： 当有缩略轴的时候，需要grid向上移
        if(option['data-showDataZoomInside']){
          option.grid.bottom = 65;
        }
      }
    }

    _.set(u, 'option.xAxis.axisLabel', {
      $merge: {
        ...opt,
        formatter: v => {
          const defaultWidth = util.guessTextWidth(v);
          if (defaultWidth > lineWidth) {
            const guessLen = Math.floor(lineWidth / 12);
            let start = guessLen;
            let first = v.toString().substr(0, start);
            while (util.guessTextWidth(`${first}...`) <= lineWidth) {
              first += v[start];
              start++;
            }
            return `${first}...`;
            // while (util.guessTextWidth(first) <= lineWidth) {
            //   first += v[start];
            //   start++;
            // }
            // let second = v.slice(start);
            // if (defaultWidth > lineWidth * 2) {
            //   second = v.substr(start, guessLen);
            //   while (util.guessTextWidth(`${second}...`) <= lineWidth) {
            //     second += v[start];
            //     start++;
            //   }
            //   second += '...';
            // }
            // return `${first}\n${second}`;
          }
          return v;
        },
      },
    });
  }

  extendDataZoom(u = {}) {
    const echartObj = this.getEchartsInstance();
    const { option } = this.props;

    if (!_.isArray(option.dataZoom)) {
      return;
    }
    const h = echartObj.getHeight();
    _.set(u, 'option.dataZoom', {
      $set: _.map(option.dataZoom, opt => {
        let newOpt = _.assign({}, opt);
        if (opt.type !== 'inside') {
          newOpt.top = h - 20;
          newOpt.bottom = 0;
          // 将dataZoom的位置控制移动至option-generator中
        }
        return newOpt;
      }),
    });
    if (this.props.option.xAxis && this.props.option.xAxis.data && !this.props.option.dataZoom) {
      // different chart has different config, Scatter, Radar, Funnel, Pie, Bar
      //
      // props = update(props, {
      //   option: {
      //     xAxis: {
      //       axisLabel: {
      //         $merge: {
      //           interval: Math.round(props.option.xAxis.data.length / Math.floor(echartObj.getWidth() / 100)),
      //         }
      //       }
      //     }
      //   }
      // });
    }
  }

  getEchartsInstance() {
    // return the echart object
    const me = this;
    const props = me.props;
    const option = props.option;
    const theme = props.theme || option.theme;
    return echarts.getInstanceByDom(me.wrapper) || echarts.init(me.wrapper, theme);
  }

  renderEchartDom() {
    // render the dom
    // init the echart object
    const echartObj = this.getEchartsInstance();

    /*
    try {
      // TODO 容错
      echartObj.resize();
    } catch (e) {
      console.log('echartObj.resize fail');
    }
    */
    const u = {};
    this.extendXaxis(u);
    this.extendDataZoom(u);

    const props = update(this.props, u);
    // set the echart option
    const option = util.pickExcept(props.option, ['width', 'height']);
    this.silent = false;
    echartObj.setOption(option, props.notMerge, props.lazyUpdate);
    // set loading mask
    if (props.showLoading) {
      echartObj.showLoading();
    } else {
      echartObj.hideLoading();
    }
    // on chart ready
    if (props.option && _.isFunction(props.option.onChartRendered)) {
      props.option.onChartRendered(this, echartObj);
    }

    return echartObj;
  }

  render() {
    const me = this;
    const props = me.props;
    const style = _.assign({
      width: props.option.width || props.width,
      height: props.option.height || props.height,
    }, props.style);
    // for render
    return (
      <div ref={(wrapper) => me.wrapper = wrapper} className={props.className} style={style}/>
    );
  }
}

Recharts.propTypes = propTypes.recharts;
Recharts.defaultProps = {
  lazyUpdate: true,
  notMerge: true,
  width: '100%',
  height: '300px',
};

module.exports = Recharts;
