function SGBase() {
}

SGBase.prototype = {
	/*****************
	 *
	 * A list of code to execute at init() time
	 *
	 ****************/
	__initItems: [],
	/*****************
	 *
	 * Do whatever it takes to debug
	 *
	 ****************/
	debug: function (str) {
		if(true) { return false; }
		alert(str);
	},
	/*****************
	 *
	 * Do the init, this should be called on body onload, or at least after the Dom is loaded
	 *
	 ****************/
	init: function () {
		this.debug('doing init');

		var key = -1, undefined;
		while (this.__initItems[++key] !== undefined) {
			switch (typeof(this.__initItems[key])) {
				case 'object':
					if (this.__initItems[key].init) { this.__initItems[key].init(); }
					else { this.debug('Object has no init function'); }
				break;
				case 'function':
					this.__initItems[key]();
				break;
				default: eval(this.__initItems[key]); break;
			}
		}

	},
	/*****************
	 *
	 * Add something to execute during the init phase
	 *
	 ****************/
	addInit: function (item) {
		this.__initItems.push(item);
	},
	/*****************
	 *
	 * Wrapper functions for whatever js toolkit, prototype, etc
	 *
	 ****************/
	$: function (id) {return document.getElementById(id); }
};

var SG=new SGBase();

/******
 *
 *  Javascript module providing menu functionality to a UL
 *  SeatGuru only has one menu using this functionality, but
 *  this is designed to be able to operate on many if needed
 *
 ******/


function SGMenu(factory, id) {
	this.factory = factory;
	this.id = id;
}

/****
 *
 *  The inherent methods of any menu
 *
 *****/
SGMenu.prototype = {
	id: null,
	activeSection: null,
	init: function () {
		var menuElement, liList, li, innerUl, innerList, thisLink, menuObj, innerLi;

		menuElement = SG.$(this.id);
		liList = menuElement.getElementsByTagName('li');

		//to pass into the function to avoid closure conflict
		menuObj = this;

		li = -1, undefined;
		while (liList[++li] !== undefined) {
			//look for top level LIs
			if (liList[li].parentNode==menuElement) {
				innerUL = liList[li].getElementsByTagName('ul');
				if (innerUL) innerUL = innerUL[0];

				//look for an inner list.  If so, make it togglable too.
				if (innerUL) {
					//the 'this' inside the onlink function will refer to the clicked element
					//the menuObj refers to the SGMenu class or the "this" you might be thinking of
					liList[li].getElementsByTagName('a')[0].onclick=function (){menuObj.handleSectionClick(this,true); return false; }

					//there can be only one
					innerList = innerUL.getElementsByTagName('li');

					innerLi = -1, undefined;
					while (innerList[++innerLi] !== undefined) {
						//look for second level LIs
						if (innerList[innerLi].parentNode==innerUL) {
							//the this inside the onlink function will refere to the clicked element
							//the menuObj refers to the SGMenu class or the "this" you might be thinking of
							thisLink = innerList[innerLi].getElementsByTagName('a')[0];
							if (innerList[innerLi].getElementsByTagName('li').length > 0) thisLink.onclick=function (){menuObj.handleSectionClick(this,false); return false; }

						}
					}
				}

			}
		}
	},

	/*****************
	 *
	 * This is the click handler for the links used to toggle sections
	 *
	 ****************/

	handleSectionClick: function (link,isTopLevel) {
		sectionLI = link.parentNode;
		this.toggleSection(sectionLI, isTopLevel);
	},

	toggleSection: function (sectionLi,isTopLevel) {
		var ul, ulList, undefined, oldMode;

		if (isTopLevel && this.activeSection && (this.activeSection != sectionLi)) {this.toggleSection(this.activeSection,true); }

		//there should only be one ul at the root here
		ulList = sectionLi.getElementsByTagName('ul');

		ul = -1;
		while (ulList[++ul] !== undefined) {

			if (ulList[ul].parentNode == sectionLi) {
				oldMode = ulList[ul].style.display;

				ulList[ul].style.display = oldMode=='block'?'none':'block';

				if (isTopLevel) {
					if (ulList[ul].style.display == 'block') {
						this.activeSection = sectionLi;
						sectionLi.className = 'sectionActive';

					}
					else {
						this.activeSection = null;
						sectionLi.className = 'section';
					}
				}
				break;
			}
		}

	}
};

//add menu constructors to them main SG object heirarchy
//this would ideally be done as needed via some lazy loader mechanism
SG.Menu = {

	/**************
	 *  return a newly instantiated Menu object
	 *  takes the id of a UL
	 **************/
	create : function (id) {
		return new SGMenu(this, id);
	},

	/**************
	 * Instantiate a menu object and add it to the init list
	 **************/
	add : function (id) {
		myMenu = this.create(id);
		SG.addInit(myMenu);
	}
}



