if (typeof(DeviceInfo) != 'object')
    DeviceInfo = {};

function Cordova() {
	ready = true;
	available = true;
	sceneController = null;	
}; 


Cordova.exec = function(win, fail, clazz, action, args) {

 setTimeout(function() { 
	 Cordova.plugins[clazz].execute(action, args, win, fail); 
   }, 0);

}

Cordova.checkArgs = function(args, func) {
    if (typeof args == 'object')
        func.apply(null, args);
    else
        func(args);
}

Cordova.callback = function(success, win, fail) {
	if (success)
		win();
	else
		fail();    
}

// translates the action into an API call
accelerometerAPI = {
    execute: function(action, args, win, fail) {
        var actionFound = false;
		switch(action) {
			case 'setFastAccelerometer':				
				Cordova.checkArgs(args, navigator.accelerometer.setFastAccelerometer);    
				actionFound = true; 
				break;
			case 'getCurrentAcceleration':
				Cordova.checkArgs(args, navigator.accelerometer.getCurrentAcceleration);
				actionFound = true;
				break;	
			case 'watchAcceleration':
			    Cordova.checkArgs(args, navigator.accelerometer.watchAcceleration);
			    actionFound = true;
			    break;
			case 'clearWatch':
			    Cordova.checkArgs(args, navigator.accelerometer.clearWatch);
			    actionFound = true;
			    break;
			case 'start':
			    Cordova.checkArgs(args, navigator.accelerometer.start);
			    actionFound = true;
			    break;      		
		}

        Cordova.callback(actionFound, win, fail);
    }
}

applicationAPI = {
    execute: function(action, args, win, fail) {
        var actionFound = false;
		switch(action) {
			case 'activate':				
				Cordova.checkArgs(args, navigator.application.activate);    
				actionFound = true; 
				break;
			case 'deactivate':
				Cordova.checkArgs(args, navigator.application.deactivate);
				actionFound = true;
				break;	
			case 'getIdentifier':
			    Cordova.checkArgs(args, navigator.application.getIdentifier);
			    actionFound = true;
			    break;      		
		}

		Cordova.callback(actionFound, win, fail);       
    }
}

cameraAPI = {
    execute: function(action, args, win, fail) {
        var actionFound = false;
		switch(action) {
			case 'getPicture':
				console.log("in here");
				Cordova.checkArgs(args, navigator.camera.getPicture);    
				actionFound = true; 
				break;      		
		}

		Cordova.callback(actionFound, win, fail);        
    }
}

// translates the action into an API call
compassAPI = {
    execute: function(action, args, win, fail) {
        var actionFound = false;
		switch(action) {
			case 'getCurrentHeading':
				Cordova.checkArgs(args, navigator.compass.getCurrentHeading);
				actionFound = true;
				break;	
			case 'watchHeading':
			    Cordova.checkArgs(args, navigator.compass.watchHeading);
			    actionFound = true;
			    break;
			case 'clearWatch':
			    Cordova.checkArgs(args, navigator.compass.clearWatch);
			    actionFound = true;
			    break;
			case 'start':
			    Cordova.checkArgs(args, navigator.compass.start);
			    actionFound = true;
			    break;      		
		}

        Cordova.callback(actionFound, win, fail);
    }
}

debugAPI = {
    execute: function(action, args, win, fail) {
        var actionFound = false;
		switch(action) {
			case 'log':				
				Cordova.checkArgs(args, window.debug.log);    
				actionFound = true; 
				break;
		    case 'warn':
			    Cordova.checkArgs(args, window.debug.warn);    
			    actionFound = true; 
			    break;		    
		    case 'error':
			    Cordova.checkArgs(args, window.debug.error);    
			    actionFound = true; 
			    break;		          		
		}

		Cordova.callback(actionFound, win, fail);        
    }
}

deviceAPI = {
    execute: function(action, args, win, fail) {
        var actionFound = false;
		switch(action) {
			case 'getDeviceInfo':				
				Cordova.checkArgs(args, navigator.device.getDeviceInfo);    
				actionFound = true; 
				break;		          		
		}

		Cordova.callback(actionFound, win, fail);        
    }
}

geolocationAPI = {
    execute: function(action, args, win, fail) {
        var actionFound = false;
		switch(action) {
			case 'getCurrentPosition':				
				Cordova.checkArgs(args, navigator.geolocation.getCurrentPosition);    
				actionFound = true; 
				break; 
			case 'watchPosition':				
				Cordova.checkArgs(args, navigator.geolocation.watchPosition);    
				actionFound = true; 
				break;
			case 'clearWatch':
			    Cordova.checkArgs(args, navigator.geolocation.clearWatch);    
			    actionFound = true; 
			    break;
			case 'start':
			    Cordova.checkArgs(args, navigator.geolocation.start);    
			    actionFound = true; 
			    break;
			case 'stop':
			    Cordova.checkArgs(args, navigator.geolocation.stop);    
			    actionFound = true; 
			    break;								   	          		
		}

		Cordova.callback(actionFound, win, fail);        
    }
}

mapAPI = {
    execute: function(action, args, win, fail) {
        var actionFound = false;
		switch(action) {
			case 'show':				
				Cordova.checkArgs(args, navigator.map.show);    
				actionFound = true; 
				break;		          		
		}

		Cordova.callback(actionFound, win, fail);        
    }
}

mouseAPI = {
    execute: function(action, args, win, fail) {
        var actionFound = false;
		switch(action) {
			case 'simulateMouseClick':				
				Cordova.checkArgs(args, navigator.mouse.simulateMouseClick);    
				actionFound = true; 
				break;		          		
		}

		Cordova.callback(actionFound, win, fail);        
    }
} 

networkAPI = {
    execute: function(action, args, win, fail) {
        var actionFound = false;
		switch(action) {
			case 'isReachable':				
				Cordova.checkArgs(args, navigator.network.isReachable);    
				actionFound = true; 
				break;		          		
		}

		Cordova.callback(actionFound, win, fail);        
    }
}

notificationAPI = {
    execute: function(action, args, win, fail) {
		var actionFound = false;
		switch(action) {
			case 'alert':				
				Cordova.checkArgs(args, navigator.notification.alert);    
				actionFound = true; 
				break;
			case 'showBanner':
				Cordova.checkArgs(args, navigator.notification.showBanner);
				actionFound = true;
				break;	
			case 'newDashboard':
			    Cordova.checkArgs(args, navigator.notification.newDashboard);
			    actionFound = true;
			    break;
			case 'removeBannerMessage':
			    Cordova.checkArgs(args, navigator.notification.removeBannerMessage);
			    actionFound = true;
			    break;
			case 'clearBannerMessage':
			    Cordova.checkArgs(args, navigator.notification.clearBannerMessage);
			    actionFound = true;
			    break;
			case 'vibrate':            
			    Cordova.checkArgs(args, navigator.notification.vibrate);
			    actionFound = true;
			    break;
			case 'beep':               
			    Cordova.checkArgs(args, navigator.notification.beep);
			    actionFound = true;
			    break;       		
		}

		Cordova.callback(actionFound, win, fail);
   }
}

