// singletone for controls handling
(function(){

//private properties
var instance = null;
var controls = {};
var sm = null;

//private methods
var deleteControl = function(id) {
      
      var c = controls[id];
      if (!c) return false;
      
      //removing child controls
      for (var key in c._controls) 
        deleteControl(c._controls[key]._id);
      
      //updating parent control
      var p = this._parentControl;
      if (p)
        delete p._controls[c._name];
      
      //removing control from internal list
      delete controls[id];
        
      //calling internal destructor
      c.__destruct();
    }

this.ControlsManager = Class.create({
  
  getInstance:function(){
    if (instance === null)
      throw Error("ControlsManager instance still not created");
    return instance;
  }
  
},{
  
  __construct:function(){
    
    if (instance !== null)
      throw Error("Only one instance of ControlsManager class allowed (ControlsManager is singletone)");
      
    instance = this;
    sm = new ScriptManager();
    this.declareEvent('preInit','init','postInit');
    setTimeout(this.getHandler(this.initialize),0);
    
  },
  
  initialize:function(){
    
    this.dispatchEvent('preInit');
    this.initControls(controls);
    this.dispatchEvent('postInit');
       
    delete this['initialize'];
    
  },
  
  
  initControls:function(controls){
    
    for (var key in controls) {
      if (controls[key] && controls[key].preInit && controls[key].preInit.constructor === Function)
        controls[key].preInit();
    }
    
    for (var key in controls) {
      if (controls[key] && controls[key].initialize && controls[key].initialize.constructor === Function)
        controls[key].initialize();
    }
    
    for (var key in controls) {
      if (controls[key] && controls[key].postInit && controls[key].postInit.constructor === Function)
        controls[key].postInit();
    }
    
  },
  
  addControl:function(id, control) {
    if (controls[id] !== undefined)
      throw new Error("Control with id '" + id +"' already exists.");
    
    return controls[id] = control; 
  },
  
  getControl:function(id) { 
    return controls[id];  
  },
  
  addAjaxControl:function(data,callback){
    
    //collecting all scripts
    var scripts = [];
    for (var i=0, l=data.length; i<l; i++){
      if (data[i].scripts.constructor === Array)
        scripts = Array.prototype.concat.apply(scripts,data[i].scripts);
    }
    
    
    var onScriptsLoaded = function(){
      
      //removing existent controls
      for (var i=0, l=data.length; i<l; i++){
        deleteControl(data[i].id);
      }
      
      //initializing new controls
      var controls = {}, c = null;
      
      for (var i=0, l=data.length; i<l; i++){
        var hash = data[i];
        c = new window[hash.className](hash.clientArgs);
        instance.addControl(hash.id, c);
        controls[hash.id] = c;
      }
      
      instance.initControls(controls);
      
      //refreshing parent's reference to control itself
      for (var key in controls){
        var c = controls[key];
        if (c._parentControl)
          c._parentControl._controls[c._name] = c;
      }
      
      if (callback && typeof callback === "function")
        callback();
      
    }
    
    //calling scripts loaded handler
    sm.loadScripts(scripts,onScriptsLoaded);
    
  }
  
  
  
  
},[Event]);

})();