if( ! Ice )
{

var Ice = new Object();
Ice.Strings = new Object();
Ice.Widget = new Object();

// *****************************************************************************
// * configuration object (singleton)
// *****************************************************************************

Ice.Conf = new function ()
{
  this.include_css       = new Array ("ext-all.css");
  this.include_pre_data  = new Array ("ext-base-debug.js","ext-all-debug.js","RowExpander.js","ice-bug.js","ice-messages.js");
  this.include_post_data = new Array ("ice-popup.js","ice-pages.js","ice-microsite.js");

  // Locations of widget resources
  this.Root       = "http://demos.ice-ol.com/";
  this.WidgetRoot = "http://demos.ice-ol.com/widget/v0/";
  this.ImgsRoot   = "http://demos.ice-ol.com/widget/v0/images/";
  
  var prepend = function (str, array)
  {
    for(var i = 0; i < array.length; i++)
    {
      array[i] = str+array[i];
    }
  }
  
  prepend(this.WidgetRoot, this.include_css);
  prepend(this.WidgetRoot, this.include_pre_data);
  prepend(this.WidgetRoot, this.include_post_data);
  
  this.MessagesRoot    = "http://v1.demo.ice-ol.com/Messages/";
  
  // the elemment to which Ice should attach
  this.IceClass = "ice-enabled";

} ();

// *****************************************************************************
// * util methods (singleton)
// *****************************************************************************

Ice.Utils = new function ()
{
  // ===========================================================================
  // = cookie access

  this.get_cookie = function (name)
  {
    //alert('heres the whole cookie: '+document.cookie);

    var crumbs = document.cookie.split('; ');

    for(var i = 0; i < crumbs.length; i++)
    {
      var kv = crumbs[i].split('=');

      if(kv[0] == name)
      {
        return kv[1];
      }
    }

    return false;
  }

  // ==============================================================================
  // = load functions (asynchronous)

  this.async_js_load = function (url)
  {
    var head = document.getElementsByTagName("head")[0];

    var new_js = document.createElement('script');
    new_js.setAttribute( 'type', 'text/javascript' );
    new_js.setAttribute( 'src',  url );

    head.appendChild(new_js);
  };

  this.async_css_load = function (url)
  {
    var head = document.getElementsByTagName("head")[0];

    var new_css = document.createElement('link');
    new_css.setAttribute( 'rel', 'stylesheet' );
    new_css.setAttribute( 'type', 'text/css' );
    new_css.setAttribute( 'href',  url );

    head.appendChild(new_css);
  };

} ();

// *****************************************************************************
// * chain loader (singleton)
// *****************************************************************************
// this allows synchronous loading of js plus a callback after it's all done
// also, this allows tracking of what is loaded
// note that all js loaded this way must have some chainloading code
//   (an if() statement surrounding all the code)

Ice.ChainLoader = new function ()
{
  this.chain = [];
  this.chain_done = true;

  this.load_chain = function (list, callback, callback_obj)
  {
    this.chain = list;
    this.chain_done = false;

    this.cb  = callback;
    this.cbo = callback_obj;

    this.next();
  };

  this.next = function ()
  {
    if( this.chain.length > 0 )
    {
      var link = this.chain.shift();

      //alert('starting to load '+link);

      Ice.Utils.async_js_load(link);
    }
    else
    {
      //alert('chain done');

      this.chain_done = true;

      this.cb(this.cbo);
    }
  };

  this.is_chain_done = function ()
  {
    return this.chain_done;
  };
  
  // ===========================================================================
  // = load tracking functions

  this.registered = new Array();

  this.register = function (id)
  {
    this.registered[id] = true;
  }

  this.is_registered = function (id)
  {
    if( this.registered[id] && this.registered[id] == true )
    {
      return true;
    }
    else
    {
      return false;
    }
  }

} ();

// *****************************************************************************
// * widget object
// *****************************************************************************

Ice.Widget = function ()
{
  this.init = function (ad_element)
  //this.init = function (ad_element, iid)
  {
    // ad on which this widget is attached
    this.ad  = ad_element;

    // id of the ad mapping to a specific set of widget content
    this.id  = this.ad.dom.getAttribute('ice-id');

    // id of this user-widget interation
    this.xid = ''+Ice.Utils.get_cookie('widgetIDSeed')+this.id+new Date().getTime()+Math.round(Math.random() * 1000000);
    //this.xid = iid;

    // collection of all "bugs" (little icon things)
    this.bugs = new Array();
    this.add_bug(ad_element);

    this.messenger = new Ice.Widget.Messages(this);
  }
  
  // this method adds a bug onto an element
  this.add_bug = function (ad_element)
  {
    var bug_obj = new Object();
    
    bug_obj.ad  = ad_element;
    bug_obj.id  = this.bugs.length;
    bug_obj.bug = new Ice.Widget.Bug(this, bug_obj);
    bug_obj.bug.init();
    
    this.bugs.push(bug_obj);
  }
  
  this.set_data = function (loaded_data)
  {
    this.data = loaded_data;
    
    if( ! this.data.language )
    {
      this.data.language = 'EN';
    }
    
    //if( this.data.resources && this.data.resources.js_onload )
    //{
    //  
    //}
  }
  
  this.process_data = function ()
  {
    this.lang = Ice.Strings[this.data.language];
    
    // each HTMLelement that a bug is associated with needs a popup too
    this.popups = new Array();
    for(var i = 0; i < this.bugs.length; i++)
    {
      var popup_obj = new Object();
      
      popup_obj.ad    = this.bugs[i].ad;
      popup_obj.popup = new Ice.Widget.Popup(this, popup_obj);
      popup_obj.popup.init();
      
      this.popups.push(popup_obj);
    }
    
    this.microsite = new Ice.Widget.Microsite(this);
    this.microsite.init();
  }

};

// *****************************************************************************
// * init functions
// *****************************************************************************

// hash containing all widgets on the page
Ice.widgets = new Object();

/* -----------------------------------------------------------------------------
 * step one of initializing ICE
 * load various css and some js prerequisites
 */ 
Ice.init_1 = function ()
{
  // load css
    for(var i = 0; i < Ice.Conf.include_css.length; i++)
    {
      Ice.Utils.async_css_load( Ice.Conf.include_css[i] );
    }
  
  // load pre-js
    Ice.ChainLoader.load_chain( Ice.Conf.include_pre_data, function (o) { o.init_2(); }, Ice );
}

/* -----------------------------------------------------------------------------
 * step two
 * init some Ext variables
 * find and tag all elements that wish to be
 * load post-js
 */
Ice.init_2 = function ()
{
  // init EXT
    Ext.BLANK_IMAGE_URL = Ice.Conf.ImgsRoot + 'default/s.gif';
    Ext.QuickTips.init();
    Ext.useShims = false;
    //Ext.form.Field.prototype.msgTarget = 'qtip';
    Ext.form.TextField.prototype.selectOnFocus = true;
    //Ext.form.TextField.prototype.grow = false;
    //Ext.form.TextField.prototype.xtype = 'textfield';
  
  // initialize initialization of widget objects
    // find all HTMLelements which need to be 'tagged'
    var divs = Ext.select('.'+Ice.Conf.IceClass, true);
    
    // for each, init a widget and store said widget so it can be easily referenced later
    for(var i = 0; i < divs.getCount(); i++)
    {
      var ice_element = divs.item(i);
      var ice_id      = ice_element.dom.getAttribute('ice-id');
      
      if( Ice.widgets[ice_id] )
      {
        Ice.widgets[ice_id].add_bug(ice_element);
      }
      else
      {
        var widget = new Ice.Widget();
        widget.init(ice_element);
        
        Ice.widgets[ice_id] = widget;
      }
    }
  
  // load post-js
    Ice.ChainLoader.load_chain( Ice.Conf.include_post_data, function (o) { o.init_3(); }, Ice );
}

/* -----------------------------------------------------------------------------
 * step 3
 * make all widgets on page query for their JSON data
 */
Ice.init_3 = function ()
{
  // start JSON call on all widget objects
    for(widget_key in Ice.widgets)
    {
      Ice.widgets[widget_key].messenger.data_message();
    }
}

/* -----------------------------------------------------------------------------
 * catch call-back from JSON
 * makes sure all JSON call-backs happen before proceeding
 * then loads all supplimental css + js
 */
Ice.init_data = function (id, data)
{
  // associate this data with its widget
  Ice.widgets[id].set_data(data);
  
  // now check to see if all data has been loaded
  // TODO: this part can be done better without the loop every time
  var all_data_loaded = true;
  
  for(widget_key in Ice.widgets)
  {
    if( ! Ice.widgets[widget_key].data )
    {
      all_data_loaded = false;
      break;
    }
  }
  
  if( all_data_loaded )
  {
    // load all individual widget resources
    // this includes language files as well as custom individual js and css
    
    // use a hash so that nothing gets loaded twice
    var css_resources_hash = new Object();
    var js_resources_hash  = new Object();
    
    for(widget_key in Ice.widgets)
    {
      var widget = Ice.widgets[widget_key];
      
      // widget language
      js_resources_hash[Ice.Conf.WidgetRoot+'ice-strings.'+widget.data.language+'.js'] = true;
      
      // extra widget css
      if( widget.data.resources )
      {
        if( widget.data.resources.css )
        {
          for( var i = 0; i < widget.data.resources.css.length; i++ )
          {
            css_resources_hash[widget.data.resources.css[i]] = true;
          }
        }
        
        // extra widget js
        if( widget.data.resources.js )
        {
          for( var i = 0; i < widget.data.resources.js.length; i++ )
          {
            js_resources_hash[widget.data.resources.js[i]] = true;
          }
        }
      }
    }
    
    // asynchronously load the css (can't load it any other way)
    for(resource in css_resources_hash)
    {
      Ice.Utils.async_css_load(resource);
    }
    
    // load-chain the js... js must be ChainLoader friendly!!
    var js_resources_array = new Array();
    for(resource in js_resources_hash)
    {
      js_resources_array.push(resource);
    }
    Ice.ChainLoader.load_chain( js_resources_array, function (o) { o.finish_init_data(); }, Ice );
  }
}

/* -----------------------------------------------------------------------------
 * after all js is loaded, start drawing all the widgets
 */
Ice.finish_init_data = function ()
{
  for(widget_key in Ice.widgets)
  {
    Ice.widgets[widget_key].process_data();
  }
}

// *****************************************************************************
// * onload hook
// *****************************************************************************

// back up old onload function so as to play nice
if( typeof onload == 'function' )
{
  Ice.oldonload = onload;
}
else
{
  Ice.oldonload = false;
}

if( Ice.oldonload )
{
  onload = function ()
  {
    Ice.oldonload();
    
    // start the load chain for the widget
    Ice.init_1();
  }
}
else
{
  onload = function ()
  {
    Ice.init_1();
  }
}

}