orientationAPI = {
    execute: function(action, args, win, fail) {
        var actionFound = false;
		switch(action) {
			case 'setOrientation':				
				Cordova.checkArgs(args, navigator.orientation.setOrientation);    
				actionFound = true; 
				break;
			case 'getOrientation':
			    Cordova.checkArgs(args, navigator.orientation.getOrientation);    
			    actionFound = true; 
			    break;			    
			case 'start':
			    Cordova.checkArgs(args, navigator.orientation.start);    
				actionFound = true; 
				break;
			case 'watchOrientation':
			    Cordova.checkArgs(args, navigator.orientation.watchOrientation);    
				actionFound = true; 
				break;
			case 'clearWatch':
                Cordova.checkArgs(args, navigator.orientation.clearWatch);    
			    actionFound = true; 
			    break;
		}

		Cordova.callback(actionFound, win, fail);        
    }
}

smsAPI = {
    execute: function(action, args, win, fail) {
        var actionFound = false;
		switch(action) {
			case 'send':				
				Cordova.checkArgs(args, navigator.sms.send);    
				actionFound = true; 
				break;		          		
		}

		Cordova.callback(actionFound, win, fail);        
    }
}

telephonyAPI = {
    execute: function(action, args, win, fail) {
        var actionFound = false;
		switch(action) {
			case 'send':				
				Cordova.checkArgs(args, navigator.telephony.send);    
				actionFound = true; 
				break;		          		
		}

		Cordova.callback(actionFound, win, fail);        
    }
}

windowAPI = {
    execute: function(action, args, win, fail) {
   		var actionFound = false;
   		switch(action) {
   			case 'newCard':
   			    Cordova.checkArgs(args, navigator.window.newCard);  				    
   				actionFound = true; 
   				break;
   			case 'setFullScreen':
   			  	Cordova.checkArgs(args, navigator.window.setFullScreen);
   				actionFound = true; 
   				break;
   			case 'setWindowProperties':
   			    Cordova.checkArgs(args, navigator.window.setWindowProperties);
		        actionFound = true;
		        break;   			
   			case 'blockScreenTimeout':
   			    Cordova.checkArgs(args, navigator.window.blockScreenTimeout);
   			    actionFound = true;
		        break;
   			case 'setSubtleLightbar':
   			    Cordova.checkArgs(args, navigator.window.setSubtleLightbar);
   			    actionFound = true;
   			    break;
   				   			  	
   		}

   		Cordova.callback(actionFound, win, fail);
      }    
}

// this mapping acts as a shim to the webOS APIs
Cordova.plugins = {};
Cordova.plugins['navigator.accelerometer'] = accelerometerAPI;
Cordova.plugins['navigator.application'] = applicationAPI;
Cordova.plugins['navigator.camera'] = cameraAPI;
Cordova.plugins['navigator.compass'] = compassAPI;
Cordova.plugins['window.debug'] = debugAPI;
Cordova.plugins['navigator.device'] = deviceAPI;
Cordova.plugins['navigator.geolocation'] = geolocationAPI;
Cordova.plugins['navigator.map'] = mapAPI;
Cordova.plugins['navigator.mouse'] = mouseAPI;
Cordova.plugins['navigator.network'] = networkAPI; 
Cordova.plugins['navigator.notification'] = notificationAPI;
Cordova.plugins['navigator.orientation'] = orientationAPI; 
Cordova.plugins['navigator.sms'] = smsAPI;
Cordova.plugins['navigator.telephony'] = telephonyAPI;  
Cordova.plugins['navigator.window'] = windowAPI;

document.addEventListener('DOMContentLoaded', function () {
    window.cordova = new Cordova();
    navigator.device.deviceReady();
});
/*
 * This class contains acceleration information
 * @constructor
 * @param {Number} x The force applied by the device in the x-axis.
 * @param {Number} y The force applied by the device in the y-axis.
 * @param {Number} z The force applied by the device in the z-axis.
 */
function Acceleration(x, y, z) {
	/*
	 * The force applied by the device in the x-axis.
	 */
	this.x = x;
	/*
	 * The force applied by the device in the y-axis.
	 */
	this.y = y;
	/*
	 * The force applied by the device in the z-axis.
	 */
	this.z = z;
	/*
	 * The time that the acceleration was obtained.
	 */
	this.timestamp = new Date().getTime();
};

/*
 * This class specifies the options for requesting acceleration data.
 * @constructor
 */
function AccelerationOptions() {
	/*
	 * The timeout after which if acceleration data cannot be obtained the errorCallback
	 * is called.
	 */
	this.timeout = 10000;
};

/*
 * This class provides access to device accelerometer data.
 * @constructor
 */
function Accelerometer() {
	/*
	 * The last known acceleration.
	 */
	this.lastAcceleration = null;
};

/*
 * Tells WebOS to put higher priority on accelerometer resolution. Also relaxes the internal garbage collection events.
 * @param {Boolean} state
 * Dependencies: Mojo.windowProperties
 * Example:
 * 		navigator.accelerometer.setFastAccelerometer(true)
 */
Accelerometer.prototype.setFastAccelerometer = function(state) {
	navigator.windowProperties.fastAccelerometer = state;
	navigator.window.setWindowProperties();
};

/*
 * Asynchronously aquires the current acceleration.
 * @param {Function} successCallback The function to call when the acceleration
 * data is available
 * @param {Function} errorCallback The function to call when there is an error 
 * getting the acceleration data.
 * @param {AccelerationOptions} options The options for getting the accelerometer data
 * such as timeout.
 */

Accelerometer.prototype.getCurrentAcceleration = function(successCallback, errorCallback, options) {

    var referenceTime = 0;
    if (this.lastAcceleration)
        referenceTime = this.lastAcceleration.timestamp;
    else
        this.start();
 
    var timeout = 20000;
    var interval = 500;
    if (typeof(options) == 'object' && options.interval)
        interval = options.interval;
 
    if (typeof(successCallback) != 'function')
        successCallback = function() {};
    if (typeof(errorCallback) != 'function')
        errorCallback = function() {};
 
    var dis = this;
    var delay = 0;
    var timer = setInterval(function() {
        delay += interval;
 
		//if we have a new acceleration, call success and cancel the timer
        if (typeof(dis.lastAcceleration) == 'object' && dis.lastAcceleration != null && dis.lastAcceleration.timestamp > referenceTime) {
            successCallback(dis.lastAcceleration);
            clearInterval(timer);
        } else if (delay >= timeout) { //else if timeout has occured then call error and cancel the timer
            errorCallback();
            clearInterval(timer);
        }
		//else the interval gets called again
    }, interval);
};


