var safire = {
	disallow: false,
	device_id: false,
	ver: "2.0",
	
	gap: function () {
		// We only support for PhoneGap 0.6.0
		var js = safire.selector('script');
		
		var gap = false;

		for (i=0; i<js.length; i++) 
		{
			var src = js[i].getAttribute('src');
			gap = /gap\.js/.test( src );
			
			if( gap )
				break;
		}
		
		return gap;
	},
	
	big5: function () {
		var js = safire.selector('script');
		
		var big5 = false;

		for (i=0; i<js.length; i++) 
		{
			var src = js[i].getAttribute('src');
			big5 = /big5\.js/.test( src );
			
			if( big5 )
				break;
		}
		
		return big5;
	},
	
	init: function() {
		if( safire.disallow && !safire.compatible() )
			window.location = safire.disallow;
		
		if( safire.gap() == true )
		{
			Device.init(); // initialize phonegap - we only support v 0.6.0
			safire.device_id = Device.uuid;
		}
		
		if( safire.big5() == true )
		{
			Device.start(); //initialize big5
			safire.device_id = Device.id;
		}
			
		
		safire.events(); //set up listeners
		
		safire.preloads(); //preload buttons & modals
		
		try{ loaded(); }
		catch(err) { /*fail silently*/ }
	},
	
	compatible: function() {
		var sys = navigator.userAgent.toLowerCase();
		
		var iphone = /iphone/.test( sys );
		var android = /android/.test( sys );
		
		return (iphone || android);
	},
	
	loader: function(url, method, params, cb) {	
		if(typeof url == 'object' && this.getAttribute('href') == '#nogo'){ elobj = this.getAttribute('id'); url = 'nogo'; }
		
		if(!url){ url = this.getAttribute('href').substr(1); }
		if(!method){ var method = (this.localName == 'button' || this.localName == 'input') ? 'post' : 'get'; }
		if(!cb){ var cb = this.getAttribute('callback').split("(")[0]; } else { cb = cb.split("(")[0]; }
		if(!params){ var params = (this.localName == 'button' || this.localName == 'input') ? safire.serialize(this) : null; }
		
		
		if(url == 'nogo'){ eval(cb+'('+elobj+');'); return false; }
		
		var ajax = new XMLHttpRequest();

		ajax.onerror = function()
		{
		    alert('Unable to connect via ajax');
			return false;
		};


		ajax.onreadystatechange = function()
		{
		    if (ajax.readyState == 4)
		    {
		        if (cb) //got a callback? well - here is your response
				{ 
					var response = ajax.responseXML ? ajax.responseXML : ajax.responseText;
					cb = cb+'('+response+');';
					eval(cb);
				}
		        else //no callback? hmmm
				{
					alert('You have not defined a callback. Please add one...');
		        }
		
				safire.events(); //set up listeners on all new elements in DOM
		    }
		};


		ajax.open(method, url, true);
		ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		ajax.setRequestHeader("X-Req", "iSk8");
		if(params != null){ ajax.setRequestHeader("Content-Length", params.length); } //ternary doesnt work here
		ajax.send((params == null ? null : params.join("&")));
	},
	
	slide: function() {
		
	},
	
	animate: function(item) {
		
	}, 
	
	append: function (item, context) {
		if(context)
			context.appendChild(item);
		else
			document.body.appendChild(item);
	},
	
	remove: function (item, context) {
		if(context)
			context.removeChild(item);
		else
			document.body.removeChild(item);
	},
	
	modal: function ( modal ) {
		
		if( !modal.title ) //check for title because it's necessary
		{
			alert( 'Modal title text is needed!' );
		}
		
		if( !modal.html ) //check for HTML
		{
			alert( 'Modal HTML is needed!' );
		}
		
		//some checking for button text
		modal.submit_text = modal.submit_text ? modal.submit_text : 'submit';
		modal.cancel_text = modal.cancel_text ? modal.cancel_text : 'cancel';
		
		/*start building modal*/
		
		//create overlay - css for entire modal in safire.css
		var overlay = document.createElement('div');
		overlay.setAttribute('id', 'modal-overlay');
		overlay.setAttribute('class', 'overlay');
		
		//get body height and set overlay height
		var ht = document.defaultView.getComputedStyle(safire.selector('body')[0], null).getPropertyValue("height");
		var height = parseInt(ht) > 400 ? ht : '450px';
		overlay.style.height = height;
		
		//create modal thingy
		var modal_popup = document.createElement('div');
		modal_popup.setAttribute('class', 'modal');
		
		//top of modal 
		var top = document.createElement('div');
		top.setAttribute('class', 'top');
		
		//title of modal
		var title = document.createElement('div');
		title.setAttribute('class', 'modal-title');
		title.innerHTML = modal.title;
		
		//attach title to top part of modal
		safire.append(title, top);
		
		//attach top part of modal to lightbox
		safire.append(top, modal_popup);
		
		//middle of modal
		var middle = document.createElement('div');
		middle.setAttribute('class', 'middle');
		
		//depending on what we're given we either appendChild or set innerHTML
		if( typeof modal.html == 'string' )
		{
			middle.innerHTML = modal.html;
		}
		else if( typeof modal.html == 'object' && typeof modal.html.getAttribute == 'function' )
		{
			safire.append(modal.html, middle);
		}
		
		//handle submit button
		var submit = document.createElement('button');
		submit.setAttribute('id', 'submit_btn');
		submit.innerHTML = modal.submit_text;
		if( modal.button_style == 'adjacent')
		{
			submit.setAttribute('class', 'grey adj');
		}
		else
		{
			submit.setAttribute('class', 'grey');
		}
		
		//attach it to the middle part of the modal
		safire.append(submit, middle);
		
		//handle cancel button
		var cancel = document.createElement('button');
		cancel.setAttribute('id', 'cancel_btn');
		cancel.innerHTML = modal.cancel_text;
		if( modal.button_style == 'adjacent')
		{
			cancel.setAttribute('class', 'red adj');
		}
		else
		{
			cancel.setAttribute('class', 'red');
		}
		
		//attach cancel button to the middle part of the modal
		safire.append(cancel, middle);
		
		//if we are adjacent create a div.clr so we look legit
		if( modal.button_style == 'adjacent')
		{
			var clr = document.createElement('div');
			clr.setAttribute('class', 'clr');
			safire.append(clr, middle);
		}
		
		//attach middle part of modal to modal
		safire.append(middle, modal_popup);
		
		
		//bottom of modal
		var bottom = document.createElement('div');
		bottom.setAttribute('class', 'bottom');
		bottom.innerHTML = '&nbsp;';

		//attach middle part of modal to modal
		safire.append(bottom, modal_popup);
		
		//attach modal to overlay
		safire.append(modal_popup, overlay);
		
		//attach the overlay to the body - we're done building the modal!
		safire.append(overlay);
		
		//attach cancel tap event binding
		safire.selector('#cancel_btn').addEventListener("click", function(){ safire.modal_close( modal.x_callback ); }, false);
		
		//attach submit tap event binding
		safire.selector('#submit_btn').addEventListener("click", function(){ safire.modal_close( modal.callback ); }, false);
		
		//attach event bindings
		if( modal.bindings )
		{
			if( typeof modal.bindings == 'object' )
			{
				for (i=0; i<modal.bindings.length; i++) //go through our array of JSON objects for event bindings
				{
					var el = safire.selector(modal.bindings[i].selector);
					
					if( el.length ) // do we have a class OR element tag on our hands?
					{
						for (e=0; e<el.length; e++) //loop through and attach!
						{
							el[e].addEventListener(modal.bindings[i].event, modal.bindings[i].callback, false);
						}
					}
					else //otherwise just attach!
					{
						el.addEventListener(modal.bindings[i].event, modal.bindings[i].callback, false);
					}
					
				}
			}
		}
	},
	
	modal_close: function ( cb ){
		safire.remove(safire.selector('#modal-overlay'));
		cb();
	},
	
	replace: function (oldEl, newEl) {
		document.body.replaceChild(newEl, oldEl);
	},
	
	selector: function (selector, context) {
		var isid = selector.substr(0, 1) == '#' ? true : false;
		var isclass = selector.substr(0, 1) == '.' ? true : false;
		var isel = (!isid && !isclass) ? true : false;
		
		if(isid)
		{
			selector = selector.substr(1);
			
			if(context)
				return context.getElementById(selector);
			else
				return document.getElementById(selector);
		}
		else if(isclass)
		{
			selector = selector.substr(1);
			
			if(context)
				return context.getElementsByClassName(selector);
			else
				return document.getElementsByClassName(selector);
		}
		else if(isel)
		{	
			if(context)
				return context.getElementsByTagName(selector);
			else
				return document.getElementsByTagName(selector);
		}
		else
		{
			alert('You have provided an invalid selector.');
		}
	},
	
	stack: function (position) {
		
	},
	
	events: function () {
		var list_items = safire.selector('li');
		
		for (i=0; i<=list_items.length; i++) 
		{
			var this_item = list_items[i];
			safire.selector('a', this_item)[0].addEventListener("click", safire.loader, false);
		}
		
		// safire.selector('#history').addEventListener("click", safire.stack, false);
		
	},
	
	preloads: function (){
		imgs = new Array();
		
		var mdl_top = new Image(); 
		mdl_top.src= "/images/mdl_top.png";
		
		imgs.push(mdl_top);
		
		var mdl_bg = new Image(); 
		mdl_bg.src= "/images/mdl_bg.png";
		
		imgs.push(mdl_bg);
		
		var mdl_btm = new Image(); 
		mdl_btm.src= "/images/mdl_bottom.png";
		
		imgs.push(mdl_btm);
	},
		
	/********************************************
	*********** WebView Ext Methods ************
	*******************************************/
	geoLoc: function ( cb ) {
		
		//big5 support
		if ( safire.big5() == true )
		{
			
			Device.Location.wait( cb );
			return true;
			
		}
			
		//phone gap support
		if ( safire.gap() == true )
		{

			Device.Location.init(); //get location
			
			if(Device.Location.lat == null || Device.Location.lat == '0.000000') //if location is bogus - recurse
				setTimeout(safire.geoLoc, 3000, cb);
			
			else // otherwise get your callback going
				cb(Device.Location);
			
		}
			
	},
	
	vibrate: function () {
		Device.vibrate();
	},
	
	accel: null,
	
	start_accel: function ( cb ) { //needs to be confirmed as "working"
		
		//big5 support
		if ( safire.big5() == true )
		{
			
			Device.Acceleration.start( cb );
			return true;
			
		}
			
		//phone gap support
		if ( safire.gap() == true )
		{
			
			safire.accel = setInterval(cb, 100, accelX, accelY, accelZ );
			return true;
			
		}
		
	}, 
	
	stop_accel: function () { //needs to be confirmed as "working"
	
		//big5 support
		if ( safire.big5() == true )
		{
			
			Device.Acceleration.stop();
			return true;
			
		}
			
		//phone gap support
		if ( safire.gap() == true )
		{
			
			clearInterval( safire.accel );
			return true;
			
		}
		
	},
	
	getPhoto: function ( dest, cb ) { // big5 specific
		Device.Image.callback = typeof cb == 'function' ? cb : safire.procPhoto ;
		Device.Image.onerror = safire.procPhoto;
		Device.Image.destination = dest;
		Device.Image.getFromCamera(); 
		
		return true;
	},
	
	procPhoto: function ( arg ){ // big5 specific
			return arg;
	},
	
	
	/********************************************
	********* PseudoDB wrapper methods *********
	*******************************************/
	data: function(info){
		info = typeof info == 'object' ? info : eval(info);
		window.storage = info;
	},
	
	get_data: function (){
		return window.storage;
	},
	
	find_node: function (obj, f_id, string){
		for (i=0; i<=obj.length; i++) 
		{
			if( obj[i] )
			{
				for(m in obj[i])
				{
					if( m == f_id)
					{
						if( obj[i][m] == string )
						{
							return obj[i];
						}
					}
				}

			}
		}
	},
	
	delete_data: function (){
		window.storage = '';
	},

}

window.addEventListener("load", safire.init, false);