/**
 * @fileOverview facets of chart
 * @author dxq613@gmail.com
 */
var Global = require('../global');

var Util = require('../util');

var assign = Util.assign;
var isNil = Util.isNil;
var isArray = Util.isArray;
var cloneDeep = Util.cloneDeep; // 绑定事件

var wrapBehavior = Util.wrapBehavior; // 获取绑定的事件

var getWrapBehavior = Util.getWrapBehavior;

var Base = /*#__PURE__*/function () {
  var _proto = Base.prototype;

  _proto.getDefaultCfg = function getDefaultCfg() {
    return {
      chart: null,
      group: null,

      /**
       * 是否默认显示每个分面的title
       * @type {Boolean}
       */
      showTitle: true,

      /**
       * 是否自动修改坐标轴的信息
       * @type {Boolean}
       */
      autoSetAxis: true,

      /**
       * View 的内边框
       * @type {Number|Array}
       */
      padding: 10,

      /**
       * 遍历每个view 的回调函数
       * @type {Function}
       */
      eachView: null,

      /**
       * 分面的字段名列表
       * @type {Array}
       */
      fields: [],

      /**
       * 列值的的标题
       * @type {Object}
       */
      colTitle: {
        offsetY: -15,
        style: {
          fontSize: 14,
          textAlign: 'center',
          fill: '#666',
          fontFamily: Global.fontFamily
        }
      },
      rowTitle: {
        offsetX: 15,
        style: {
          fontSize: 14,
          textAlign: 'center',
          rotate: 90,
          fill: '#666',
          fontFamily: Global.fontFamily
        }
      }
    };
  };

  function Base(cfg) {
    var defaultCfg = this.getDefaultCfg();
    assign(this, defaultCfg, cfg);
    this.init();
  }

  _proto.init = function init() {
    if (!this.chart) {
      throw new Error('Facets Error: please specify the chart!');
    }

    this._bindEvent();

    this.initContainer();

    if (this.chart.get('data')) {
      this.initViews();
    }
  };

  _proto.initContainer = function initContainer() {
    var chart = this.chart;
    var frontPlot = chart.get('frontPlot');
    var group = frontPlot.addGroup();
    this.group = group;
  };

  _proto.initViews = function initViews() {
    var chart = this.chart;
    var data = chart.get('data');
    var eachView = this.eachView;
    var facets = this.generateFacets(data);

    for (var i = 0; i < facets.length; i++) {
      var facet = facets[i];
      var region = facet.region;
      var view = chart.view({
        start: region.start,
        end: region.end,
        padding: this.padding
      });
      view.source(facet.data);
      this.beforeProcessView(view, facet);

      if (eachView) {
        eachView(view, facet);
      }

      this.afterProcessView(view, facet);
      facet.view = view;
    }

    this.facets = facets;
  }
  /**
   * 处理 view 前
   * @protected
   */
  ;

  _proto.beforeProcessView = function beforeProcessView() {}
  /**
   * 处理view
   * @param {Object} view 视图
   * @param {Object} facet 分面信息
   * @protected
   */
  ;

  _proto.afterProcessView = function afterProcessView(view, facet) {
    if (this.autoSetAxis) {
      this.processAxis(view, facet);
    }
  };

  _proto.processAxis = function processAxis(view, facet) {
    var viewOptions = view.get('options');
    var geoms = view.get('geoms');

    if ((!viewOptions.coord.type || viewOptions.coord.type === 'rect') && geoms.length) {
      var field = geoms[0].get('attrOptions').position.field;
      var fields = isArray(field) ? field : field.split('*').map(function (str) {
        return str.trim();
      });
      var xField = fields[0];
      var yField = fields[1];

      if (isNil(viewOptions.axes)) {
        viewOptions.axes = {};
      }

      var axes = viewOptions.axes;

      if (axes !== false) {
        if (xField && axes[xField] !== false) {
          axes[xField] = axes[xField] || {};
          this.setXAxis(xField, axes, facet);
        }

        if (yField && axes[yField] !== false) {
          axes[yField] = axes[yField] || {};
          this.setYAxis(yField, axes, facet);
        }
      }
    }
  };

  _proto.setXAxis = function setXAxis() {};

  _proto.setYAxis = function setYAxis() {} // 默认显示各列的标题
  ;

  _proto.renderTitle = function renderTitle(view, facet) {
    this.drawColTitle(view, facet);
  };

  _proto.getScaleText = function getScaleText(field, value, view) {
    var rst;

    if (field) {
      var scales = view.get('scales');
      var scale = scales[field];

      if (!scale) {
        scale = view.createScale(field);
      }

      rst = scale.getText(value);
    } else {
      rst = value;
    }

    return rst;
  };

  _proto.drawColTitle = function drawColTitle(view, facet) {
    var text = this.getScaleText(facet.colField, facet.colValue, view);
    var colTextCfg = assign({
      position: ['50%', '0%'],
      content: text
    }, this.colTitle);
    view.guide().text(colTextCfg);
  };

  _proto.drawRowTitle = function drawRowTitle(view, facet) {
    var text = this.getScaleText(facet.rowField, facet.rowValue, view);
    var rowTextCfg = assign({
      position: ['100%', '50%'],
      content: text
    }, cloneDeep(this.rowTitle));
    view.guide().text(rowTextCfg);
  }
  /**
   * 数据过滤器
   * @protected
   * @param {Array} conditions 过滤条件
   * @return {Function} 过滤函数
   */
  ;

  _proto.getFilter = function getFilter(conditions) {
    var filter = function filter(obj) {
      var filtered = true;
      conditions.forEach(function (cond) {
        var field = cond.field;
        var value = cond.value; // const values = cond.values;

        var tmp = true;

        if (!isNil(value) && field) {
          tmp = obj[field] === value;
        }

        filtered = filtered && tmp;
      });
      return filtered;
    };

    return filter;
  }
  /**
   * 获取字段对应的值
   * @protected
   * @param  {String} field 字段名
   * @param  {Array} data 数据
   * @return {Array} 字段对应的值
   */
  ;

  _proto.getFieldValues = function getFieldValues(field, data) {
    var rst = [];
    var tmpMap = {};

    for (var i = 0; i < data.length; i++) {
      var obj = data[i];
      var value = obj[field];

      if (!isNil(value) && !tmpMap[value]) {
        rst.push(value);
        tmpMap[value] = true;
      }
    }

    return rst;
  };

  _proto.getRegion = function getRegion(rows, cols, xIndex, yIndex) {
    var xWidth = 1 / cols; // x轴方向的每个分面的偏移

    var yWidth = 1 / rows; // y轴方向的每个分面的偏移

    var start = {
      x: xWidth * xIndex,
      y: yWidth * yIndex
    };
    var end = {
      x: start.x + xWidth,
      y: start.y + yWidth
    };
    return {
      start: start,
      end: end
    };
  }
  /**
   * 生成分面
   * @protected
   * @return {Array} 多个分面集合
   */
  ;

  _proto.generateFacets = function generateFacets() {
    return [];
  };

  _proto._bindEvent = function _bindEvent() {
    var chart = this.chart;
    chart.on('afterchangedata', wrapBehavior(this, 'onDataChange'));
    chart.on('beforeclear', wrapBehavior(this, 'onClear'));
    chart.on('beforedestroy', wrapBehavior(this, 'destroy'));
    chart.on('beforepaint', wrapBehavior(this, 'onPaint'));
    chart.on('setdata', wrapBehavior(this, 'onDataChange'));
  };

  _proto._clearEvent = function _clearEvent() {
    var chart = this.chart;

    if (chart) {
      chart.off('afterchangedata', getWrapBehavior(this, 'onDataChange'));
      chart.off('beforeclear', getWrapBehavior(this, 'onClear'));
      chart.off('beforedestroy', getWrapBehavior(this, 'destroy'));
      chart.off('beforepaint', getWrapBehavior(this, 'onPaint'));
      chart.off('setdata', getWrapBehavior(this, 'onDataChange'));
    }
  };

  _proto._clearFacets = function _clearFacets() {
    var facets = this.facets;
    var chart = this.chart;

    if (facets) {
      for (var i = 0; i < facets.length; i++) {
        var facet = facets[i];
        chart.removeView(facet.view);
      }
    }

    this.facets = null;
  };

  _proto.onClear = function onClear() {
    this.onRemove();
  };

  _proto.onPaint = function onPaint() {
    if (this.showTitle) {
      var facets = this.facets;

      for (var i = 0; i < facets.length; i++) {
        var facet = facets[i];
        var view = facet.view;
        this.renderTitle(view, facet);
      }
    }
  };

  _proto.onDataChange = function onDataChange() {
    this._clearFacets();

    this.initViews();
  };

  _proto.onRemove = function onRemove() {
    this._clearFacets();

    this._clearEvent();

    this.group && this.group.remove();
    this.chart = null;
    this.facets = null;
    this.group = null;
  };

  _proto.destroy = function destroy() {
    this.onRemove();
    this.destroyed = true;
  };

  return Base;
}();

module.exports = Base;