/*
 * Asynchronously aquires the acceleration repeatedly at a given interval.
 * @param {Function} successCallback The function to call each time the acceleration
 * data is available
 * @param {Function} errorCallback The function to call when there is an error 
 * getting the acceleration data.
 * @param {AccelerationOptions} options The options for getting the accelerometer data
 * such as timeout.
 */

Accelerometer.prototype.watchAcceleration = function(successCallback, errorCallback, options) {
	this.getCurrentAcceleration(successCallback, errorCallback, options);
	// TODO: add the interval id to a list so we can clear all watches
 	var frequency = (options != undefined)? options.frequency : 10000;
	var that = this;
	return setInterval(function() {
		that.getCurrentAcceleration(successCallback, errorCallback, options);
	}, frequency);
};

/*
 * Clears the specified accelerometer watch.
 * @param {String} watchId The ID of the watch returned from #watchAcceleration.
 */
Accelerometer.prototype.clearWatch = function(watchId) {
	clearInterval(watchId);
};

/*
 * Starts the native acceleration listener.
 */

Accelerometer.prototype.start = function() {
	var that = this;
	//Mojo.Event.listen(document, "acceleration", function(event) {
	document.addEventListener("acceleration", function(event) {
		var accel = new Acceleration(event.accelX, event.accelY, event.accelZ);
		that.lastAcceleration = accel;
	});
};

if (typeof navigator.accelerometer == "undefined") navigator.accelerometer = new Accelerometer();

function Application() {
	
};

/*
 * Tell webOS to activate the current page of your app, bringing it into focus.
 * Example:
 * 		navigator.application.activate();
 */	
Application.prototype.activate = function() {
	PalmSystem.activate();
};

/*
 * Tell webOS to deactivate your app.
 * Example:
 *		navigator.application.deactivate();
 */	
Application.prototype.deactivate = function() {
	PalmSystem.deactivate();
};

/*
 * Returns the identifier of the current running application (e.g. com.yourdomain.yourapp).
 * Example:
 *		navigator.application.getIdentifier();
 */
Application.prototype.getIdentifier = function() {
	return PalmSystem.identifier;
};

if (typeof navigator.application == "undefined") navigator.application = new Application();

/*
 * This class provides access to the device audio
 * @constructor
 */

Cordova.overrideAudio = function() {
	
	Cordova.MojoAudio = Audio;
	
	Audio = function(src) {
		this.src = src;							
	};

	Audio.prototype.play = function() {
		// this.src = src;
		// The 'end' event listener doesn't seem to work, so we have to call stop before playing
		// otherwise, we'll never be able to play again
		if (this.paused && !this.stopped) {
			this.paused = false;
			this.playing = true;	
			this.audioPlayer.play();
		} else {
			if (this.audioPlayer)
				this.stop();
			if (!this.playing) {
				this.paused = false;
				this.playing = true;	
				this.stopped = false;
				this.audioPlayer = new Cordova.MojoAudio();
				var file = Mojo.appPath + this.src;
				if (this.audioPlayer.palm) {
					this.audioPlayer.mojo.audioClass = "media";
				}
				this.audioPlayer.src = file;
		
				//event doesn't work, see above
				this.audioPlayer.addEventListener('end', this.endHandler, false);
				this.audioPlayer.play();
			}
		}
	};

	Audio.prototype.pause = function() {
		if (this.stopped)
			return;
		this.paused = true;	
		if (this.playing) {
			this.playing = false;
			this.stopped = false;
			this.audioPlayer.pause();
		} else {
			this.playing = false;	
			this.paused = false;
			this.stopped = true;
		}
	};

	Audio.prototype.stop = function() {
		this.audioPlayer.pause();	
		this.audioPlayer.src = null;
		this.playing = false;	
		this.paused = false;
		this.stopped = true;
	};

	// End event handler not working (see comment in Audio.prototype.play)
	Audio.prototype.endHandler = function () {
		this.audioPlayer.removeEventListener('end', endHandler, false);
		this.audioPlayer.pause();	
		this.audioPlayer.src = null;
		this.paused = false;
		this.stopped = true;
	};

	/*
	 * This class contains information about any Media errors.
	 * @constructor
	 */
	MediaError = function() {
		this.code = null,
		this.message = "";
	};

	MediaError.MEDIA_ERR_ABORTED 		= 1;
	MediaError.MEDIA_ERR_NETWORK 		= 2;
	MediaError.MEDIA_ERR_DECODE 		= 3;
	MediaError.MEDIA_ERR_NONE_SUPPORTED = 4;

}

document.addEventListener("deviceready", Cordova.overrideAudio, false);

/*
 * This class provides access to the device camera.
 * @constructor
 */
function Camera() {
	
};

/*
 * @param {Function} successCallback
 * @param {Function} errorCallback
 * @param {Object} options
 */
Camera.prototype.getPicture = function(successCallback, errorCallback, options) {

	var filename = "";

	if (typeof options != 'undefined' && typeof options.filename != 'undefined') {
		filename = options.filename;
	}	

	this.service = navigator.service.Request('palm://com.palm.applicationManager', {
		method: 'launch',
		parameters: {
		id: 'com.palm.app.camera',
		params: {
				appId: 'com.palm.app.camera',
				name: 'capture',
				sublaunch: true,
				filename: filename
			}
		},
		onSuccess: successCallback,
		onFailure: errorCallback
	});	
};

if (typeof navigator.camera == 'undefined') navigator.camera = new Camera();

/*
 * This class provides access to the device contacts.
 * @constructor
 */

function Contacts() {
	
};

function Contact() {
    this.phones = [];
    this.emails = [];
	this.name = {
		givenName: "",
		familyName: "",
		formatted: ""
	};
	this.id = "";
};

Contact.prototype.displayName = function()
{
    // TODO: can be tuned according to prefs
	return this.givenName + " " + this.familyName;
};

function ContactsFilter(name) {
	if (name)
		this.name = name;
	else
		this.name = "";
};

/*
 * @param {ContactsFilter} filter Object with filter properties. filter.name only for now.
 * @param {function} successCallback Callback function on success
 * @param {function} errorCallback Callback function on failure
 * @param {object} options Object with properties .page and .limit for paging
 */

Contacts.prototype.find = function(filter, successCallback, errorCallback, options) {
	errorCallback({ name: "ContactsError", message: "Cordova Palm contacts not implemented" });
};

Contacts.prototype.success_callback = function(contacts_iterator) {
};

if (typeof navigator.contacts == "undefined") navigator.contacts = new Contacts();
/*
 * This class provides access to device compass data.
 * @constructor
 */
function Compass() {
  /*
	 * The last known heading.
	 */
	this.lastHeading = null;
};

