'use strict';
/**
 * an class to generate options for ECharts
 * @module option-generator
 * @see module:index
 */
const _ = require('lodash');
const numeral = require('numeral');
const util = require('../util/index');
const constant = require('../constant');

// const MIN_DATA_ZOOM_LIMIT = 20;

const DEFAULT_OPTION = {
  animation: false,
  theme: constant.DEFAULT_THEME_NAME,
  tooltip: {},
  toolbox: {
    feature: {},
  },
};

class OptionGenerator {
  constructor(extraOption) {
    const me = this;
    extraOption = extraOption || {};
    me._option = {};
    _.merge(me._option, DEFAULT_OPTION);
    _.merge(me._option, util.parseExtraOption(extraOption));
    this._configLayout();
  }

  configCoordinates(coordinates, horizontal, extraOption) {
    const me = this;
    const option = me._option;
    extraOption = extraOption || {};
    let dimensionAxis = 'xAxis';
    let measuresAxis = 'yAxis';
    if (horizontal) {
      const temp = measuresAxis;
      measuresAxis = dimensionAxis;
      dimensionAxis = temp;
    }
    option[dimensionAxis] = _.extend(option[dimensionAxis], {
      type: 'category',
      data: coordinates,
    }, extraOption.category);

    if (extraOption.yAxis) {
      option[measuresAxis] = extraOption.yAxis;
    } else {
      option[measuresAxis] = [{
        type: 'value'
      }];
    }
    option[measuresAxis].forEach(item => {
      _.merge(item, {
        splitLine: {
          show: false,
        },
        axisLine: {
          show: false
        }
      });
    });
    _.merge(option.xAxis, this._configXLabel());
    _.merge(option[measuresAxis][0], {
      name: option['data-yAxisName'] || ''
    });
    if (_.isNumber(option['data-yAxisMax'])) {
      option[measuresAxis][0].max = option['data-yAxisMax'];
    }
    if (_.isNumber(option['data-yAxisMin'])) {
      option[measuresAxis][0].min = option['data-yAxisMin'];
    }
    if (_.isNumber(option['data-yAxisMaxRight']) && option[measuresAxis][1]) {
      option[measuresAxis][1].max = option['data-yAxisMaxRight'];
    }
    if (_.isNumber(option['data-yAxisMinRight']) && option[measuresAxis][1]) {
      option[measuresAxis][1].min = option['data-yAxisMinRight'];
    }

    if (option['data-showDataZoomInside']) {
      option.dataZoom = [{
        show: true,
        type: 'slider',
        start: _.isPlainObject(option['data-dataZoomInside']) ? option['data-dataZoomInside'].start : 0,
        end: _.isPlainObject(option['data-dataZoomInside']) ? option['data-dataZoomInside'].end : 100
      }];
    } else {
      option.xAxis.axisTick = { alignWithLabel: true };
    }
    return me;
  }

  configMeasures(type, measures, dataSet, extraSeriesOption) {
    const me = this;
    const option = me._option;
    option.series = [];
    _.each(measures, (measure) => {
      const colInfo = dataSet.colByName[measure];
      const measureSchema = _.find(dataSet.schema, { name: measure });
      let data = dataSet.colValuesByName[measure];
      if (!_.isEmpty(measureSchema.format)) {
        data = data.map((v) => Number.parseFloat(v.match(/[0-9.]/g).join('')));
        const formatter = util.reverseFormatter(measureSchema.format);
        if (formatter !== '{value}') {
          const rightValues = this._option['data-valuesRight'] || [];
          if (rightValues.some(v => v === measure)) {
            option.yAxis[1].axisLabel = _.merge(option.yAxis[1].axisLabel, {
              formatter,
            });
          }
          if (this._option['data-values'].some(v => v === measure)) {
            option.yAxis[0].axisLabel = _.merge(option.yAxis[0].axisLabel, {
              formatter,
            });
          }
        }
      }
      option.series.push(_.extend({
        name: colInfo.comments,
        type,
        data,
        label: {
          normal: {
            show: option['data-showNormalLabel'] || false
          }
        },
        areaStyle: {
          normal: {
            opacity: option['data-showAreaStyle'] ? 1 : 0
          }
        },
        yAxisIndex: (extraSeriesOption.measuresRight && (extraSeriesOption.measuresRight.indexOf(measure) > -1)) ? 1 : 0,
        smooth: option['data-smooth'] || false
      }, extraSeriesOption));
      if (data.length === 1) {
          // 只有一条数据时，显示一个点
          option.series.forEach(item => {
            item.symbol = 'circle';
          })
      }
    });
    return me;
  }

  configLegend(colNames, dataSet) {
    const me = this;
    me._option.legend = {
      data: _.map(colNames, colName => dataSet.colByName[colName].comments)
    };
    return me;
  }

  configLegendByData(data) {
    const me = this;
    me._option.legend = {
      data,
    };
    return me;
  }

  toOption() {
    return this._option;
  }

  _configLayout() {
    switch (this._option.padding) {
      case 'large':
        this._option.grid = {
          left: 100,
          right: 100,
          bottom: 30,
        };
        break;
      case 'small':
        this._option.grid = {
          left: 50,
          right: 50,
          bottom: 30,
          containLabel: true,
        };
        break;
      case 'none':
        this._option.grid = {
          left: 0,
          // 露出最后一个刻度
          right: 5,
          bottom: 30,
          containLabel: true,
        };
        break;
      default:
        break;
    }
  }

  _configXLabel() {
    const lineWidth = 75;
    return {
      axisLabel: {
        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;
        },
      },
    };
  }
}

module.exports = OptionGenerator;
