var angular = require('angular'),
  _ = require('jsUtil');
require('../modules');
var module = angular.module('commons.services');

/**
 * 提供缓存与异步获取数据相结合的服务。
 *
 * 
 * @example
 * var Storage = window.localStorage;
 * var LocalCache = CacheFactory.generate(Storage);
 * var key = 'key';
 * var getterFn = function() {
 *   return $http.get('/common/option/key').then(function(response) {return response.data;});
 * };
 *
 * LocalCache.setGetter('key', getterFn);
 *
 * LocalCache.get('key').then(function(value){
 *   console.log('获取到的值为：', value);
 * });
 *
 * //第二个场景
 * LocalCache.put('key', 'value');
 * LocalCache.get('key').then(function(value) {
 *   console.log('获取到的值为：' + value);
 * });
 */
module.factory('CacheFactory', function($q) {
  function CacheFactory(storage) {
    this.storage = storage;
    this.getterConfig = {};
    this.gettingValuePromise = {};
  }

  CacheFactory.prototype = {
    setGetter: function(key, fn) {
      if (this.getterConfig[key]) {
        throw new Error('缓存中已存在缓存key：' + key);
      } else {
        this.getterConfig[key] = fn;
      }
    },

    /**
     * 获取值。
     * 
     * @param  {String} key 键值
     * @return {Promise}    未来对象。
     */
    get: function(key) {
      var storage = this.storage,
        promiseCache = this.gettingValuePromise,
        promise = promiseCache[key],
        fn = this.getterConfig[key];
      if (!promise) {
        var value = storage.getItem(key);
        if (!_.isUndefined(value) && !_.isNull(value)) {
          promise = $q.when(value);
        } else if (fn) {
          promise = $q.when(fn(key)).then(function(value) {
            delete promiseCache[key];
            storage.setItem(key, value);
            return value;
          });
          promiseCache[key] = promise;
        } else {
          promise = $q.when(null);
        }
      }
      
      return promise;
    },

    /**
     * 缓存值。
     * 
     * @param  {String} key   缓存的键值
     * @param  {Any}    value 缓存的值
     * @return {Promise}      未来对象。
     */
    put: function(key, value) {
      var promise = $q.when(value),
        storage = this.storage,
        promiseCache = this.gettingValuePromise;
      promiseCache[key] = promise;

      return promise.then(function(value) {
        storage.setItem(key, value);
        delete promiseCache[key];
        return value;
      });
    },

    /**
     * 删除数据项
     * 
     * @param  {String} key 数据项名称
     * @return {Promise}    未来对象。
     */
    remove: function(key) {
      var value = this.storage.getItem(key);
      delete this.gettingValuePromise[key];
      this.storage.removeItem(key);
      return $q.when(value);
    }
  };

  CacheFactory.generate = function(storage) {
    return new CacheFactory(storage);
  };

  return CacheFactory;
});
