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

module.constant('AppModules', AppModules)
  .constant('ModuleItem', ModuleItem);

function AppModules() {
  this.allModules = []; // 存放所有模块
  this.modules = []; // 存放有效模块
  this.moduleMap = {};
  this.moduleMapWithModuleIdKey = {};
  this.stachChildren = {};
  this.authVisibile = {};
}

AppModules.prototype = {

  /**
   * 新增一个module
   */
  add: function(moduleConfig) {
    var moduleItem = new ModuleItem(moduleConfig),
      parent = moduleItem.parent? this.getByModuleName(moduleItem.parent) : null;
    if (moduleItem.parent && !parent) {
      this.stashChildModule(moduleItem);
    } else {
      if (parent) {
        parent.add(moduleItem);
      }
      this.addModuleItemToModules(moduleItem);
      this.applyStash(moduleItem);
    }
    if (moduleItem.moduleId) {
      moduleItem.setAuthVisible(this.authVisibile[moduleItem.moduleId]);
    }
  },

  /**
   * 向allModules添加moduleConfig
   */
  addToAll: function(moduleConfig) {
    this.allModules.push(moduleConfig);
  },
  
  /**
   * 从所有的配置中获取mduleConfig
   */
  getModuleConfig: function(moduleName) {
    for(var i=0, len = this.allModules.length; i<len; i++) {
      if(this.allModules[i].moduleName === moduleName) {
        return this.allModules[i];
      }
    }
  },

  delete: function(moduleName) {
    /**
     * todo
     * 多级时的删除
     */
    var index;
    for(var i=0, len = this.modules.length; i<len; i++) {
      if(this.modules[i].moduleName === moduleName) {
        index = i;
      }
    }
    if(_.isEmpty(index) || index == -1) {
      return;
    }
    this.modules.splice(index, 1);
    delete this.moduleMap[moduleName];
  },

  applyAuthVisible: function(authVisible) {
    if (typeof authVisible !== 'object') {
        return;
    }

    this.authVisibile = authVisible || {};
    if (authVisible) {
      var moduleId, moduleAuthVisible,
        moduleItem;
      for (moduleId in authVisible) {
        if (authVisible.hasOwnProperty(moduleId)) {
          moduleAuthVisible = authVisible[moduleId];
          moduleItem = this.getByModuleId(moduleId);
          if (moduleItem) {
            moduleItem.setAuthVisible(moduleAuthVisible);
          }
        }
      }
    }
  },

  getByModuleId: function(moduleId) {
    return this.moduleMapWithModuleIdKey[moduleId];
  },

  getModuleIds: function() {
    var moduleIds = [];
    _.each(this.modules, function(module) {
      if(!_.isEmpty(module.moduleId)) {
        moduleIds.push(module.moduleId);
      }
    });
    return moduleIds;
  },

  getByModuleName: function(moduleName) {
    return this.moduleMap[moduleName];
  },

  getModuleByFlowType: function(typeId) {
    var module;
    for (var i = 0, len = this.modules.length; i < len; i++) {
      module = this.modules[i];
      if(module.flowType == typeId) {
        return module;
      }
    }
    return null;
  },

  update: function(moduleName, moduleConfig) {
    var module = this.getByModuleName(moduleName);
    if(module) {
      if (module.moduleName != moduleConfig.moduleName  && moduleConfig.moduleName) {
        this.updateModuleMap(module, moduleConfig.moduleName);
      }

      if (module.moduleId != moduleConfig.moduleId  &&  moduleConfig.moduleId) {
        this.updateModuleMapWithModuleIdKey(module, moduleConfig.moduleId);
      }

      module.update(moduleConfig);

    } else {
      this.add(moduleConfig);
    }
  },

  updateModuleMap: function(moduleItem, moduleName) {
    delete this.moduleMap[moduleItem.moduleName];
    this.moduleMap[moduleName] = moduleItem;
  },

  updateModuleMapWithModuleIdKey: function(moduleItem, moduleId) {
    delete this.moduleMapWithModuleIdKey[moduleItem.moduleId];
    this.moduleMapWithModuleIdKey[moduleId] = moduleItem;
  },

  /**
   * 暂存二级模块。
   *
   * @param  {ModuleItem} moduleItem 某个二级模块。
   */
  stashChildModule: function(moduleItem) {
    if (!this.stachChildren[moduleItem.parent]) {
      this.stachChildren[moduleItem.parent] = [];
    }

    this.stachChildren[moduleItem.parent].push(moduleItem);
  },

  /**
   * 应用暂存的moduleItem模块的二级模块。
   *
   * @param  {ModuleItem} moduleItem 父模块
   */
  applyStash: function(moduleItem) {
    var stashedChildren = this.stachChildren[moduleItem.moduleName];
    var childModuleItem;
    if (stashedChildren) {
      for (var i = 0, len = stashedChildren.length; i < len; i++) {
        childModuleItem = stashedChildren[i];
        moduleItem.add(childModuleItem);
        this.addModuleItemToModules(childModuleItem);
      }
      delete this.stachChildren[moduleItem.moduleName];
    }
  },

  /**
   * 计算moduleItem将要插入modules的数组位置。
   *
   * @param  {ModuleItem} moduleItem 模块
   * @return {Integer} 返回位置。
   */
  calcIndex: function(moduleItem) {
    var parent = moduleItem._parent,
      idx = -1;

    if (parent) {
      var siblingRange = this.getChildrenModuleItemsRange(parent);
      idx = AppModules.calcModuleIndex(this.modules, moduleItem,
        siblingRange.begin, siblingRange.end);
    } else {
      idx = AppModules.calcModuleIndex(this.modules, moduleItem);
    }
    return idx;
  },

  /**
   * 向模块列表中有序的加入模块
   * @param {ModuleItem} moduleItem 模块
   */
  addModuleItemToModules: function(moduleItem) {
    var index = this.calcIndex(moduleItem);
    if (index >= 0) {
      this.modules.splice(index, 0, moduleItem);
    }

    this.moduleMap[moduleItem.moduleName] = moduleItem;
    if (moduleItem.moduleId) {
      this.moduleMapWithModuleIdKey[moduleItem.moduleId] = moduleItem;
    }
  },

  /**
   * 获取一个模块的子模块在modules数组中的开始结束位置。
   *
   * @param  {ModuleItem} moduleItem 模块
   * @return {Range}            返回子模块所在的区域
   */
  getChildrenModuleItemsRange: function(moduleItem) {
    var module,
      begin = -1,
      end = -1;
    for (var i = 0, len = this.modules.length; i < len; i++) {
      module = this.modules[i];
      if (moduleItem === module) {
        begin = i + 1;
      } else if (begin >= 0 && module._parent !== moduleItem) {
        end = i;
        break;
      }
    }

    if (begin >= 0 && end === -1) {
      end = this.modules.length;
    }

    return {begin: begin, end: end};
  }
};