function SGCookie() {
}

SGCookie.prototype = {
	set: function (name,value,minutes) {
		var expires = "", date;
		if (minutes) {
			date = new Date();
			date.setTime(date.getTime()+(minutes*60*1000));
			expires = ";expires="+date.toGMTString();
		}
		document.cookie = name+"="+value+expires+";domain=.seatguru.com;path=/";
	},
	get: function (name) {
		var start, end, value, pos = document.cookie.indexOf(name + '=');
		if (pos !== -1)
		{
			start = pos + name.length + 1;
			end = document.cookie.indexOf(';', start);
			if (end === -1)
			{
				end = document.cookie.length;
			}
			value = document.cookie.substring(start, end);
			return value;
		}
	
		return '';

	},
	remove: function (name) { }
};

SG.Cookie = new SGCookie();

//controller for popups/unders
function SGPop(page, props) {

	this.page = page;

	//optional hargs
	props = props || {};
	this.toolbar     = props.toolbar     || 0;
	this.location    = props.location    || 0;
	this.directories = props.directories || 0;
	this.status      = props.status      || 0;
	this.menubar     = props.menubar     || 0;
	this.scrollbar   = props.scrollbar   || 0;
	this.resizable   = props.resizable   || 0;
	this.height      = props.height      || null;
	this.width       = props.width       || null;
	this.winHandle   = props.winHandle   || '';

	//a function that returns true if the popup should happen, false otherwise
	this.trigger     = props.trigger     || null;

	//a callback function that happens after the pop (only if pop)	
	this.callback    = props.callback    || null;
}


//a commonly used callback, here for convenience
SGPop.popUnder = function () {
	this.win.blur();
	if (this.moveTo) {
		this.win.moveTo(0, 0);
	}
};

//creates and returns a function that acts as a popup trigger. 
//the returned function returns true or false if the popup should launch
SGPop.getPopTriggerFn = function (props) {
	props = props || {};
	props.flagName  = props.flagName || 'sgPop';
	props.flagTTL   = props.flagTTL   || null;
	//only do the trigger on the nth time (counted via cookies)
	props.triggerAt = props.triggerAt || 0;
	//see if we even care about logic
	props.useCookie = props.useCookie || true;

	ret = function () {

		var ct;

		if (document.referrer&&document.referrer!="") {
			if(document.referrer.indexOf('google.com') > -1) return false;
		}

		if (!props.useCookie) {
			return true;
		}

		if (!(ct = SG.Cookie.get(props.flagName))) {
			ct = 0;
		}

		//increments and casts to int
		ct = ++ct;

		SG.Cookie.set(props.flagName,ct,props.flagTTL);

		//was a specific trigger count specified?
		if (props.triggerAt) {

			//see if it's time to trigger
			return ct === props.triggerAt;

		}

		//in none specified, always trigger
		return true;

		return false;
	}

	return ret;
}


SGPop.prototype = {

	//the actual window	
	win: null,

	init: function () {
		//if no trigger, then pop with no conditions
		if (null === this.trigger || this.trigger()) {
			this.doPop();
		}
	},

	doPop: function () {

		this.win = window.open(this.page, this.winHandle, this.getWinParamString());

		if (this.win) {

			if (null !== this.callback) {
				this.callback();
			}

		}

	},

	getWinParamString: function () {

		var ret;
		ret =  'toolbar=' + this.toolbar + ',location=' + this.location + ',directories=' + this.directories + ',status=' + this.status;
		ret += ',menubar=' + this.menubar + ',scrollbars=' + this.scrollbars + ',resizable=' + this.resizable;

		if (this.height) {
			ret += ',height=' + this.height;
		}

		if (this.width) {
			ret += ',width=' + this.width;
		}

		return ret;

	}

};

//add the object, not an instance
//This should be thought of as 'static'

//var mySTPopInstance = new SG.Pop({all my params})
//instances are passed in via: SG.addInit(mySTPopInstance);
SG.Pop = SGPop;


function SGFlightsWidget (id, props) {

	this.id = id;

	props = props || {};

	/* The handle given to the new window, so all searches share the same one */
	this.winHandle          = props.winHandle          || 'BBWin';
	this.locationCookieName = props.locationCookieName || 'BBLocationCode';
	this.locationCode       = props.locationCode       ||  null;

	this.validModes = props.validModes || ['air','hotel','car','vacation'];

	this.defaultMode = props.defaultMode || 'air';


	//target url for each search mode
	this.modeUrls   = props.modeUrls   || {};

	//target referal tag for each search mode
	this.modeReferrers  = props.modeReferrers   || {};

	//overrides for header that goes above tabs
	this.modeHeaders  = props.modeHeaders   || {};

}