/*
 * Asynchronously aquires the current compass heading.
 * @param {Function} successCallback The function to call when the compass
 * data is available
 * @param {Function} errorCallback The function to call when there is an error 
 * getting the compass data.
 * @param {CompassOptions} options The options for getting the compass data
 * such as timeout.
 */

Compass.prototype.getCurrentHeading = function(successCallback, errorCallback, options) {

    var referenceTime = 0;
    if (this.lastHeading)
        referenceTime = this.lastHeading.timestamp;
    else
        this.start();
 
    var timeout = 20000;
    var interval = 500;
    if (typeof(options) == 'object' && options.interval)
        interval = options.interval;
 
    if (typeof(successCallback) != 'function')
        successCallback = function() {};
    if (typeof(errorCallback) != 'function')
        errorCallback = function() {};
 
    var dis = this;
    var delay = 0;
    var timer = setInterval(function() {
        delay += interval;
 
		//if we have a new compass heading, call success and cancel the timer
        if (typeof(dis.lastHeading) == 'object' && dis.lastHeading != null && dis.lastHeading.timestamp > referenceTime) {
            successCallback(dis.lastHeading.magHeading);
            clearInterval(timer);
        } else if (delay >= timeout) { //else if timeout has occured then call error and cancel the timer
            errorCallback();
            clearInterval(timer);
        }
		//else the interval gets called again
    }, interval);
};


/*
 * Asynchronously aquires the compass heading repeatedly at a given interval.
 * @param {Function} successCallback The function to call each time the acceleration
 * data is available
 * @param {Function} errorCallback The function to call when there is an error 
 * getting the compass data.
 * @param {CompassOptions} options The options for getting the compass data
 * such as timeout.
 */

Compass.prototype.watchHeading = function(successCallback, errorCallback, options) {
	this.getCurrentHeading(successCallback, errorCallback, options);
	// TODO: add the interval id to a list so we can clear all watches
 	var frequency = (options != undefined)? options.frequency : 10000;
	var that = this;
	return setInterval(function() {
		that.getCurrentHeading(successCallback, errorCallback, options);
	}, frequency);
};

/*
 * Clears the specified heading watch.
 * @param {String} watchId The ID of the watch returned from #watchHeading.
 */
Compass.prototype.clearWatch = function(watchId) {
	clearInterval(watchId);
};

/*
 * Starts the native compass listener.
 */

Compass.prototype.start = function() {
	var that = this;
	//Mojo.Event.listen(document, "acceleration", function(event) {
	document.addEventListener("compass", function(event) {
		var heading={};
    heading.trueHeading=event.trueHeading;
    heading.magHeading=event.magHeading;
    heading.timestamp = new Date().getTime();
		that.lastHeading = heading;
	});
};

if (typeof navigator.compass == "undefined") navigator.compass = new Compass();
/*
 * This class provides access to the debugging console.
 * @constructor
 */
function DebugConsole() {
};

/*
 * Print a normal log message to the console
 * @param {Object|String} message Message or object to print to the console
 */
DebugConsole.prototype.log = function(message) {
	if (typeof message == 'object')
		message = Object.toJSON(message);   
		
	this.error(message);
};

/*
 * Print a warning message to the console
 * @param {Object|String} message Message or object to print to the console
 */
DebugConsole.prototype.warn = function(message) {
	if (typeof message == 'object')
		message = Object.toJSON(message);    
		
	this.error(message);
};

/**
 * Print an error message to the console
 * @param {Object|String} message Message or object to print to the console
 */
DebugConsole.prototype.error = function(message) {
	if (typeof message == 'object')
		message = Object.toJSON(message);
 
	console.log(JSON.stringify(message));
};

if (typeof window.debug == "undefined") window.debug = new DebugConsole();
/*
 * this represents the mobile device, and provides properties for inspecting the model, version, UUID of the
 * phone, etc.
 * @constructor
 */
function Device() {
    this.platform = "palm";
    this.version  = null;
    this.name     = null;
    this.uuid     = null;
    this.deviceInfo = null;
};

/*
 * A direct call to return device information.
 * Example:
 *		var deviceinfo = JSON.stringify(navigator.device.getDeviceInfo()).replace(/,/g, ', ');
 */
Device.prototype.getDeviceInfo = function() {
	return this.deviceInfo;//JSON.parse(PalmSystem.deviceInfo);
};

/*
 * needs to be invoked in a <script> nested within the <body> it tells WebOS that the app is ready
        TODO: see if we can get this added as in a document.write so that the user doesn't have to explicitly call this method
 * Dependencies: Mojo.onKeyUp
 * Example:
 *		navigator.device.deviceReady();
 */	
Device.prototype.deviceReady = function() {

	// tell webOS this app is ready to show
	if (window.PalmSystem) {
		// setup keystroke events for forward and back gestures
		document.body.addEventListener("keyup", Mojo.onKeyUp, true);

		setTimeout(function() { PalmSystem.stageReady(); PalmSystem.activate(); }, 1);
		alert = this.showBanner;
	}

    // fire deviceready event; taken straight from phonegap-iphone
    // put on a different stack so it always fires after DOMContentLoaded
    window.setTimeout(function () {
        var e = document.createEvent('Events');
        e.initEvent('deviceready');
        document.dispatchEvent(e);
    }, 10);
	
	this.setUUID();
	this.setDeviceInfo();
};

Device.prototype.setDeviceInfo = function() {
    var parsedData = JSON.parse(PalmSystem.deviceInfo);
    
    this.deviceInfo = parsedData;
    this.version = parsedData.platformVersion;
    this.name = parsedData.modelName;
};

Device.prototype.setUUID = function() {
	//this is the only system property webos provides (may change?)
	var that = this;
	this.service = navigator.service.Request('palm://com.palm.preferences/systemProperties', {
	    method:"Get",
	    parameters:{"key": "com.palm.properties.nduid" },
	    onSuccess: function(result) {
			that.uuid = result["com.palm.properties.nduid"];
		}
    });	


};


if (typeof window.device == 'undefined') window.device = navigator.device = new Device();

/*
 * This class provides generic read and write access to the mobile device file system.
 */
function File() {
	/**
	 * The data of a file.
	 */
	this.data = "";
	/**
	 * The name of the file.
	 */
	this.name = "";
};

/*
 * Reads a file from the mobile device. This function is asyncronous.
 * @param {String} fileName The name (including the path) to the file on the mobile device. 
 * The file name will likely be device dependant.
 * @param {Function} successCallback The function to call when the file is successfully read.
 * @param {Function} errorCallback The function to call when there is an error reading the file from the device.
 */