/**
 * 计算即将加入modules中的moduleItem的位置。
 *
 * @param  {ModuleItem[]} modules  模块数组
 * @param  {ModuleItem} moduleItem 模块
 * @param  {Number} begin      数组开始检索的位置
 * @param  {Number} end        数组结束检索的位置
 * @return {Number}            返回数组位置，如果不存在，则返回-1。
 */
AppModules.calcModuleIndex = function(modules, moduleItem, begin, end) {
  var module,
    hasOrderProperty = moduleItem.hasOwnProperty('order'),
    top = moduleItem._level_top;
  begin = begin || 0;
  end = end || modules.length;

  if (!hasOrderProperty) {
    return end;
  } else {
    for (var i = begin; i < end; i++) {
      module = modules[i];

      if ((top && !module._level_top) ||
        (module.hasOwnProperty('order') && module.order <= moduleItem.order)) {
        continue;
      } else {
        return i;
      }
    }

    return end;
  }
};

function ModuleItem(moduleConfig) {
  _.apply(this, moduleConfig);
  this._moduleConfig = moduleConfig;

  this._children = [];//该模块的子结点
  this._leaf = true;//该模块是否是叶子结点
  this._open = false;//默认所有的模块都关闭
  this._hidden = false;//默认都展示
  this._showByAuth = true;//通过权限控制--默认都显示
  this._level_top = !this.parent;
  this._authVisible = true;
}

ModuleItem.prototype = {
  /**
   * 添加子模块
   *
   * @param {ModuleItem} module
   */
  add: function(module) {
    this._children.push(module);
    this._leaf = false;
    module._parent = this;
    module._level_top = false;
    this.calcVisible();
    module.calcVisible();
  },

  /**
   *
   */
  update: function(moduleConfig) {
    _.apply(this, moduleConfig);
    _.apply(this._moduleConfig, moduleConfig);
  },

  /**
   * 设置权限可见性
   *
   * @param {Boolean} visible 权限可见性
   */
  setAuthVisible: function(visible) {
    var changed = this._authVisible !== visible;
    this._authVisible = visible;

    if (changed) {
      this.triggerParentCalcVisibile();

      this.calcVisible();

      this.triggerChildrenCalcVisible();
    }
  },

  /**
   * 顶级菜单打开，子菜单也显示
   */
  open: function() {
    this._open = true;
    _.each(this._children, function(child) {
      child.calcVisible();
    });
  },

  /**
   * 顶级菜单关闭，子菜单也不显示
   */
  close: function() {
    this._open = false;
    _.each(this._children, function(child) {
      child.hide();
    });
  },

  show: function() {
    this._hidden = !this._authVisible;
  },

  hide: function() {
    this._hidden = true;
    if (this._children) {
      for (var i = 0, len = this._children.length; i < len; i++) {
        this._children[i].hide();
      }
    }
  },

  triggerParentCalcVisibile: function() {
    if (this._parent) {
      this._parent.calcVisible();
    }
  },

  triggerChildrenCalcVisible: function() {
    if (this._children) {
      for (var i = 0, len = this._children.length; i < len; i++) {
        this._children[i].calcVisible();
      }
    }
  },

  /**
   * 计算模块的可见性
   *
   */
  calcVisible: function() {
    if (this._authVisible) {
      if (this._leaf) {
        if (this._level_top) {
          this.show();
        } else if (this._parent) {
          if (this._parent._hidden) {
            this.hide();
          } else if (this._parent._open) {
            this.show();
          } else {
            this.hide();
          }
        }
      } else {
        if (this._children) {
          var visible = false;
          for (var i = 0, len = this._children.length; i < len; i++) {
            if (this._children[i]._authVisible) {
              visible = true;
              break;
            }
          }
          if (visible) {
            this.show();
          } else {
            this.hide();
          }
        }
      }
    } else {
      this.hide();
    }
  }
};