SGFlightsWidget.prototype = {

	mode : null,

	launchSearch : function ()
	{
		var w = window.open('about:blank',this.winHandle);
		f.target = this.winHandle;
		w.focus();
		return true;
	},


	displayCompareForm : function (mode) {

		try {
			document.getElementById(this.id).className = mode;
			SG.$('widgetHeader').innerHTML = this.getHeaderText(mode);
		}

		//no such mode, do nothing
		catch(err) {;}

		return;
	},


	init: function () {

		if(null !== this.locationCode) SG.Cookie.set(this.locationCookieName, this.locationCode );

		if((top != self)){top.location.replace(self.location.href);};

		this.initModes();

		this.displayCompareForm(this.defaultMode);

	},

	/***
	*
	* Set up each mode, urls for forms, and all that mechanical stuff
	*
	***/
	initModes : function() {

		for(key in this.validModes) {  
			if(this.validModes.hasOwnProperty(key)) {  
				this.initMode(this.validModes[key]);
			}  
		} 

	},


	initMode : function (mode) {
		var widget, changeTabs;
		tabLink = SG.$(mode + '_widget_tab').getElementsByTagName('a')[0];

		widget = this;
		changeTabs = function(){ widget.displayCompareForm(mode); };
		tabLink.onclick = function(){
			changeTabs();
			return false;
		};

		this.setModeUrl(mode);
		this.setModeReferrer(mode);

	},

	setModeUrl : function (mode) {
		var f;

		f = SG.$(mode + '_widget_form');
		f.target = this.winHandle;

		if(this.modeUrls[mode] !== undefined) {
			f.action = this.modeUrls[mode];
		}
	},

	setModeReferrer : function (mode) {
		var f;

		f = SG.$(mode + '_widget_form');

		if(this.modeReferrers[mode] !== undefined) {
			f.r.value = this.modeReferrers[mode];
		}
	},


	/* returns the string that appears above the tabs */
	getHeaderText : function (mode) {

		if(this.modeHeaders[mode] !== undefined) {
			return this.modeHeaders[mode];
		}


		switch(mode) {
			case 'air':
				return 'Find Cheap Flights!';
				break;
			default:
				return 'Find ' + mode.charAt(0).toUpperCase() + mode.substr(1) + 's for less';

		}

	}


};

SG.FlightsWidget = {
	/**************
	 *  return a newly instantiated Widget object
	 *  takes the id of a UL
	 **************/
	create : function (id, props) {
		return new SGFlightsWidget(id, props);
	},

	/**************
	 * Instantiate a menu object and add it to the init list
	 **************/
	add : function (id, props) {
		myWidget = this.create(id, props);
		SG.addInit(myWidget);
	}
};

var ifminheight = 245;
// Function used to update the height of the iframe, the child calls this as needed.
function air_updateFrame(shorten, height) {
	var kid = document.getElementById('air_frame');
	if (shorten) {
		kid.height = ifminheight + 'px';
	}
	else if (height > ifminheight) {
		kid.height = height + 'px';
	}
	// update outer overlay
	var overlay = document.getElementById("hideOuter");
	if (overlay) {
		overlay.style.height = air_getHeight() + "px";
	}
}

function air_getHeight() {
	// browser checks lifted from moo-tools
	if (window.ActiveXObject) { // IE
		return Math.max(document.documentElement.offsetHeight,document.documentElement.scrollHeight);
	} else if (document.childNodes && !document.all && !navigator.taintEnabled) { // webkit
		return document.body.scrollHeight;
	} else { // everything else
		return document.documentElement.scrollHeight;
	}
}

function air_hideOuter() {
	var overlay = document.getElementById("hideOuter");
	var bod = document.getElementsByTagName('body')[0];
	if (!overlay) {
		overlay = document.createElement("div");
		overlay.id = "hideOuter";
       var style = "\
 position:absolute;         \
 top:0; left:0;             \
 width:100%;                \
 background-color:#000;     \
 -moz-opacity: 0.5;         \
 opacity:.50;               \
 filter: alpha(opacity=50); \
 display: none              \
";
       overlay.style.cssText = style;
       bod.appendChild(overlay);
	}
	var lightbox = document.getElementById('lightbox');
	if (!lightbox) {
		lightbox = document.createElement("div");
		lightbox.id = "lightbox";
       lightbox.style.cssText = "\
   position: absolute;\n\
   display: none;\n\
";
       bod.appendChild(lightbox);
	}
	if (overlay) {
		overlay.style.height = air_getHeight() + "px";
		overlay.style.display = "block";
	}
}

function air_showOuter() {
	var overlay = document.getElementById("hideOuter");
	if (overlay) {
		overlay.style.display = "none";
	}
}