File.prototype.read = function(fileName, successCallback, errorCallback) {
	//Mojo has no file i/o yet, so we use an xhr. very limited
	var path = fileName;	//incomplete
	//Mojo.Log.error(path);
	navigator.debug.error(path);
	
	if (typeof successCallback != 'function')
		successCallback = function () {};
	if (typeof errorCallback != 'function')
		errorCallback = function () {};
	
	var xhr = new XMLHttpRequest();
	xhr.onreadystatechange = function() {
		if (xhr.readyState == 4) {
			if (xhr.status == 200 && xhr.responseText != null) {
				this.data = xhr.responseText;
				this.name = path;
				successCallback(this.data);
			} else {
				errorCallback({ name: xhr.status, message: "could not read file: " + path });
			}
		}
	};
	xhr.open("GET", path, true);
	xhr.send();
};

/*
 * Writes a file to the mobile device. 
 * @param {File} file The file to write to the device.
 */
File.prototype.write = function(file) {
	//Palm does not provide file i/o
};

if (typeof navigator.file == "undefined") navigator.file = new File();

/*
 * This class provides access to device GPS data.
 * @constructor
 */
function Geolocation() {
    /**
     * The last known GPS position.
     */
    this.lastPosition = null;
    this.lastError = null;
    this.callbacks = {
        onLocationChanged: [],
        onError: []
    };
};

/*
 * Asynchronously aquires the current position.
 * @param {Function} successCallback The function to call when the position
 * data is available
 * @param {Function} errorCallback The function to call when there is an error 
 * getting the position data.
 * @param {PositionOptions} options The options for getting the position data
 * such as timeout.
 */
Geolocation.prototype.getCurrentPosition = function(successCallback, errorCallback, options) {
    /*
	var referenceTime = 0;
    if (this.lastPosition)
        referenceTime = this.lastPosition.timestamp;
    else
        this.start(options);
	*/

    var timeout = 20000;
    if (typeof(options) == 'object' && options.timeout)
    timeout = options.timeout;

    if (typeof(successCallback) != 'function')
    successCallback = function() {};
    if (typeof(errorCallback) != 'function')
    errorCallback = function() {};

    /*
    var dis = this;
    var delay = 0;
    var timer = setInterval(function() {
        delay += interval;
		
		//if we have a new position, call success and cancel the timer
        if (dis.lastPosition && typeof(dis.lastPosition) == 'object' && dis.lastPosition.timestamp > referenceTime) {
            successCallback(dis.lastPosition);
            clearInterval(timer);
        } else if (delay >= timeout) { //else if timeout has occured then call error and cancel the timer
            errorCallback();
            clearInterval(timer);
        }
		//else the interval gets called again
    }, interval);
	*/

    var responseTime;
    if (timeout <= 5000)
    responseTime = 1;
    else if (5000 < timeout <= 20000)
    responseTime = 2;
    else
    responseTime = 3;

    var timer = setTimeout(function() {
        errorCallback({
            message: "timeout"
        });
    },
    timeout);

    var startTime = (new Date()).getTime();

    var alias = this;

    // It may be that getCurrentPosition is less reliable than startTracking ... but
    // not sure if we want to be starting and stopping the tracker if we're not watching.
    //new Mojo.Service.Request('palm://com.palm.location', {
    navigator.service.Request('palm://com.palm.location', {
        method: "getCurrentPosition",
        parameters: {
            responseTime: responseTime
        },
        onSuccess: function(event) {
            alias.lastPosition = {
                coords: {
                    latitude: event.latitude,
                    longitude: event.longitude,
                    altitude: (event.altitude >= 0 ? event.altitude: null),
                    speed: (event.velocity >= 0 ? event.velocity: null),
                    heading: (event.heading >= 0 ? event.heading: null),
                    accuracy: (event.horizAccuracy >= 0 ? event.horizAccuracy: null),
                    altitudeAccuracy: (event.vertAccuracy >= 0 ? event.vertAccuracy: null)
                },
                timestamp: new Date().getTime()
            };

            var responseTime = alias.lastPosition.timestamp - startTime;
            if (responseTime <= timeout)
            {
                clearTimeout(timer);
                successCallback(alias.lastPosition);
            }
        },
        onFailure: function() {
            errorCallback();
        }
    });

};

/*
 * Asynchronously aquires the position repeatedly at a given interval.
 * @param {Function} successCallback The function to call each time the position
 * data is available
 * @param {Function} errorCallback The function to call when there is an error 
 * getting the position data.
 * @param {PositionOptions} options The options for getting the position data
 * such as timeout and the frequency of the watch.
 */
Geolocation.prototype.watchPosition = function(successCallback, errorCallback, options) {
    // Invoke the appropriate callback with a new Position object every time the implementation
    // determines that the position of the hosting device has changed.
    var frequency = 10000;
    if (typeof(options) == 'object' && options.frequency)
    frequency = options.frequency;

    this.start(options, errorCallback);

    var referenceTime = 0;
    if (this.lastPosition)
    referenceTime = this.lastPosition.timestamp;

    var alias = this;
    return setInterval(function() {
        // check if we have a new position, if so call our successcallback
        if (!alias.lastPosition)
        return;

        if (alias.lastPosition.timestamp > referenceTime)
        successCallback(alias.lastPosition);
    },
    frequency);
};


/*
 * Clears the specified position watch.
 * @param {String} watchId The ID of the watch returned from #watchPosition.
 */
Geolocation.prototype.clearWatch = function(watchId) {
    clearInterval(watchId);
    this.stop();
};

Geolocation.prototype.start = function(options, errorCallback) {
    //options.timeout;
    //options.interval;
    if (typeof(errorCallback) != 'function')
    errorCallback = function() {};

    var that = this;
    var frequency = 10000;
    if (typeof(options) == 'object' && options.frequency)
    frequency = options.frequency;

    var responseTime;
    if (frequency <= 5000)
    responseTime = 1;
    else if (5000 < frequency <= 20000)
    responseTime = 2;
    else
    responseTime = 3;

    //location tracking does not support setting a custom interval :P
    this.trackingHandle = navigator.service.Request('palm://com.palm.location', {
        method: 'startTracking',
        parameters: {
            subscribe: true
        },
        onSuccess: function(event) {
            that.lastPosition = {
                coords: {
                    latitude: event.latitude,
                    longitude: event.longitude,
                    altitude: (event.altitude >= 0 ? event.altitude: null),
                    speed: (event.velocity >= 0 ? event.velocity: null),
                    heading: (event.heading >= 0 ? event.heading: null),
                    accuracy: (event.horizAccuracy >= 0 ? event.horizAccuracy: null),
                    altitudeAccuracy: (event.vertAccuracy >= 0 ? event.vertAccuracy: null)
                },
                timestamp: new Date().getTime()
            };
        },
        onFailure: function() {
            errorCallback();
        }
    });
};

Geolocation.prototype.stop = function() {
    this.trackingHandle.cancel();
};

if (typeof navigator.geolocation == "undefined") navigator.geolocation = new Geolocation();

/*
 * This class provides access to native mapping applications on the device.
 */
function Map() {
	
};

