var angular = require('angular');
require('../modules');
require('jsUtil');
require('./TaskRemoteService');
'use strict';

var module = angular.module('task.services');

/**
 * 任务缓存服务。
 */
module.factory('TaskLocalforageService', function($q, TaskRemoteService, localforage) {
  var service = {
    map: {},
    promiseMap: {},
    /**
     * 根据任务id从任务缓存中获取一条任务。
     * @param {String} taskId 任务id
     * @param {Boolean} [=false] fromCache 是否强制从缓存中加载
     * @return Promise
     */
    getById: function(taskId, fromCache) {
      var promise = service.getFromMapOrCache(taskId, fromCache).then(function(task) {
        if (task) {
          return task;
        } else {
          return service.getFromRemote(taskId).then(function(task) {
            return service.setTask(task);
          });
        }
      });
      return promise;
    },
    /**
     * 根据消息id从缓存中获取消息。
     * @param  {String} discussionId 消息id
     */
    getDiscussionById: function(discussionId) {
      var promise = service.getDiscussionFromMapOrCache(discussionId).then(function(discussion) {
        return discussion;
      });
      return promise;
    },
    /**
     * 根据消息的id从内存或者缓存中获取消息。
     * @param  {String} discussionId 消息id
     */
    getDiscussionFromMapOrCache: function(discussionId) {
      var cachedDiscussion = service.map[discussionId];
      if(cachedDiscussion) {
        return $q.when(cachedDiscussion);
      }else {
        var promise = localforage.getItem('discussion:' + discussionId).then(function(discussion) {
          cachedDiscussion = service.map[discussionId] = discussion;
          delete service.promiseMap[discussionId];
          return cachedDiscussion;
        });
        service.promiseMap[discussionId] = promise;
        return $q.when(promise);
      }
    },
    /**
     * 根据任务id从内存或者缓存中获取任务。
     * @param  {String} taskId 任务id
     * @return {Promise}
     */
    getFromMapOrCache: function(taskId, fromCache) {
      var cachedTask = service.map[taskId];
      if (cachedTask && !fromCache) {
        return $q.when(cachedTask);
      } else if (service.promiseMap[taskId] && !fromCache) {
        return service.promiseMap[taskId];
      } else {
        var promise = localforage.getItem('task:' + taskId).then(function(task) {
          cachedTask = service.map[taskId] = task;
          delete service.promiseMap[taskId];
          return cachedTask;
        });
        service.promiseMap[taskId] = promise;
        return $q.when(promise);
      }

    },
    /**
     * 根据任务id从远端获取任务。
     * @param  {String} taskId 任务id
     */
    getFromRemote: function(taskId) {
      if (service.promiseMap[taskId]) {
        return service.promiseMap[taskId];
      } else {
        var promise = TaskRemoteService.queryTaskDetail(taskId);
        service.promiseMap[taskId] = promise;
        return promise;
      }
    },

    applyTask: function(task) {
      return service.getFromMapOrCache(task.id).then(function(cachedTask) {
        if (cachedTask !== task) {
          if (cachedTask) {
            delete task.discussions;
            _.apply(cachedTask, task);
            return cachedTask;
          } else {
            cachedTask = service.map[task.id] = task;
            return cachedTask;
          }
        } else {
          return cachedTask;
        }
      });
    },

    cloneTask: function(task) {
      task = _.copy(task);
      _.each(task, function(value, key) {
        if (key.charAt(0) === '$') {
          delete task[key];
        }
      });
      return task;
    },
    /**
     * 将任务添加到缓存中。
     * @param {Task} task 需要添加到缓存中的任务
     */
    setTask: function(task) {
      return service.applyTask(task).then(function(cachedTask) {
        task = service.cloneTask(cachedTask);
        return service.setCacheTask(task).then(function() {
          return cachedTask;
        });
      });
    },
    /**
     * 将消息添加到缓存中。
     * @param {Discussion} discussion 需要添加到缓存中的消息数据。
     */
    setDiscussion: function(discussion) {
      return $q.when(localforage.setItem('discussion:' + discussion.id, discussion));
    },
    /**
     * 设置缓存任务。
     * @param {Task} task 任务对象
     */
    setCacheTask: function(task) {
      return $q.when(localforage.setItem('task:' + task.id, task));
    },
    /**
     * 获取某一任务的评论列表。
     * @param  {String} taskId 任务id
     */
    getDiscussions: function(taskId) {
      return service.getById(taskId).then(function(task) {
        return task.discussions;
      });
    },
    /**
     * 给某一任务添加评论
     * @param {Discussion} discussion [description]
     */
    addDiscussion: function(discussion) {
      return service.getById(discussion.recordId).then(function(task) {
        task.discussions = jsUtil.isArray(task.discussions) ? task.discussions : [];
        if (!service.getEqualItem(task.discussions, discussion)) {
          task.discussions.push(discussion);
        }
        return service.setCacheTask(task);
      });
    },

    indexOfItem: function(array, item) {
      var id = _.isObject(item) ? item.id : item,
        result = -1;
      _.each(array, function(_item, index) {
        if (id === _item.id) {
          result = index;
        }
      });

      return result;
    },
    /**
     * 修改缓存中任务的评论或消息列表。
     * @param  {Array} discussions 评论或消息列表
     */
    changeDiscussions: function(discussions) {
      if (discussions.length === 0) {
        return $q.when();
      } else {
        return service.getById(discussions[0].recordId).then(function(task) {
          task.discussions = discussions;
          return service.setCacheTask(task);
        });
      }
    },
    /**
     * 修改缓存中任务的消息列表中的某一个消息。
     * 此处localContent的作用是将本地缓存中的讨论消息内容保留，避免在图片上传的时候，出现替换闪现。
     * 
     * @param  {Object} discussion 需要替换的新消息
     * @param {String} cacheId 缓存中的消息id
     */
    changeDiscussion: function(discussion, cacheId) {
      return service.getById(discussion.recordId).then(function(task) {
        task.discussions = jsUtil.isArray(task.discussions) ? task.discussions : [];
        var idx = service.indexOfItem(task.discussions, cacheId);
        var localContent = task.discussions[idx]? task.discussions[idx].content: discussion.content;
        task.discussions[idx] = discussion;
        task.discussions[idx].content = localContent;

        return service.setCacheTask(task);
      });
    },
    /**
     * 从items中获取与myItem具有相同id的元素。
     * @param  {Array} items
     * @param  {Object} myItem
     */
    getEqualItem: function(items, myItem) {
      return jsUtil.find(items, function(item) {
        return item.id === myItem.id;
      });
    },
    /**
     * 移除缓存中已缓存的某一任务。
     * @param {String} itemName 需要移除值的属性
     * @return Promise
     */
    removeItem: function(taskId) {
      delete service.map[taskId];
      return $q.when(localforage.removeItem('task:' + taskId));
    },
    /**
     * 移除缓存中的消息。
     * @param  {String} discussionId 消息id
     */
    removeDiscussionFromCache: function(discussionId) {
      delete service.map[discussionId];
      return $q.when(localforage.removeItem('discussion:' + discussionId));
    }
  };

  return service;

});