
  /**
   * Module Arranger
   */
  var moduleOrganizer = function(){
    var addMdContainerId = 'addModuleContainer';
    var EMPTY_MODULE     = -1;
	  var sections         = new Array("group1", "group2");
    var addedModules     = new Array(new Array(), //for section 1
                                    new Array());              //for section 2
    
    var removedModules   = new Array(new Array(),   //for section 1
                                     new Array());  //for section 2
    
    var moduleTemplate   = new Template('<div id="item#{itemIndex}-#{moduleId}" class="lineitem section#{sIndex}" module_id="#{moduleId}">#{itemLabel}<em class="moduleDeleteBtn"><a id="item_#{moduleId}" href="javascript://" onclick="moduleOrganizer.removeModule(this, \'item#{itemIndex}-#{moduleId}\');" >X</a> </em><input type="hidden" value="Y" name="event_module_#{moduleId}"/></div>');
    var addMdTemplate    = new Template('<div id="item_#{moduleId}" class="addme addmeSection#{sectionIndex}" module_id="#{moduleId}" onclick="moduleOrganizer.addModule(this, #{sectionIndex},#{moduleIndex});">#{moduleLabel}</div>');
    
		return {
      
      /**
       * Function to set the modules data
       * @param {Hash} options :{
       *                           sections     :['aa_left', 'bb_right'],  // sections unique name(as ID)
       *                           addedModules :[[],[]],                  // section wise adding modules object Array
       *                           removedModules :[[],[]],                // section wise removed modules object Array
       *                         }
       */
      setModuleOrganizerData : function(options){
        try{
          options      = options.toObject() || {};
          sections     = options.sections || [];
          addedModules = options.addedModules || [];
          removedModules = options.removedModules || [];
          
          for(var i = 0, len = addedModules.length ; i < len; i++){
            var md = addedModules[i];
            var mdObjs = [];
            for(var j = 0, len1 = md.length ; j < len1; j++){
              mdObjs.push(this.getModuleObject(md[j]));
            }
            addedModules[i] = mdObjs;
          }
          
          for(var i = 0, len = removedModules.length ; i < len; i++){
            var md = removedModules[i];
            var mdObjs = [];
            for(var j = 0, len1 = md.length ; j < len1; j++){
              mdObjs.push(this.getModuleObject(md[j]));
            }
            removedModules[i] = mdObjs;
          }
        }catch(e){}
      },
      
      /**
       * Function to change the Module array to a hash object
       * @param {Object} moduleArr
       */
      getModuleObject : function(moduleArr){
        try{
          var module_name = this.getModuleName(moduleArr[0]);
          var moduleObj = {  
                            name : module_name,
                            partialName : moduleArr[1],
                            orderNumber : parseInt(moduleArr[2]),
                            sectionPosition : moduleArr[3],
                            isShow : (parseInt(moduleArr[4]) == 0 ? false : true),
                            id : parseInt(moduleArr[5])
                          };
          return moduleObj;
        }catch(e){}
      },
      /**
       * Function to initialize the module Arranger
       */
			init : function (){
				try{
          var s     = null;
          var md    = null;
          var mHtml = '';
          var itemIndex  = '';
          var moduleObj = null;
          
          //loop all sections
          for(var i=0, len = sections.length; i<len; i++){
            s = $(sections[i]);
            md = addedModules[i];
            
            //Add all modules for each section
            for(var j = 0, mLen = md.length; j < mLen; j++){
              moduleObj = md[j];
              itemIndex = "_" + i + "__" + j;
              
              mHtml     = moduleTemplate.evaluate({sIndex : new String(i), itemIndex : itemIndex, itemLabel : moduleObj.name, moduleId : moduleObj.id});
              //new Insertion.Bottom(s, mHtml);
              Element.insert(s,{
                bottom: mHtml
              })
            }
          }
          //Adding draggable functionality to all adding modules
          this.createModuleSortables();
          
          //creating removed modules
          this.refreshRemovedModules();
          
				}catch(e){}
			},
      
      //add a module to a section
      /**
       * Function to add a module in section
       * @param {Object} me      : clicked rlement ref
       * @param {Object} sIndex  : belonging section index
       * @param {Object} mdIndex : module index in removed module Array
       */
      addModule : function(me, sIndex, mdIndex){
        try{
          sIndex  = parseInt(sIndex);
          mdIndex = parseInt(mdIndex);
          
          //Removing the module object from the removed module Array
          var removedSection   = removedModules[sIndex];
          var moduleObject     = removedSection.splice(mdIndex, 1, EMPTY_MODULE)[0];
          var moduleName       = moduleObject.name;
          
          
          //Adding the module object in Add Module Array
          addedSection = addedModules[sIndex];
          addedSection.push(moduleObject);
          
          //Reassigning the new Arrays
          removedModules[sIndex] = removedSection
          addedModules[sIndex]   = addedSection;
          
          //Creating new element
          var s         = $(sections[sIndex]);
          var itemIndex = "_" + sIndex + "__" + (addedSection.length - 1);
          
          var mHtml     = moduleTemplate.evaluate({sIndex : new String(sIndex),itemIndex : itemIndex, itemLabel : moduleName, moduleId : moduleObject.id});
          
          //Inserting the element to dom
          //new Insertion.Bottom(s, mHtml);
          Element.insert(s,{
            bottom: mHtml
          })
          
          //to prevent multiple clicking on element, Removing onclick function from the clicked element
          me.onclick = function(e){};
          
          //Re-Initialize all modules
          this.destroyModuleSortables();
          this.createModuleSortables();
          
          var _self = this;
          var moduleToRemove = $(me);
              new Effect.Fade(moduleToRemove, {afterFinish : function(){moduleToRemove.remove();_self.setModuleOrder();}});
              //$('item_' + moduleObject.id).remove(); new Insertion.Bottom(s, mHtml);
          //Set the new module order
          this.setModuleOrder();
				}catch(e){}
      },
      
      //remove any module from a section
      /**
       * Function to remove the module from the added section
       * @param {Object} me    : Clicked element
       * @param {Object} modId : module id
       */
      removeModule : function(me, modId){
        try{
          //getting the section index and module index from the modId
          var sIndex  = modId.substring(modId.indexOf('_') + 1 , modId.indexOf('__'));
          var mdIndex = modId.substring(modId.indexOf('__')+ 2, modId.indexOf('-'));
          var addedSection = null, removedSection = null, moduleObject = null, moduleName = null;
          
          //Removing the module object from the added module Array
          addedSection   = addedModules[sIndex];
          moduleObject   = addedSection.splice(mdIndex, 1, EMPTY_MODULE)[0];
          moduleName     = moduleObject.name;
          //Adding the module object in Removed Module Array
          removedSection = removedModules[sIndex];
          removedSection.push(moduleObject);
          
          //Re-Initialize all modules
          removedModules[sIndex] = removedSection
          addedModules[sIndex]   = addedSection;
          
          //to prevent multiple clicking on element, Removing onclick function from the clicked element
          me.onclick = function(e){};

          var _self = this;
          //removing the module from the added section
          var moduleToRemove = $(modId);
              new Effect.Fade(moduleToRemove);
              new Effect.BlindUp(moduleToRemove, {afterFinish : function(){_self.insertIntoAddModule(new String(sIndex), new String(removedSection.length - 1), moduleName, moduleObject);  moduleToRemove.remove();_self.setModuleOrder();}} );
				}catch(e){}
      },
      
      /**
       * Function to set the draggable functionality to the elements
       */
      createModuleSortables : function(){
        try{
          //loop all sections
          for(var i = 0, len = sections.length; i < len; i++){
            //creating sortable object
            Sortable.create(sections[i] ,{tag:'div', only:'lineitem', overlap :'horizontal', constraint: false, onChange : function(){setTimeout(function(){moduleOrganizer.setModuleOrder();}, 100)} });//
          }
        }catch(e){}
      },
      
      /**
       * Function to removing the draggable functionality from the elements
       */
      destroyModuleSortables : function(){
        try{
          //loop all sections
          for(var i = 0, len = sections.length; i < len; i++){
            //creating sortable object
            Sortable.destroy(sections[i] ,{tag:'div', only:'lineitem'});
          }
        }catch(e){}
      },
      
      /**
       * Function to add the all removed modules in 'add more module section'
       */
      refreshRemovedModules : function(){
        try{
          var rMd = null;
          //loop all sections
          for(var i = 0, len = sections.length; i < len; i++){
            
            rMd = removedModules[i];
            //Add all removed modules for each section
            for(var j = 0, mLen = rMd.length; j < mLen; j++){
              var moduleObject = rMd[j];
              if(moduleObject != EMPTY_MODULE){
                this.insertIntoAddModule(new String(i), new String(j), moduleObject.name, moduleObject);  
              }else{
                //TODO:clean the empty modules from array
              }
            }
          }
          //Set the new module order
          this.setModuleOrder();
          
        }catch(e){}
      },
      /**
       * Function to create and insert the module in 'add more module section'
       * @param {Object} sectionIndex  : section index
       * @param {Object} moduleIndex   : module index
       * @param {Object} moduleLabel   : module name
       * @param {Object} moduleObj     : module object
       */
      insertIntoAddModule : function(sectionIndex, moduleIndex, moduleLabel, moduleObj){
         try{
           var container = $(addMdContainerId);
           var html      = addMdTemplate.evaluate({sectionIndex : sectionIndex, moduleIndex : moduleIndex, moduleLabel : moduleLabel, moduleId : moduleObj.id});
           var br        = this.addMdBr ? this.addMdBr : (this.addMdBr = container.getElementsByTagName('BR')[0]);
           //new Insertion.Before(br, html);
           Element.insert(br,{
             before: html
           })
         }catch(e){}
      },
      
      /**
       * Function to set the module order on the elements
       */
      setModuleOrder: function() {
        try{
      		var alerttext = '';
          var allSections = [];
          for(var i = 0, len = sections.length; i < len; i++){
            allSections.push($(sections[i]));
          }
      		allSections.each(function(section) {
      			var sectionID = section.id;
      			var orders = Sortable.sequence(section);
            var newModuleOrder = [];
            orders.each(function(moduleId){
              newModuleOrder.push(moduleId.substring(moduleId.indexOf('-')+1));
            });
            $("section_" + sectionID).value = newModuleOrder.toString();
      			//alerttext += sectionID + ': ' + orders +"\n===\n newModuleOrder :" + newModuleOrder + "\n--\n" ;
      		});
        }catch(e){}
    	},
      getModuleName : function(module_name){
        try{
          var tempname = module_name.toLowerCase();
              if(tempname.indexOf("event") != -1 ){
                tempname = tempname.replace(/event/g, g_event_label);
              }
          return tempname.capitalize();
        }catch(e){}
      }
      
      
		}//End of function return
	}();

  