/*
 * Shows a native map on the device with pins at the given positions.
 * @param {Array} positions
 */
Map.prototype.show = function(positions) {

	var jsonPos = {};
	var pos = null;
	if (typeof positions == 'object') {
		// If positions is an array, then get the first only, since google's query
		// can't take more than one marker (believe it or not).
		// Otherwise we assume its a single position object.
		if (positions.length) {
			pos = positions[0];
		} else {
			pos = positions;
		}
	} 
	else if (navigator.geolocation.lastPosition) {
		pos = navigator.geolocation.lastPosition;
	} else {
		// If we don't have a position, lets use nitobi!
		pos = { coords: { latitude: 49.28305, longitude: -123.10689 } };
	}

	this.service = navigator.service.Request('palm://com.palm.applicationManager', {
		method: 'open',
		parameters: {
		id: 'com.palm.app.maps',
		params: {
			query: "@" + pos.coords.latitude + "," + pos.coords.longitude
			}
		}
	});

};

if (typeof navigator.map == "undefined") navigator.map = new Map();

//===========================
//		Mojo Dependencies - we still need to rely on these minimal parts of the Mojo framework - should try to find if we can get access to lower level APIs
//							so that we can remove dependence of Mojo
//===========================
	
Mojo = {
	contentIndicator: false,

	// called by webOS in certain cases
	relaunch: function() {
		var launch = JSON.parse(PalmSystem.launchParams);
		
		if (launch['palm-command'] && launch['palm-command'] == 'open-app-menu')
			this.fireEvent(window, "appmenuopen");
		else
			this.fireEvent(window, "palmsystem", launch);
	},
	
	// called by webOS when your app gets focus
	stageActivated: function() {
		this.fireEvent(window, "activate");
	},

	// called by webOS when your app loses focus
	stageDeactivated: function() {
		this.fireEvent(window, "deactivate");
	},

	// this is a stub -- called by webOS when orientation changes
	// but the preferred method is to use the orientationchanged
	// DOM event
	screenOrientationChanged: function(dir) {
	},
	
	// used to redirect keyboard events to DOM event "back"
	onKeyUp: function(e) {
		if (e.keyCode == 27)
			this.fireEvent(window, "back");
	},
		
	// private method, used to fire off DOM events
	fireEvent: function(element, event, data) {
		var e = document.createEvent("Event");
		e.initEvent(event, false, true);
		
		if (data)
			e.data = data;
		
		element.dispatchEvent(e);
	},
	
	/*
	 	not sure if these stubs are still needed since the Log object is encapsulated in debugconsole class 
		and the Service object is encapsulated in the Service class
	*/
	// stubs to make v8 happier
	Service: {},
	Log: {}
	
};function Mouse() {
	
};

/*
 * Possibly useful for automated testing, this call to PalmSystem triggers a mouse click (i.e. touch event). 
 * x coordinate & y coordinate of where the screen was touched and also a true/false flag to tell WebOS if it should simulate the mouse click
 * @param {Number} x
 * @param {Number} y
 * @param {Boolean} state
 * Example:
 *		navigator.mouse.simulateMouseClick(10, 10, true);
 */	
Mouse.prototype.simulateMouseClick = function(x, y, state) {
	PalmSystem.simulateMouseClick(x, y, state || true);
};

if (typeof navigator.mouse == "undefined") navigator.mouse = new Mouse();

function Network() {
    /*
     * The last known Network status.
     */
	this.lastReachability = null;
};

Network.prototype.isReachable = function(hostName, successCallback, options) {
	this.request = navigator.service.Request('palm://com.palm.connectionmanager', {
	    method: 'getstatus',
	    parameters: {},
	    onSuccess: function(result) { 
		
			var status = NetworkStatus.NOT_REACHABLE;
			if (result.isInternetConnectionAvailable == true) {

				if (result.wan.state == "connected") {
					status = NetworkStatus.REACHABLE_VIA_CARRIER_DATA_NETWORK;
				}
				
				if (result.wifi.state == "connected") {
					status = NetworkStatus.REACHABLE_VIA_WIFI_NETWORK;
				}
							
			}
			successCallback(status); 
		},
	    onFailure: function() {}
	});

};

Network.prototype.connection = function(hostName, successCallback, options) {
	this.request = navigator.service.Request('palm://com.palm.connectionmanager', {
	    method: 'getstatus',
	    parameters: {},
	    onSuccess: function(result) { 
			successCallback(result); 
		},
	    onFailure: function() {}
	});	
};

/*
 * This class contains information about any NetworkStatus.
 * @constructor
 */
function NetworkStatus() {
	this.code = null;
	this.message = "";
};

NetworkStatus.NOT_REACHABLE = 0;
NetworkStatus.REACHABLE_VIA_CARRIER_DATA_NETWORK = 1;
NetworkStatus.REACHABLE_VIA_WIFI_NETWORK = 2;

if (typeof navigator.network == "undefined") navigator.network = new Network();

/*
 * This class provides access to notifications on the device.
 */
function Notification() {

    };

/*
 * adds a dashboard to the WebOS app
 * @param {String} url
 * @param {String} html
 * Example:
 *		navigator.notification.newDashboard("dashboard.html");
 */
Notification.prototype.newDashboard = function(url, html) {
    var win = window.open(url, "_blank", "attributes={\"window\":\"dashboard\"}");
    html && win.document.write(html);
    win.PalmSystem.stageReady();
};

/*
 * Displays a banner notification. If specified, will send your 'response' object as data via the 'palmsystem' DOM event.
 * If no 'icon' filename is specified, will use a small version of your application icon.
 * @param {String} message
 * @param {Object} response
 * @param {String} icon 
 * @param {String} soundClass class of the sound; supported classes are: "ringtones", "alerts", "alarm", "calendar", "notification"
 * @param {String} soundFile partial or full path to the sound file
 * @param {String} soundDurationMs of sound in ms
 * Example:
 *		navigator.notification.showBanner('test message');
 */
Notification.prototype.showBanner = function(message, response, icon, soundClass, soundFile, soundDurationMs) {
    var response = response || {
        banner: true
    };
    PalmSystem.addBannerMessage(message, JSON.stringify(response), icon, soundClass, soundFile, soundDurationMs);
};

/**
 * Remove a banner from the banner area. The category parameter defaults to 'banner'. Will not remove
 * messages that are already displayed.
 * @param {String} category 
		Value defined by the application and usually same one used in {@link showBanner}. 
		It is used if you have more than one kind of banner message. 
 */
Notification.prototype.removeBannerMessage = function(category) {
    var bannerKey = category || 'banner';
    var bannerId = this.banners.get(bannerKey);
    if (bannerId) {
        try {
            PalmSystem.removeBannerMessage(bannerId);
        } catch(removeBannerException) {
            window.debug.error(removeBannerException.toString());
        }
    }
};

