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

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

module.run(function(LinkerCache) {
  LinkerCache.loadDataFromCache();
});

module.factory('LinkerCache',function(localforage, $q){
  var userMap = {},
    allUsers = [],
    loadUserPromise,
    deptMap = {},
    allDepts = [],
    loadDeptPromise;

  function loadFromCache() {
    if (!loadUserPromise) {
      loadUserPromise = localforage.getItem('users')
      .then(function(users) {
        if ((!users) || users.length == 0) {
          loadUserPromise = null;
          return users;
        }
        allUsers = users || [];
        _.each(allUsers, function(user) {
          user.querySources = applyUserQuerySources(user);
          userMap[user.userId] = user;
        });
        return allUsers;
      }, function() {
        loadUserPromise = null;
      });
    }
    return loadUserPromise;
  }

  function loadFromDeptCache() {
    if (!loadDeptPromise) {
      loadDeptPromise = localforage.getItem('depts')
      .then(function(depts) {
        if ((!depts) || depts.length == 0) {
          loadDeptPromise = null;
          return depts;
        }
        allDepts = depts || [];
        _.each(allDepts, function(dept) {
          if (dept) {
            dept.querySources = applyDeptQuerySources(dept);
            deptMap[dept.deptId] = dept;
          }
        });
        return allDepts;
      }, function() {
        loadDeptPromise = null;
      });
    }
    return loadDeptPromise;
  }

  function removeFromMemoryUsers(userId) {
    var result = userMap[userId];
    delete userMap[userId];
    _.any(allUsers, function(user, index) {
      if (user.userId === userId) {
        allUsers.splice(index, 1);
        return true;
      } else {
        return false;
      }
    });
    return result;
  }

  function applyUserQuerySources(user) {
    var querySources = user.querySources;
    if (!querySources) {
      querySources = [user.userName, user.deptName || ''].concat(user.userNamePinyin);
      /* istanbul ignore else */
      if (user.userNameEn) {
        querySources.push(user.userNameEn);
      }
      /* istanbul ignore else */
      if (user.phone) {
        querySources.push(user.phone);
      }

      user.querySources = querySources;
    }
    return user.querySources;
  }

  /**  部门查询项 */
  function applyDeptQuerySources(dept) {
    var querySources = dept.querySources;
    if (!querySources) {
      dept.querySources = [dept.deptName].concat(dept.deptNamePinyin);
    }
    return dept.querySources;
  }

  /**
   * 更新用户缓存
   *
   * @param  {User | Array.<User>} user 待缓存的用户对象
   * @return {Promise}
   */
  function updateUser(users) {
    if (!_.isArray(users)) {
      users = [users];
    }

    var cachedUsers = _.map(users, function(user) {
      var cachedUser = userMap[user.userId];
      if (cachedUser) {
        _.apply(cachedUser, user);
      } else {
        cachedUser = userMap[user.userId] = user;
        allUsers.push(cachedUser);
      }
      cachedUser.querySources = applyUserQuerySources(user);

      return cachedUser;
    });

    return localforage.setItem('users', allUsers).then(function() {
      return cachedUsers;
    });
  }

  function clearDept() {
    loadDeptPromise = null;
    deptMap = {};
    allDepts = [];
    return localforage.removeItem('depts');
  }

  function clearUser() {
    loadUserPromise = null;
    userMap = {};
    allUsers = [];
    return localforage.removeItem('users');
  }

  /**
   * 更新部门缓存
   *
   * @param  {Dept | Array.<Dept>} dept 待缓存的部门对象
   * @return {Promise}
   */
  function updateDept(depts) {
    if (!_.isArray(depts)) {
      depts = [depts];
    }

    var cachedDepts = _.map(depts, function(dept) {
      var cachedDept = deptMap[dept.deptId];
      if (cachedDept) {
        _.apply(cachedDept, dept);
      } else {
        cachedDept = deptMap[dept.deptId] = dept;
        allDepts.push(cachedDept);
      }
      cachedDept.querySources = applyDeptQuerySources(dept);
      return cachedDept;
    });

    return localforage.setItem('depts', allDepts)
      .then(function() { return cachedDepts; });
  }

  /**
   * 删除用户缓存
   *
   * @param  {String} userId 用户id
   * @return {Promise}
   */
  function remove(userId) {
    return get(userId).then(function() {
      var user = removeFromMemoryUsers(userId);
      if (user) {
        return localforage.setItem('users', allUsers).then(function() {
          return user;
        });
      } else {
        return $q.when(user);
      }
    });
  }

  /**
   * 获取userId指向的用户。
   *
   * @param  {String|Array.<String>} userIds 用户id
   * @return {Promise}
   */
  function get(userIds) {
    return loadFromCache().then(function() {
      if (_.isArray(userIds)) {
        var users = [], user, userId;
        for (var i = 0, len = userIds.length; i < len; i++) {
          userId = userIds[i];
          user = userMap[userId];
          if (user) {
            users.push(user);
          }
        }
        return users;
      } else {
        return userMap[userIds];
      }
    });
  }

  /**
   * 获取一组或者一个部门信息
   *
   * @param {Array<String> | String}
   *
   * @return {Promise}
   */
  function getDept(deptIds) {
    return loadFromDeptCache().then(function() {
      if (_.isArray(deptIds)) {
        var depts = [];
        _.each(deptIds, function(value) {
          var dept = deptMap[value];
          if (dept) {
            depts.push(dept);
          }
        });
        return depts;
      } else {
        return deptMap[deptIds];
      }
    });
  }

  /**
   * 获取一组或者一个部门信息
   *
   * @param {Array<String> | String}
   *
   * @return {Promise}
   */
  function getDeptSync(deptIds) {
    var depts = [];
    deptIds = deptIds ? deptIds : [];

    if (Object.prototype.toString.call(deptIds) !== '[object Array]') {
      deptIds = [deptIds];
    }

    _.each(deptIds, function(deptId) {
      if (deptMap[deptId]) {
        depts.push(deptMap[deptId]);
      }
    });
    return depts;
  }

  function getUserSync(userIds) {
    var users = [];
    userIds = userIds ? userIds : [];

    if (Object.prototype.toString.call(userIds) !== '[object Array]') {
      userIds = [userIds];
    }

    _.each(userIds, function(userId) {
      users.push(userMap[userId]);
    });
    return users;
  }

  /**
   * 获取一组或者一个部门所有上级信息包含当前
   *
   * @param {Array<String> | String}
   *
   * @return {Promise}
   */
  function getAllDeptSync(deptIds) {
    var allDepts = [],
      depts = getDeptSync(deptIds);
    allDepts = allDepts.concat(depts);
    _.each(depts, function(dept) {
      while(dept && dept.superId !== '0') {
        var deptId = dept.superId;
        dept = deptMap[deptId];
        if(dept) {
          allDepts.push(dept);
        }
      }
    });
    return allDepts;
  }

  /**
  * 获取指定部门下面的人员信息
  *
  * @param {String} 部门ID
  */
  function getSubUser(deptId) {
    return loadFromCache().then(function(users) {
      var subUsers = [];
      _.each(users, function(user) {
        if (!user.deptId) { return; }
        var deptIds = user.deptId.split(',');
        for (var i = 0, size = deptIds.length; i < size; i++) {
          if (deptIds[i] === deptId) {
            if (user.orderNo) {
              user.orderValue = parseInt(user.orderNo.split(',')[i]);
            }
            subUsers.push(user);
          }
        }
      });
      return subUsers;
    });
  }

  /**
  * 获取指定部门下面的部门信息
  *
  * @param {String} 部门ID
  */
  function getSubDept(deptId) {
    return loadFromDeptCache().then(function(depts) {
      var subDepts = [];
      _.each(depts, function(dept) {
        if (dept.superId === deptId) {
          subDepts.push(dept);
        }
      });
      return subDepts;
    });
  }

  /**
  * 获取指定部门下面的用户和部门信息
  *
  * @param {String} 部门ID
  */
  function getSubUserDept(deptId) {
    return $q.all([getSubUser(deptId), getSubDept(deptId)]);
  }

  function getAllUsers() {
    return allUsers;
  }

  function getAllDepts() {
    return allDepts;
  }

  function loadDataFromCache() {
    this.loadFromCache();
    this.loadFromDeptCache();
  }

  return {
    get: get,
    updateUser: updateUser,
    updateDept: updateDept,
    remove: remove,
    clearUser: clearUser,
    clearDept: clearDept,
    users: allUsers,
    depts: allDepts,
    getUserSync: getUserSync,
    getAllUsers: getAllUsers,
    getAllDepts: getAllDepts,
    getDept: getDept,
    getDeptSync: getDeptSync,
    getAllDeptSync: getAllDeptSync,
    getSubUser: getSubUser,
    getSubDept: getSubDept,
    getSubUserDept: getSubUserDept,
    loadFromCache: loadFromCache,
    loadFromDeptCache: loadFromDeptCache,
    loadDataFromCache: loadDataFromCache
  };
});
