/**
 * @fileOverview 边的 shape
 * @author dxq613@gmail.com
 */
var Util = require('../../util');

var Shape = require('./shape');

var ShapeUtil = require('../util/shape');

var Global = require('../../global');

var PathUtil = require('../util/path');

var CORNER_PERCENT = 1 / 3;

function getAttrs(cfg) {
  var defaultCfg = Global.shape.edge;
  var lineAttrs = Util.mix({}, defaultCfg, cfg.style);
  ShapeUtil.addStrokeAttrs(lineAttrs, cfg);

  if (cfg.size) {
    lineAttrs.lineWidth = cfg.size;
  }

  return lineAttrs;
}

var Edge = Shape.registerFactory('edge', {
  defaultShapeType: 'line',
  getDefaultPoints: function getDefaultPoints(pointInfo) {
    return ShapeUtil.splitPoints(pointInfo);
  },
  getActiveCfg: function getActiveCfg(type, cfg) {
    var lineWidth = cfg.lineWidth || 0;
    return {
      lineWidth: lineWidth + 1
    };
  }
});

function getCPath(from, to) {
  var points = [];
  points.push({
    x: from.x,
    y: from.y * (1 - 1 / 2) + to.y * 1 / 2
  });
  points.push({
    y: from.y * (1 - 1 / 2) + to.y * 1 / 2,
    x: to.x
  });
  points.push(to);
  var sub = ['C'];
  Util.each(points, function (point) {
    sub.push(point.x, point.y);
  });
  return sub;
}

function getQPath(to, center) {
  var points = [];
  points.push({
    x: center.x,
    y: center.y
  });
  points.push(to);
  var sub = ['Q'];
  Util.each(points, function (point) {
    sub.push(point.x, point.y);
  });
  return sub;
}

function createSmoothPath(from, to) {
  var sub = getCPath(from, to);
  var path = [['M', from.x, from.y]];
  path.push(sub);
  return path;
}

function createArcPath(from, to, center) {
  var sub = getQPath(to, center);
  var path = [['M', from.x, from.y]];
  path.push(sub);
  return path;
}

function createArcWeightPath(points, center) {
  var arc1 = getQPath(points[1], center);
  var arc2 = getQPath(points[3], center);
  var path = [['M', points[0].x, points[0].y]];
  path.push(arc2);
  path.push(['L', points[3].x, points[3].y]);
  path.push(['L', points[2].x, points[2].y]);
  path.push(arc1);
  path.push(['L', points[1].x, points[1].y]);
  path.push(['L', points[0].x, points[0].y]);
  path.push(['Z']);
  return path;
}

function createRectPath(from, to) {
  var points = [];
  points.push({
    y: from.y * (1 - CORNER_PERCENT) + to.y * CORNER_PERCENT,
    x: from.x
  });
  points.push({
    y: from.y * (1 - CORNER_PERCENT) + to.y * CORNER_PERCENT,
    x: to.x
  });
  points.push(to);
  var path = [['M', from.x, from.y]];
  Util.each(points, function (point) {
    path.push(['L', point.x, point.y]);
  });
  return path;
}

Shape.registerShape('edge', 'line', {
  draw: function draw(cfg, container) {
    var points = this.parsePoints(cfg.points);
    var attrCfg = getAttrs(cfg);
    var path = PathUtil.getLinePath(points);
    var line = container.addShape('path', {
      attrs: Util.mix(attrCfg, {
        path: path
      })
    });
    return line;
  },
  getMarkerCfg: function getMarkerCfg(cfg) {
    return Util.mix({
      symbol: 'circle',
      radius: 4.5
    }, getAttrs(cfg));
  }
});
Shape.registerShape('edge', 'vhv', {
  draw: function draw(cfg, container) {
    var points = cfg.points;
    var attrCfg = getAttrs(cfg);
    var path = createRectPath(points[0], points[1]);
    path = this.parsePath(path);
    var line = container.addShape('path', {
      attrs: Util.mix(attrCfg, {
        path: path
      })
    });
    return line;
  },
  getMarkerCfg: function getMarkerCfg(cfg) {
    return Util.mix({
      symbol: 'circle',
      radius: 4.5
    }, getAttrs(cfg));
  }
});
Shape.registerShape('edge', 'smooth', {
  draw: function draw(cfg, container) {
    var points = cfg.points;
    var attrCfg = getAttrs(cfg);
    var path = createSmoothPath(points[0], points[1]);
    path = this.parsePath(path);
    var line = container.addShape('path', {
      attrs: Util.mix(attrCfg, {
        path: path
      })
    });
    return line;
  },
  getMarkerCfg: function getMarkerCfg(cfg) {
    return Util.mix({
      symbol: 'circle',
      radius: 4.5
    }, getAttrs(cfg));
  }
}); //  弧线包括笛卡尔坐标系下的半圆弧线、极坐标系下以圆心为控制点的二阶曲线、笛卡尔坐标系下带权重的三阶曲线、极坐标系下带权重的以圆心为控制点的二阶曲线

Shape.registerShape('edge', 'arc', {
  draw: function draw(cfg, container) {
    var points = cfg.points;
    var type = points.length > 2 ? 'weight' : 'normal';
    var attrCfg = getAttrs(cfg);
    var line;
    var path;

    if (cfg.isInCircle) {
      var center = {
        x: 0,
        y: 1
      };

      if (type === 'normal') {
        path = createArcPath(points[0], points[1], center);
      } else {
        attrCfg.fill = attrCfg.stroke;
        path = createArcWeightPath(points, center);
      }

      path = this.parsePath(path);
      line = container.addShape('path', {
        attrs: Util.mix(attrCfg, {
          path: path
        })
      });
    } else {
      if (type === 'normal') {
        points = this.parsePoints(points);
        line = container.addShape('arc', {
          attrs: Util.mix(attrCfg, {
            x: (points[1].x + points[0].x) / 2,
            y: points[0].y,
            r: Math.abs(points[1].x - points[0].x) / 2,
            startAngle: Math.PI,
            endAngle: Math.PI * 2
          })
        });
      } else {
        path = [['M', points[0].x, points[0].y], ['L', points[1].x, points[1].y]];
        var c1 = getCPath(points[1], points[3]);
        var c2 = getCPath(points[2], points[0]);
        path.push(c1);
        path.push(['L', points[3].x, points[3].y]);
        path.push(['L', points[2].x, points[2].y]);
        path.push(c2);
        path.push(['Z']);
        path = this.parsePath(path);
        attrCfg.fill = attrCfg.stroke;
        line = container.addShape('path', {
          attrs: Util.mix(attrCfg, {
            path: path
          })
        });
      }
    }

    return line;
  },
  getMarkerCfg: function getMarkerCfg(cfg) {
    return Util.mix({
      symbol: 'circle',
      radius: 4.5
    }, getAttrs(cfg));
  }
});
module.exports = Edge;