/*
 * Remove all pending banner messages from the banner area. Will not remove messages that are already displayed.
 */
Notification.prototype.clearBannerMessage = function() {
    PalmSystem.clearBannerMessage();
};

/*
 * This function vibrates the device
 * @param {number} duration The duration in ms to vibrate for.
 * @param {number} intensity The intensity of the vibration
 */
Notification.prototype.vibrate = function(duration, intensity) {
    //the intensity for palm is inverted; 0=high intensity, 100=low intensity
    //this is opposite from our api, so we invert
    if (isNaN(intensity) || intensity > 100 || intensity <= 0)
    intensity = 0;
    else
    intensity = 100 - intensity;

    // if the app id does not have the namespace "com.palm.", an error will be thrown here
    //this.vibhandle = new Mojo.Service.Request("palm://com.palm.vibrate", {
    this.vibhandle = navigator.service.Request("palm://com.palm.vibrate", {
        method: 'vibrate',
        parameters: {
            'period': intensity,
            'duration': duration
        }
    },
    false);
};

/* 
 * Plays the specified sound
 * @param {String} soundClass class of the sound; supported classes are: "ringtones", "alerts", "alarm", "calendar", "notification"
 * @param {String} soundFile partial or full path to the sound file
 * @param {String} soundDurationMs of sound in ms
 */
Notification.prototype.beep = function(soundClass, soundFile, soundDurationMs) {
    PalmSystem.playSoundNotification(soundClass, soundFile, soundDurationMs);
};

/*
 * displays a notification
 * @param {String} message
 * @param {Object} response
 * @param {String} icon
 */
Notification.prototype.alert = function(message, response, icon) {
    var response = response || {
        banner: true
    };
    navigator.notification.showBanner(message, response, icon);
};

if (typeof navigator.notification == 'undefined') {
    navigator.notification = new Notification();
    alert = navigator.notification.alert;
}

/*
 * This class provides access to the device orientation.
 * @constructor
 */
function Orientation() {
	this.started = false;
};

/*
 * Manually sets the orientation of the application window. 
 * 'up', 'down', 'left' or 'right' used to specify fixed window orientation
 * 'free' WebOS will change the window orientation to match the device orientation
 * @param {String} orientation
 * Example:
 *		navigator.orientation.setOrientation('up');
 */
Orientation.prototype.setOrientation = function(orientation) {
	PalmSystem.setWindowOrientation(orientation);   
};

/*
 * Returns the current window orientation
 */
Orientation.prototype.getCurrentOrientation = function() {
  	return PalmSystem.windowOrientation;
};

/*
 * Starts the native orientationchange event listener.
 */  
Orientation.prototype.start = function (successCallback) {
	var that = this;
	// This subscribes the callback once for the successCallback function
	that.callback = function (e) {
		document.removeEventListener("orientationChanged", that.callback);
		successCallback(e.orientation);
	}
	
	document.addEventListener("orientationChanged", that.callback);
	
	// This subscribes setOrientation to be constantly updating the currentOrientation property
	document.addEventListener("orientationchange", function(event) {
		var orient = null;
		switch (event.position) {
			case 0: orient = DisplayOrientation.FACE_UP; break;
			case 1: orient = DisplayOrientation.FACE_DOWN; break;
			case 2: orient = DisplayOrientation.PORTRAIT; break;
			case 3: orient = DisplayOrientation.REVERSE_PORTRAIT; break;
			case 4: orient = DisplayOrientation.LANDSCAPE_RIGHT_UP; break;
			case 5: orient = DisplayOrientation.LANDSCAPE_LEFT_UP; break;
			default: return; 	//orientationchange event seems to get thrown sometimes with a null event position
		}
		that.setOrientation(orient);
	});
	this.started = true;
};

/*
 * Asynchronously aquires the orientation repeatedly at a given interval.
 * @param {Function} successCallback The function to call each time the orientation
 * data is available.
 * @param {Function} errorCallback The function to call when there is an error 
 * getting the orientation data.
 */             
Orientation.prototype.watchOrientation = function(successCallback, errorCallback, options) {
	// Invoke the appropriate callback with a new Position object every time the implementation 
	// determines that the position of the hosting device has changed. 
	this.getCurrentOrientation(successCallback, errorCallback);
	var interval = 1000;
	if (options && !isNaN(options.interval))
		interval = options.interval;
	var that = this;
	return setInterval(function() {
		that.getCurrentOrientation(successCallback, errorCallback);
	}, interval);
};
       
/*
 * Clears the specified orientation watch.
 * @param {String} watchId The ID of the watch returned from #watchOrientation.
 */     
Orientation.prototype.clearWatch = function(watchId) {
	clearInterval(watchId);
};
  
/*
 * This class encapsulates the possible orientation values.
 * @constructor
 */  
function DisplayOrientation() {
	this.code = null;
	this.message = "";
};

DisplayOrientation.PORTRAIT = 0;
DisplayOrientation.REVERSE_PORTRAIT = 1;
DisplayOrientation.LANDSCAPE_LEFT_UP = 2;
DisplayOrientation.LANDSCAPE_RIGHT_UP = 3;
DisplayOrientation.FACE_UP = 4;
DisplayOrientation.FACE_DOWN = 5;

if (typeof navigator.orientation == "undefined") navigator.orientation = new Orientation();

function Position(coords) {
	this.coords = coords;
    this.timestamp = new Date().getTime();
};

function Coordinates(lat, lng, alt, acc, head, vel, altacc) {
	/*
	 * The latitude of the position.
	 */
	this.latitude = lat;
	/*
	 * The longitude of the position,
	 */
	this.longitude = lng;
	/*
	 * The accuracy of the position.
	 */
	this.accuracy = acc;
	/*
	 * The altitude of the position.
	 */
	this.altitude = alt;
	/*
	 * The direction the device is moving at the position.
	 */
	this.heading = head;
	/*
	 * The velocity with which the device is moving at the position.
	 */
	this.speed = vel;
	/*
	 * The altitude accuracy of the position.
	 */
	this.altitudeAccuracy = (typeof(altacc) != 'undefined') ? altacc : null;
};

/*
 * This class specifies the options for requesting position data.
 * @constructor
 */
function PositionOptions() {
	/*
	 * Specifies the desired position accuracy.
	 */
	this.enableHighAccuracy = true;
	/*
	 * The timeout after which if position data cannot be obtained the errorCallback
	 * is called.
	 */
	this.timeout = 10000;
};

/*
 * This class contains information about any GSP errors.
 * @constructor
 */
function PositionError() {
	this.code = null;
	this.message = "";
};

PositionError.UNKNOWN_ERROR = 0;
PositionError.PERMISSION_DENIED = 1;
PositionError.POSITION_UNAVAILABLE = 2;
PositionError.TIMEOUT = 3;

function Service() {
	
};

