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

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

function defaultFilter() {
  return true;
}

module.factory('PageableCacheArray', function($q, localforage, PageableArray) {
  function PageableCacheArray(cacheKey, pageSize, filterFn) {
    this.pageableArray = new PageableArray([], pageSize);
    this.items = this.pageableArray.items;
    this.allItems = [];
    this.ids = [];
    this.cacheKey = cacheKey;
    this.filterFn = filterFn || defaultFilter;
    this.loadFromCache();
  }

  function unique(array) {
    var map = {}, item, result = [];
    for (var i = 0, len = array.length; i < len; i++) {
      item = array[i];
      if (!map[item]) {
        result.push(item);
      }
      map[item] = true;
    }
    return result;
  }

  PageableCacheArray.prototype = {
    /**
     * 从缓存中加载ids
     */
    loadFromCache: function() {
      var self = this;
      return localforage.getItem(this.cacheKey).then(function(ids) {
        self.readyPromise = self.applyIds(ids);
        return self.readyPromise;
      });
    },

    ready: function(fn) {
      /* istanbul ignore else  */
      if (this.readyPromise) {
        this.readyPromise.then(fn);
      }
    },

    /**
     * 应用数据主键列表
     * 
     * @param  {Array} ids
     * @param {Promise} [varname] [description]
     */
    applyIds: function(ids) {
      ids = ids || [];
      this.ids = unique(ids);
      return this.reset();
    },

    /**
     * 通过id获取数据。需要扩展实现。
     * 
     * @param  {String} id
     * @return {Promise} 返回promise，resolve中的第一个参数应为获取到的数据。
     */
    getById: function(/*id*/) {
      throw new Error('需要扩展。');
    },

    /**
     * 加载更多的数据
     * @return {Promise}
     */
    loadMore: function() {
      return $q.when(this.pageableArray.loadMore());
    },

    /**
     * 重置分页状态
     * 
     * @return {Promise}
     */
    reset: function() {
      var self = this;
      return this.loadAllItems().then(function() {
        return self.pageableArray.reset(self.allItems);
      });
    },

    /**
     * 更新数组。
     * 
     * @param  {Array} ids
     * @return {Promise}
     */
    updateIds: function(ids) {
      ids = unique(ids);
      return $q.all([localforage.setItem(this.cacheKey, ids), this.applyIds(ids)]);
    },

    /**
     * 加载所有的组件
     * @return {[type]}
     */
    loadAllItems: function() {
      var self = this;
      this.allItems = [];
      return $q.all(_.map(this.ids, function(id) {
        return self.getById(id).then(function(item) {
          var filterResult = self.filterFn(item);
          if (filterResult.then) {
            return filterResult.then(function(result) {
              if (result) {
                self.allItems.push(item);
              }
              return item;
            });
          } else if (filterResult) {
            self.allItems.push(item);
          }

          return item;
        });
      }));
    }
  };

  return PageableCacheArray;
});
