import * as echarts from 'echarts/lib/echarts';
import createGraphFromNodeEdge from './createGraphFromNodeEdge';
import formatUtil from '../../util/format';
var GraphSeries = echarts.SeriesModel.extend({
  type: 'series.graphGL',
  visualStyleAccessPath: 'itemStyle',
  hasSymbolVisual: true,
  init: function (option) {
    GraphSeries.superApply(this, 'init', arguments); // Provide data for legend select

    this.legendDataProvider = function () {
      return this._categoriesData;
    };

    this._updateCategoriesData();
  },
  mergeOption: function (option) {
    GraphSeries.superApply(this, 'mergeOption', arguments);

    this._updateCategoriesData();
  },
  getFormattedLabel: function (dataIndex, status, dataType, dimIndex) {
    var text = formatUtil.getFormattedLabel(this, dataIndex, status, dataType, dimIndex);

    if (text == null) {
      var data = this.getData();
      var lastDim = data.dimensions[data.dimensions.length - 1];
      text = data.get(lastDim, dataIndex);
    }

    return text;
  },
  getInitialData: function (option, ecModel) {
    var edges = option.edges || option.links || [];
    var nodes = option.data || option.nodes || [];
    var self = this;

    if (nodes && edges) {
      return createGraphFromNodeEdge(nodes, edges, this, true, beforeLink).data;
    }

    function beforeLink(nodeData, edgeData) {
      // Overwrite nodeData.getItemModel to
      nodeData.wrapMethod('getItemModel', function (model) {
        const categoriesModels = self._categoriesModels;
        const categoryIdx = model.getShallow('category');
        const categoryModel = categoriesModels[categoryIdx];

        if (categoryModel) {
          categoryModel.parentModel = model.parentModel;
          model.parentModel = categoryModel;
        }

        return model;
      }); // TODO Inherit resolveParentPath by default in Model#getModel?

      const oldGetModel = ecModel.getModel([]).getModel;

      function newGetModel(path, parentModel) {
        const model = oldGetModel.call(this, path, parentModel);
        model.resolveParentPath = resolveParentPath;
        return model;
      }

      edgeData.wrapMethod('getItemModel', function (model) {
        model.resolveParentPath = resolveParentPath;
        model.getModel = newGetModel;
        return model;
      });

      function resolveParentPath(pathArr) {
        if (pathArr && (pathArr[0] === 'label' || pathArr[1] === 'label')) {
          const newPathArr = pathArr.slice();

          if (pathArr[0] === 'label') {
            newPathArr[0] = 'edgeLabel';
          } else if (pathArr[1] === 'label') {
            newPathArr[1] = 'edgeLabel';
          }

          return newPathArr;
        }

        return pathArr;
      }
    }
  },

  /**
   * @return {module:echarts/data/Graph}
   */
  getGraph: function () {
    return this.getData().graph;
  },

  /**
   * @return {module:echarts/data/List}
   */
  getEdgeData: function () {
    return this.getGraph().edgeData;
  },

  /**
   * @return {module:echarts/data/List}
   */
  getCategoriesData: function () {
    return this._categoriesData;
  },

  /**
   * @override
   */
  formatTooltip: function (dataIndex, multipleSeries, dataType) {
    if (dataType === 'edge') {
      var nodeData = this.getData();
      var params = this.getDataParams(dataIndex, dataType);
      var edge = nodeData.graph.getEdgeByIndex(dataIndex);
      var sourceName = nodeData.getName(edge.node1.dataIndex);
      var targetName = nodeData.getName(edge.node2.dataIndex);
      var html = [];
      sourceName != null && html.push(sourceName);
      targetName != null && html.push(targetName);
      html = echarts.format.encodeHTML(html.join(' > '));

      if (params.value) {
        html += ' : ' + echarts.format.encodeHTML(params.value);
      }

      return html;
    } else {
      // dataType === 'node' or empty
      return GraphSeries.superApply(this, 'formatTooltip', arguments);
    }
  },
  _updateCategoriesData: function () {
    var categories = (this.option.categories || []).map(function (category) {
      // Data must has value
      return category.value != null ? category : Object.assign({
        value: 0
      }, category);
    });
    var categoriesData = new echarts.List(['value'], this);
    categoriesData.initData(categories);
    this._categoriesData = categoriesData;
    this._categoriesModels = categoriesData.mapArray(function (idx) {
      return categoriesData.getItemModel(idx, true);
    });
  },
  setView: function (payload) {
    if (payload.zoom != null) {
      this.option.zoom = payload.zoom;
    }

    if (payload.offset != null) {
      this.option.offset = payload.offset;
    }
  },
  setNodePosition: function (points) {
    for (var i = 0; i < points.length / 2; i++) {
      var x = points[i * 2];
      var y = points[i * 2 + 1];
      var opt = this.getData().getRawDataItem(i);
      opt.x = x;
      opt.y = y;
    }
  },
  isAnimationEnabled: function () {
    return GraphSeries.superCall(this, 'isAnimationEnabled') // Not enable animation when do force layout
    && !(this.get('layout') === 'force' && this.get('force.layoutAnimation'));
  },
  defaultOption: {
    zlevel: 10,
    z: 2,
    legendHoverLink: true,
    // Only support forceAtlas2
    layout: 'forceAtlas2',
    // Configuration of force directed layout
    forceAtlas2: {
      initLayout: null,
      GPU: true,
      steps: 1,
      // barnesHutOptimize
      // Maxp layout steps.
      maxSteps: 1000,
      repulsionByDegree: true,
      linLogMode: false,
      strongGravityMode: false,
      gravity: 1.0,
      // scaling: 1.0,
      edgeWeightInfluence: 1.0,
      // Edge weight range.
      edgeWeight: [1, 4],
      // Node weight range.
      nodeWeight: [1, 4],
      // jitterTolerence: 0.1,
      preventOverlap: false,
      gravityCenter: null
    },
    focusNodeAdjacency: true,
    focusNodeAdjacencyOn: 'mouseover',
    left: 'center',
    top: 'center',
    // right: null,
    // bottom: null,
    // width: '80%',
    // height: '80%',
    symbol: 'circle',
    symbolSize: 5,
    roam: false,
    // Default on center of graph
    center: null,
    zoom: 1,
    // categories: [],
    // data: []
    // Or
    // nodes: []
    //
    // links: []
    // Or
    // edges: []
    label: {
      show: false,
      formatter: '{b}',
      position: 'right',
      distance: 5,
      textStyle: {
        fontSize: 14
      }
    },
    itemStyle: {},
    lineStyle: {
      color: '#aaa',
      width: 1,
      opacity: 0.5
    },
    emphasis: {
      label: {
        show: true
      }
    },
    animation: false
  }
});
export default GraphSeries;