// Gaia Ajax Copyright (C) 2008 - 2009 Gaiaware AS. details at http://gaiaware.net/

/* 
 * Gaia Ajax - Ajax Control Library for ASP.NET
 * Copyright (C) 2008 - 2009 Gaiaware AS
 * All rights reserved.
 * This program is distributed under either GPL version 3 
 * as published by the Free Software Foundation or the
 * Gaia Commercial License version 1 as published by
 * Gaiaware AS
 * read the details at http://gaiaware.net
 */

/* ---------------------------------------------------------------------------
   Class basically wrapping the common functions of Container Widgets 
   (Window, Panel, MultiView, ViewportView etc)
   --------------------------------------------------------------------------- */

// Don't need a "full" (prototype) class here since no initialization is done in this class...
Gaia.Container = function(){}

Gaia.Container.prototype = {

  setEnabled: function(value, skipChildren) {
    if (this.setSelfEnabled)
        this.setSelfEnabled(value);
    if (!skipChildren)
      this._getChildControls().select(function(child) { return child.setEnabled; }).invoke('setEnabled', value, true);
    return this; 
  },
  
  storeEnabled: function(value, skipChildren) {
    if (this.storeSelfEnabled)
        this.selfEnabledState = this.storeSelfEnabled();
    if (!skipChildren)
        this._getChildControls().select(function(child) { return child.storeEnabled; }).invoke('storeEnabled', value, true);
  },
  
  restoreEnabled: function(value, skipChildren) {
    if (this.restoreSelfEnabled)
        this.restoreSelfEnabled(this.selfEnabledState);
    if (!skipChildren)
        this._getChildControls().select(function(child) { return child.restoreEnabled; }).invoke('restoreEnabled', value, true);
  },

  // Called when user has choosen to do a "ForceAnUpdate" on the server side
  // Basically just makes sure ALL child controls are DESTROYED before the re-rendering
  // of the innerHTML of the control
  forceAnUpdate: function(){
    this.destroyContainer();
    this.forceUpdateOfAspects();
  },

  forceUpdateOfAspects: function(){
    if( this.options.aspects ){
      for( var idx=0, length = this.options.aspects.length; idx < length; ++idx ) {
        this.options.aspects[idx].forceAnUpdate();
      }
    }
  },

  appendHtml: function(html) {
    this._appendHtml(this.getBody(), html);
    return this;
  },
  
  getBody: function() {
    var ctrl = $(this.element.id + "_content");
    if (!ctrl) ctrl = this.element;
    return ctrl;
  },
  
  _appendHtml: function(control, html) {
    var el = new Element('div');
    el.innerHTML = html;
    var children = el.childNodes;
    
    while (children.length > 0)
      control.appendChild(children[0]);
  },

  // destructor. override this one in derived objects
  destroyContainer: function(){
     this._destroyChildControls();
  },
  
  // Called AFTER the forceAnUpdate AND the "new innerHTML" has been set....!!!
  // Basically just "re-inits" the DOM reference to the physically new DOM element (though
  // with the same ID)
  reInit: function(){
    this._reInit();
  },
  
  _reInit: function(){
     // Since DOM element physically has been REMOVED and then ADDED again we run the initialization again...
    // Note that the Control reference doesn't need to be "re-initialized" since it contains a reference to
    // the Gaia object on the "element.id" hash value...
    // Only the "this.element" needs to be re-initialized
    this.element = $(this.element.id);

    if( this.options.aspects ){
      for( var idx=0, length = this.options.aspects.length; idx < length; ++idx ) {
        this.options.aspects[idx].reInit();
      }
    }
  },
  
  _getChildControls: function() {
    var children = $A([]);
    var searchString = this.getControlId() + "_";
    
    // get all visible and invisible controls
    var controls = Gaia.Control._registeredControls.values();
    
    for (var index = 0, length = controls.length; index < length; ++index) {
      var control = controls[index];
      if (control.getControlId().indexOf(searchString) !== 0) continue;
      children.push(control);
    }
    
    return children;
  },
  
  _destroyChildControls: function() {
    var searchString = this.getControlId() + "_";
    
    // get all visible and invisible controls
    var controls = this._getChildControls();
    
    // collect items to destroy
    var destroyables = $H({});
    for (var index = 0, length = controls.length; index < length; ++index) {
        var id = controls[index].getControlId();
        if (destroyables.get(id.length) == null)
          destroyables.set(id.length, new Array());
        destroyables.get(id.length).push(id);
    }

    // destroy collected items
    var keys = destroyables.keys().sort(function(a, b) { return b - a;  });
    for(var index = 0, length = keys.length; index < length; ++index) {
        var controls = destroyables.get(keys[index]);
        
        for(var idx = 0, len = controls.length; idx < len; ++idx) {
            var id = controls[idx];
            var control = $G(id);
            if (control != null)
                control.destroy();
        }
    }
  }
};

Gaia.Container.browserFinishedLoading = true;