Service.prototype.Request = function (uri, params) {
	var req = new PalmServiceBridge();
	var url = uri + "/" + (params.method || "");
	req.url = url;

	this.req = req;
	this.url = url;
	this.params = params || {};
	
	this.call(params);
	
	return this;
};

Service.prototype.call = function(params) {
	var onsuccess = null;
	var onfailure = null;
	var oncomplete = null;

	if (typeof params.onSuccess === 'function')
		onsuccess = params.onSuccess;

	if (typeof params.onFailure === 'function')
		onerror = params.onFailure;

	if (typeof params.onComplete === 'function')
		oncomplete = params.onComplete;

	this.req.onservicecallback = callback;

	function callback(msg) {
		var response = JSON.parse(msg);

		if ((response.errorCode) && onfailure)
			onfailure(response);
		else if (onsuccess)
			onsuccess(response);
		
		if (oncomplete)
			oncomplete(response);
	}

	this.data = (typeof params.parameters === 'object') ? JSON.stringify(params.parameters) : '{}';

	this.req.call(this.url, this.data);
}

if (typeof navigator.service == "undefined") navigator.service = new Service();

/*
 * This class provides access to the device SMS functionality.
 * @constructor
 */
function Sms() {

    };

/*
 * Sends an SMS message.
 * @param {Integer} number The phone number to send the message to.
 * @param {String} message The contents of the SMS message to send.
 * @param {Function} successCallback The function to call when the SMS message is sent.
 * @param {Function} errorCallback The function to call when there is an error sending the SMS message.
 * @param {PositionOptions} options The options for accessing the GPS location such as timeout and accuracy.
 */
Sms.prototype.send = function(number, message, successCallback, errorCallback, options) {
    try {
        this.service = navigator.service.Request('palm://com.palm.applicationManager', {
            method: 'launch',
            parameters: {
                id: "com.palm.app.messaging",
                params: {
                    composeAddress: number,
                    messageText: message
                }
            }
        });
        successCallback();
    } catch(ex) {
        errorCallback({
            name: "SMSerror",
            message: ex.name + ": " + ex.message
        });
    }
};

if (typeof navigator.sms == "undefined") navigator.sms = new Sms();

/*
 * This class provides access to the telephony features of the device.
 * @constructor
 */
function Telephony() {
    this.number = "";
};

/*
 * Calls the specifed number.
 * @param {Integer} number The number to be called.
 */
Telephony.prototype.send = function(number) {
    this.number = number;
    this.service = navigator.service.Request('palm://com.palm.applicationManager', {
        method: 'open',
        parameters: {
            target: "tel://" + number
        }
    });
};

if (typeof navigator.telephony == "undefined") navigator.telephony = new Telephony();

function Window() {

    };

/*
 * This is a thin wrapper for 'window.open()' which optionally sets document contents to 'html', and calls 'PalmSystem.stageReady()'
 * on your new card. Note that this new card will not come with your framework (if any) or anything for that matter.
 * @param {String} url
 * @param {String} html
 * Example:
 *		navigator.window.newCard('about:blank', '<html><body>Hello again!</body></html>');
 */
Window.prototype.newCard = function(url, html) {
    var win = window.open(url || "");
    if (html)
        win.document.write(html);
    win.PalmSystem.stageReady();
};

/*
 * Enable or disable full screen display (full screen removes the app menu bar and the rounded corners of the screen).
 * @param {Boolean} state
 * Example:
 *		navigator.window.setFullScreen(true);
 */
Window.prototype.setFullScreen = function(state) {
    // valid state values are: true or false
    PalmSystem.enableFullScreenMode(state);
};

/*
 * used to set the window properties of the WebOS app
 * @param {Object} props
 * Example:
 * 		private method used by other member functions - ideally we shouldn't call this method
 */
Window.prototype.setWindowProperties = function(props) {
    if (typeof props === 'object')
        navigator.windowProperties = props;

    PalmSystem.setWindowProperties(props || this.windowProperties);
};

/*
 * Enable or disable screen timeout. When enabled, the device screen will not dim. This is useful for navigation, clocks or other "dock" apps.
 * @param {Boolean} state
 * Example:
 *		navigator.window.blockScreenTimeout(true);
 */
Window.prototype.blockScreenTimeout = function(state) {
    navigator.windowProperties.blockScreenTimeout = state;
    this.setWindowProperties();
};

/*
 * Sets the lightbar to be a little dimmer for screen locked notifications.
 * @param {Boolean} state
 * Example:
 *		navigator.window.setSubtleLightbar(true);
 */
Window.prototype.setSubtleLightbar = function(state) {
    navigator.windowProperties.setSubtleLightbar = state;
    this.setWindowProperties();
};

if (typeof navigator.window == 'undefined') navigator.window = new Window();

/*
 * Object for storing WebOS window properties
 */
function WindowProperties() {
    blockScreenTimeout = false;
    setSubtleLightbar = false;
    fastAccelerometer = false;
};

if (typeof navigator.windowProperties == 'undefined') navigator.windowProperties = new WindowProperties();(function(window) {

    /**
     * Do not use thumbs.js on touch-enabled devices
     * 
     * Thanks to Jesse MacFadyen (purplecabbage):
     * https://gist.github.com/850593#gistcomment-22484
     */
    try {
        document.createEvent('TouchEvent');
        return;
    }
    catch(e) {
    }

    /**
     * Map touch events to mouse events
     */
    var eventMap = {
        'mousedown': 'touchstart',
        'mouseup':   'touchend',
        'mousemove': 'touchmove'
    };

    /**
     * Fire touch events
     *
     * Monitor mouse events and fire a touch event on the
     * object broadcasting the mouse event. This approach
     * likely has poorer performance than hijacking addEventListener
     * but it is a little more browser friendly.
     */
    window.addEventListener('load', function() {
        for (var key in eventMap) {
            document.body.addEventListener(key, function(e) {
                // Supports:
                //   - addEventListener
                //   - setAttribute
                var event = createTouchEvent(eventMap[e.type], e);
                e.target.dispatchEvent(event);

                // Supports:
                //   - element.ontouchstart
                var fn = e.target['on' + eventMap[e.type]];
                if (typeof fn === 'function') fn(e);
            }, false);
        }
    }, false);

    /**
     * Utility function to create a touch event.
     *
     * @param  name  {String} of the event
     * @return event {Object}
     */
    var createTouchEvent = function(name, e) {
        var event = document.createEvent('MouseEvents');

        event.initMouseEvent(
            name,
            e.bubbles,
            e.cancelable,
            e.view,
            e.detail,
            e.screenX,
            e.screenY,
            e.clientX,
            e.clientY,
            e.ctrlKey,
            e.altKey,
            e.shiftKey,
            e.metaKey,
            e.button,
            e.relatedTarget
        );

        return event;
    };

})(window);
