/**
 * echarts图表动画基类
 *
 * @desc echarts基于Canvas，纯Javascript图表库，提供直观，生动，可交互，可个性化定制的数据统计图表。
 * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
 *
 */
module.exports = function (require) {
  var zrUtil = require('zrender/tool/util');

  var curveTool = require('zrender/tool/curve');
  /**
   * 折线型动画
   * 
   * @param {ZRender} zr
   * @param {shape} oldShape
   * @param {shape} newShape
   * @param {number} duration
   * @param {tring} easing
   */


  function pointList(zr, oldShape, newShape, duration, easing) {
    var newPointList = newShape.style.pointList;
    var newPointListLen = newPointList.length;
    var oldPointList;

    if (!oldShape) {
      // add
      oldPointList = [];

      if (newShape._orient != 'vertical') {
        var y = newPointList[0][1];

        for (var i = 0; i < newPointListLen; i++) {
          oldPointList[i] = [newPointList[i][0], y];
        }
      } else {
        var x = newPointList[0][0];

        for (var i = 0; i < newPointListLen; i++) {
          oldPointList[i] = [x, newPointList[i][1]];
        }
      }

      if (newShape.type == 'half-smooth-polygon') {
        oldPointList[newPointListLen - 1] = zrUtil.clone(newPointList[newPointListLen - 1]);
        oldPointList[newPointListLen - 2] = zrUtil.clone(newPointList[newPointListLen - 2]);
      }

      oldShape = {
        style: {
          pointList: oldPointList
        }
      };
    }

    oldPointList = oldShape.style.pointList;
    var oldPointListLen = oldPointList.length;

    if (oldPointListLen == newPointListLen) {
      newShape.style.pointList = oldPointList;
    } else if (oldPointListLen < newPointListLen) {
      // 原来短，新的长，补全
      newShape.style.pointList = oldPointList.concat(newPointList.slice(oldPointListLen));
    } else {
      // 原来长，新的短，截断
      newShape.style.pointList = oldPointList.slice(0, newPointListLen);
    }

    zr.addShape(newShape);
    newShape.__animating = true;
    zr.animate(newShape.id, 'style').when(duration, {
      pointList: newPointList
    }).during(function () {
      // Updating bezier points
      if (newShape.updateControlPoints) {
        newShape.updateControlPoints(newShape.style);
      }
    }).done(function () {
      newShape.__animating = false;
    }).start(easing);
  }
  /**
   * 复制样式
   * 
   * @inner
   * @param {Object} target 目标对象
   * @param {Object} source 源对象
   * @param {...string} props 复制的属性列表
   */


  function cloneStyle(target, source) {
    var len = arguments.length;

    for (var i = 2; i < len; i++) {
      var prop = arguments[i];
      target.style[prop] = source.style[prop];
    }
  }
  /**
   * 方型动画
   * 
   * @param {ZRender} zr
   * @param {shape} oldShape
   * @param {shape} newShape
   * @param {number} duration
   * @param {tring} easing
   */


  function rectangle(zr, oldShape, newShape, duration, easing) {
    var newShapeStyle = newShape.style;

    if (!oldShape) {
      // add
      oldShape = {
        position: newShape.position,
        style: {
          x: newShapeStyle.x,
          y: newShape._orient == 'vertical' ? newShapeStyle.y + newShapeStyle.height : newShapeStyle.y,
          width: newShape._orient == 'vertical' ? newShapeStyle.width : 0,
          height: newShape._orient != 'vertical' ? newShapeStyle.height : 0
        }
      };
    }

    var newX = newShapeStyle.x;
    var newY = newShapeStyle.y;
    var newWidth = newShapeStyle.width;
    var newHeight = newShapeStyle.height;
    var newPosition = [newShape.position[0], newShape.position[1]];
    cloneStyle(newShape, oldShape, 'x', 'y', 'width', 'height');
    newShape.position = oldShape.position;
    zr.addShape(newShape);

    if (newPosition[0] != oldShape.position[0] || newPosition[1] != oldShape.position[1]) {
      zr.animate(newShape.id, '').when(duration, {
        position: newPosition
      }).start(easing);
    }

    newShape.__animating = true;
    zr.animate(newShape.id, 'style').when(duration, {
      x: newX,
      y: newY,
      width: newWidth,
      height: newHeight
    }).done(function () {
      newShape.__animating = false;
    }).start(easing);
  }
  /**
   * 蜡烛动画
   * 
   * @param {ZRender} zr
   * @param {shape} oldShape
   * @param {shape} newShape
   * @param {number} duration
   * @param {tring} easing
   */


  function candle(zr, oldShape, newShape, duration, easing) {
    if (!oldShape) {
      // add
      var y = newShape.style.y;
      oldShape = {
        style: {
          y: [y[0], y[0], y[0], y[0]]
        }
      };
    }

    var newY = newShape.style.y;
    newShape.style.y = oldShape.style.y;
    zr.addShape(newShape);
    newShape.__animating = true;
    zr.animate(newShape.id, 'style').when(duration, {
      y: newY
    }).done(function () {
      newShape.__animating = false;
    }).start(easing);
  }
  /**
   * 环型动画
   * 
   * @param {ZRender} zr
   * @param {shape} oldShape
   * @param {shape} newShape
   * @param {number} duration
   * @param {tring} easing
   */


  function ring(zr, oldShape, newShape, duration, easing) {
    var x = newShape.style.x;
    var y = newShape.style.y;
    var r0 = newShape.style.r0;
    var r = newShape.style.r;
    newShape.__animating = true;

    if (newShape._animationAdd != 'r') {
      newShape.style.r0 = 0;
      newShape.style.r = 0;
      newShape.rotation = [Math.PI * 2, x, y];
      zr.addShape(newShape);
      zr.animate(newShape.id, 'style').when(duration, {
        r0: r0,
        r: r
      }).done(function () {
        newShape.__animating = false;
      }).start(easing);
      zr.animate(newShape.id, '').when(duration, {
        rotation: [0, x, y]
      }).start(easing);
    } else {
      newShape.style.r0 = newShape.style.r;
      zr.addShape(newShape);
      zr.animate(newShape.id, 'style').when(duration, {
        r0: r0
      }).done(function () {
        newShape.__animating = false;
      }).start(easing);
    }
  }
  /**
   * 扇形动画
   * 
   * @param {ZRender} zr
   * @param {shape} oldShape
   * @param {shape} newShape
   * @param {number} duration
   * @param {tring} easing
   */


  function sector(zr, oldShape, newShape, duration, easing) {
    if (!oldShape) {
      // add
      if (newShape._animationAdd != 'r') {
        oldShape = {
          style: {
            startAngle: newShape.style.startAngle,
            endAngle: newShape.style.startAngle
          }
        };
      } else {
        oldShape = {
          style: {
            r0: newShape.style.r
          }
        };
      }
    }

    var startAngle = newShape.style.startAngle;
    var endAngle = newShape.style.endAngle;
    cloneStyle(newShape, oldShape, 'startAngle', 'endAngle');
    zr.addShape(newShape);
    newShape.__animating = true;
    zr.animate(newShape.id, 'style').when(duration, {
      startAngle: startAngle,
      endAngle: endAngle
    }).done(function () {
      newShape.__animating = false;
    }).start(easing);
  }
  /**
   * 文本动画
   * 
   * @param {ZRender} zr
   * @param {shape} oldShape
   * @param {shape} newShape
   * @param {number} duration
   * @param {tring} easing
   */


  function text(zr, oldShape, newShape, duration, easing) {
    if (!oldShape) {
      // add
      oldShape = {
        style: {
          x: newShape.style.textAlign == 'left' ? newShape.style.x + 100 : newShape.style.x - 100,
          y: newShape.style.y
        }
      };
    }

    var x = newShape.style.x;
    var y = newShape.style.y;
    cloneStyle(newShape, oldShape, 'x', 'y');
    zr.addShape(newShape);
    newShape.__animating = true;
    zr.animate(newShape.id, 'style').when(duration, {
      x: x,
      y: y
    }).done(function () {
      newShape.__animating = false;
    }).start(easing);
  }
  /**
   * 多边形动画
   * 
   * @param {ZRender} zr
   * @param {shape} oldShape
   * @param {shape} newShape
   * @param {number} duration
   * @param {tring} easing
   */


  function polygon(zr, oldShape, newShape, duration, easing) {
    var rect = require('zrender/shape/Polygon').prototype.getRect(newShape.style);

    var x = rect.x + rect.width / 2;
    var y = rect.y + rect.height / 2;
    newShape.scale = [0.1, 0.1, x, y];
    zr.addShape(newShape);
    newShape.__animating = true;
    zr.animate(newShape.id, '').when(duration, {
      scale: [1, 1, x, y]
    }).done(function () {
      newShape.__animating = false;
    }).start(easing);
  }
  /**
   * 和弦动画
   * 
   * @param {ZRender} zr
   * @param {shape} oldShape
   * @param {shape} newShape
   * @param {number} duration
   * @param {tring} easing
   */


  function ribbon(zr, oldShape, newShape, duration, easing) {
    if (!oldShape) {
      // add
      oldShape = {
        style: {
          source0: 0,
          source1: newShape.style.source1 > 0 ? 360 : -360,
          target0: 0,
          target1: newShape.style.target1 > 0 ? 360 : -360
        }
      };
    }

    var source0 = newShape.style.source0;
    var source1 = newShape.style.source1;
    var target0 = newShape.style.target0;
    var target1 = newShape.style.target1;

    if (oldShape.style) {
      cloneStyle(newShape, oldShape, 'source0', 'source1', 'target0', 'target1');
    }

    zr.addShape(newShape);
    newShape.__animating = true;
    zr.animate(newShape.id, 'style').when(duration, {
      source0: source0,
      source1: source1,
      target0: target0,
      target1: target1
    }).done(function () {
      newShape.__animating = false;
    }).start(easing);
  }
  /**
   * gaugePointer动画
   * 
   * @param {ZRender} zr
   * @param {shape} oldShape
   * @param {shape} newShape
   * @param {number} duration
   * @param {tring} easing
   */


  function gaugePointer(zr, oldShape, newShape, duration, easing) {
    if (!oldShape) {
      // add
      oldShape = {
        style: {
          angle: newShape.style.startAngle
        }
      };
    }

    var angle = newShape.style.angle;
    newShape.style.angle = oldShape.style.angle;
    zr.addShape(newShape);
    newShape.__animating = true;
    zr.animate(newShape.id, 'style').when(duration, {
      angle: angle
    }).done(function () {
      newShape.__animating = false;
    }).start(easing);
  }
  /**
   * icon动画
   * 
   * @param {ZRender} zr
   * @param {shape} oldShape
   * @param {shape} newShape
   * @param {number} duration
   * @param {tring} easing
   */


  function icon(zr, oldShape, newShape, duration, easing, delay) {
    // 避免markPoint特效取值在动画帧上
    newShape.style._x = newShape.style.x;
    newShape.style._y = newShape.style.y;
    newShape.style._width = newShape.style.width;
    newShape.style._height = newShape.style.height;

    if (!oldShape) {
      // add
      var x = newShape._x || 0;
      var y = newShape._y || 0;
      newShape.scale = [0.01, 0.01, x, y];
      zr.addShape(newShape);
      newShape.__animating = true;
      zr.animate(newShape.id, '').delay(delay).when(duration, {
        scale: [1, 1, x, y]
      }).done(function () {
        newShape.__animating = false;
      }).start(easing || 'QuinticOut');
    } else {
      // mod
      rectangle(zr, oldShape, newShape, duration, easing);
    }
  }
  /**
   * line动画
   * 
   * @param {ZRender} zr
   * @param {shape} oldShape
   * @param {shape} newShape
   * @param {number} duration
   * @param {tring} easing
   */


  function line(zr, oldShape, newShape, duration, easing) {
    if (!oldShape) {
      oldShape = {
        style: {
          xStart: newShape.style.xStart,
          yStart: newShape.style.yStart,
          xEnd: newShape.style.xStart,
          yEnd: newShape.style.yStart
        }
      };
    }

    var xStart = newShape.style.xStart;
    var xEnd = newShape.style.xEnd;
    var yStart = newShape.style.yStart;
    var yEnd = newShape.style.yEnd;
    cloneStyle(newShape, oldShape, 'xStart', 'xEnd', 'yStart', 'yEnd');
    zr.addShape(newShape);
    newShape.__animating = true;
    zr.animate(newShape.id, 'style').when(duration, {
      xStart: xStart,
      xEnd: xEnd,
      yStart: yStart,
      yEnd: yEnd
    }).done(function () {
      newShape.__animating = false;
    }).start(easing);
  }
  /**
   * markline动画
   * 
   * @param {ZRender} zr
   * @param {shape} oldShape
   * @param {shape} newShape
   * @param {number} duration
   * @param {tring} easing
   */


  function markline(zr, oldShape, newShape, duration, easing) {
    easing = easing || 'QuinticOut';
    newShape.__animating = true;
    zr.addShape(newShape);
    var newShapeStyle = newShape.style;

    var animationDone = function () {
      newShape.__animating = false;
    };

    var x0 = newShapeStyle.xStart;
    var y0 = newShapeStyle.yStart;
    var x2 = newShapeStyle.xEnd;
    var y2 = newShapeStyle.yEnd;

    if (newShapeStyle.curveness > 0) {
      newShape.updatePoints(newShapeStyle);
      var obj = {
        p: 0
      };
      var x1 = newShapeStyle.cpX1;
      var y1 = newShapeStyle.cpY1;
      var newXArr = [];
      var newYArr = [];
      var subdivide = curveTool.quadraticSubdivide;
      zr.animation.animate(obj).when(duration, {
        p: 1
      }).during(function () {
        // Calculate subdivided curve
        subdivide(x0, x1, x2, obj.p, newXArr);
        subdivide(y0, y1, y2, obj.p, newYArr);
        newShapeStyle.cpX1 = newXArr[1];
        newShapeStyle.cpY1 = newYArr[1];
        newShapeStyle.xEnd = newXArr[2];
        newShapeStyle.yEnd = newYArr[2];
        zr.modShape(newShape);
      }).done(animationDone).start(easing);
    } else {
      zr.animate(newShape.id, 'style').when(0, {
        xEnd: x0,
        yEnd: y0
      }).when(duration, {
        xEnd: x2,
        yEnd: y2
      }).done(animationDone).start(easing);
    }
  }

  return {
    pointList: pointList,
    rectangle: rectangle,
    candle: candle,
    ring: ring,
    sector: sector,
    text: text,
    polygon: polygon,
    ribbon: ribbon,
    gaugePointer: gaugePointer,
    icon: icon,
    line: line,
    markline: markline
  };
}(require);