var angular = require('angular');
require('../modules');

var module = angular.module('commons.services.timer');

/**
 * @ngdoc service
 * @name commons.Timer
 * @module commons
 * @kind function
 *
 * @requires $$rAF
 * 
 * @description
 * 时间管理组件。可以延迟或者周期性执行任务。主要用于执行动画效果。
 * 
 * ```javascript
 * var taskId = Timer.interval(function() {
 *     console.log('do something');
 * }, 1000); //每隔1s执行一次。
 *
 * Timer.clear(taskId); //清除执行的任务。
 *
 * var taskId = Timer.delay(function() {
 *     console.log('do something');
 * }, 1000); //1s之后执行一次。自动清除任务。
 * ```
 */
module.factory('Timer', function($$rAF, $rootScope) {
  var tasks = [];
  var taskMap = {};
  var taskSeed = 0;
  var Timer = {};

  function createTask(type, fn, time) {
    time = time || 1000 / 60;
    var taskId = taskSeed++;
    var frames = Math.ceil(time / (1000 / 60));
    var task = {
      id: taskId,
      type: type,
      fn: fn,
      time: time,
      defaultFrames: frames,
      frames: frames
    };
    tasks.push(task);
    taskMap[taskId] = task;
    return taskId;
  }

  /**
   * @ngdoc method
   * @name commons.Timer#interval
   * @module commons
   *
   * @description
   * 添加周期性执行任务。即每隔`time`ms执行一次`fn`。
   * 
   * @param  {Function} fn    待执行的函数。
   * @param  {Integer}  time  执行的时间间隔，即执行周期。
   * @return {Integer}  返回执行任务的id。
   */
  Timer.interval = function(fn, time) {
    return createTask('interval', fn, time);
  };

  /**
   * @ngdoc method
   * @name Timer#stop
   *
   * @description
   * 等同于{@link Timer#clear Timer.clear}。
   */
  /**
   * @ngdoc method
   * @name Timer#clear
   *
   * @description
   * 停止并清除正在执行的任务。
   * 
   * @param  {Integer} taskId 待清除的任务id。
   */
  Timer.stop = Timer.clear = function(taskId) {
    if (taskMap[taskId]) {
      taskMap[taskId].removed = true;
    }
  };

  /**
   * @ngdoc method
   * @name Timer#pause
   *
   * @description
   * 暂停正在执行的任务。任务暂停之后，可以调用{@link Timer#continue Timer.continue(taskId)}
   * 方法恢复正在执行的任务。
   *
   * ```javascript
   * var taskId = Timer.interval(function() {
   *     console.log('do something');
   * }, 1000); // 每隔1s执行一次。
   *
   * //500ms之后
   * Timer.pause(taskId); //暂停任务。
   *
   * Timer.continue(taskId); //恢复暂停的任务。
   *
   * //500ms之后，打印do something。
   * ```
   * 
   * @param  {Integer} taskId 待暂停的任务id。
   */
  Timer.pause = function(taskId) {
    if (taskMap[taskId]) {
      taskMap[taskId].pause = true;
    }
  };

  /**
   * @ngdoc method
   * @name Timer#continue
   *
   * @description
   * 恢复暂停的任务。
   * 
   * @param  {Integer} taskId 待恢复的任务id。
   */
  Timer.continue = function(taskId) {
    if (taskMap[taskId]) {
      delete taskMap[taskId].pause;
    }
  };

  /**
   * @ngdoc method
   * @name Timer#delay
   *
   * @description
   * 添加延迟执行的任务。任务执行完之后，会自动清除。
   * 
   * @param  {Function}  fn    任务执行函数。
   * @param  {Integer}   time  延迟执行的时间。
   * @return {Integer}   返回创建的任务id。
   */
  Timer.delay = function(fn, time) {
    return createTask('delay', fn, time);
  };

  function doTasks() {
    if (tasks.length > 0) {
      var willExecTasks = [];

      for (var i = tasks.length; i--;) {
        var task = tasks[i];
        if (task.removed) {
          tasks.splice(i, 1);
          continue;
        }
        if (task.pause) {
          continue;
        }
        task.frames--;
        if (task.frames <= 0) {
          if (task.type === 'interval') {
            task.frames = task.defaultFrames;
          } else {
            task.removed = true;
          }
          willExecTasks.push(task);
        }
      }

      if (willExecTasks.length > 0) {
        $rootScope.$evalAsync(function() {
          willExecTasks.forEach(execTask);
        });
      }
    }
  }

  function execTask(task) {
    task.fn();
  }

  function doTasksInRaf() {
    doTasks();
    $$rAF(doTasksInRaf);
  }
  doTasksInRaf();

  return Timer;
});
