var MapshellAssistant = Class.create({ 

	initialize: function() {
		// determines what will happen on back gesture
		// when true, card the app else instruct webview to go back
		this.goBack = false;
		this.spinnerModel = {spinning: false};
		
		// event handlers
		this._onWebViewCreatePageH = this._onWebViewCreatePage.bind(this);
		this._onWebViewMimeNotSupportedH = this._onWebViewMimeNotSupported.bind(this)
		this._onWebViewMimeHandoffH = this._onWebViewMimeHandoff.bind(this);
		this._onWebViewLoadProgressH = this._onWebViewLoadProgress.bind(this);
		this._onWebViewLoadStoppedH = this._onWebViewLoadStopped.bind(this);
		this._onWebViewLoadFailedH = this._onWebViewLoadFailed.bind(this);
		this._onWebViewTitleUrlChangedH = this._onWebViewTitleUrlChanged.bind(this);
		this._onAdapterConnectH = this._onAdapterConnect.bind(this);
		this._onAdapterDisconnectH = this._onAdapterDisconnect.bind(this);
		
		/*
		var curr = new Date();
		console.log("@@@@@@@@@@@@@@@@@@@ init diff: " + (curr.getTime() - timer.getTime()));
		console.log("@@@@@@@@@@@@@@@@@@@ init total: " + (curr.getTime() - total.getTime()));
		timer = new Date();
		*/
	},

	setup: function() {
		/*
		var curr = new Date();
		console.log("@@@@@@@@@@@@@@@@@@@ setup diff: " + (curr.getTime() - timer.getTime()));
		console.log("@@@@@@@@@@@@@@@@@@@ setup total: " + (curr.getTime() - total.getTime()));
		timer = new Date();
		*/
		
		var appMenuAttrs = {
			omitDefaultItems: true
		};
		this.appMenuModel = {
			visible: true,
			items: [Mojo.Menu.editItem]
		};	
		this.controller.setupWidget(Mojo.Menu.appMenu, appMenuAttrs, this.appMenuModel);	
		
		// setup spinner
		this.controller.setupWidget('disconnected_spinner', 
			{spinnerSize: Mojo.Widget.spinnerLarge}, this.spinnerModel);
		
		Mojo.Log.info("Maps setup: screen size %d x %d", this.controller.window.innerWidth, this.controller.window.innerHeight);
	    var attr = {
			virtualpagewidth: this.controller.window.innerWidth,
			virtualpageheight: this.controller.window.innerHeight, 
			useMouseEvents: true,
			showClickedLink: false, 
		};
	
		this.controller.setupWidget('webview', attr, {});
		
		// setup event listeners
		this.controller.listen('webview', Mojo.Event.webViewCreatePage, this._onWebViewCreatePageH);
		this.controller.listen('webview', Mojo.Event.webViewMimeNotSupported, this._onWebViewMimeNotSupportedH);
		this.controller.listen('webview', Mojo.Event.webViewMimeHandoff, this._onWebViewMimeHandoffH);
		this.controller.listen('webview', Mojo.Event.webViewLoadProgress, this._onWebViewLoadProgressH);
		this.controller.listen('webview', Mojo.Event.webViewLoadStopped, this._onWebViewLoadStoppedH);	
		this.controller.listen('webview', Mojo.Event.webViewLoadFailed, this._onWebViewLoadFailedH);	
		this.controller.listen('webview', Mojo.Event.webViewTitleUrlChanged, this._onWebViewTitleUrlChangedH);
		this.controller.listen('webview', Mojo.Event.webViewServerConnect, this._onAdapterConnectH);
		this.controller.listen('webview', Mojo.Event.webViewServerDisconnect, this._onAdapterDisconnectH);
	},
	
	cleanup: function() {
		// clear event listeners
		this.controller.stopListening('webview', Mojo.Event.webViewCreatePage, this._onWebViewCreatePageH);
		this.controller.stopListening('webview', Mojo.Event.webViewMimeNotSupported, this._onWebViewMimeNotSupportedH);
		this.controller.stopListening('webview', Mojo.Event.webViewMimeHandoff, this._onWebViewMimeHandoffH);
		this.controller.stopListening('webview', Mojo.Event.webViewLoadProgress, this._onWebViewLoadProgressH);
		this.controller.stopListening('webview', Mojo.Event.webViewLoadStopped, this._onWebViewLoadStoppedH);	
		this.controller.stopListening('webview', Mojo.Event.webViewLoadFailed, this._onWebViewLoadFailedH);	
		this.controller.stopListening('webview', Mojo.Event.webViewTitleUrlChanged, this._onWebViewTitleUrlChangedH);
		this.controller.stopListening('webview', Mojo.Event.webViewServerConnect, this._onAdapterConnectH);	
		this.controller.stopListening('webview', Mojo.Event.webViewServerDisconnect, this._onAdapterDisconnectH);
	},
	
	activate: function() {
		Mojo.Log.info("Maps: mapshell-assistant: activate")
		Mojo.Log.info("Maps: setting focus on webview widget: %s", this.controller.get('webview'))
		this.controller.setInitialFocusedElement(this.controller.get('webview'));
	},

	ready: function(event) {	
		/*
		var curr = new Date();
		console.log("@@@@@@@@@@@@@@@@@@@ ready diff: " + (curr.getTime() - timer.getTime()));
		console.log("@@@@@@@@@@@@@@@@@@@ ready total: " + (curr.getTime() - total.getTime()));
		timer = new Date();
		*/
		
		var wb = this.controller.get('webview');
		
		if (wb === null) {
			Mojo.Log.error("couldn't find web adapter");
		} else {
			// store web view widget in the globals
			// so that we can change the URL on potential relaunch
			AppAssistant.webViewWidget = wb;

			// set load timeout: if we don't get any load progress
			// give up and show no-wifi scene
			// we only track the load time first time this scene is pushed
			this.loadTimeoutId = setTimeout( function(){
						this.handleLoadTimedOut();
					}.bind(this), this.loadTimeout);
			
			Mojo.Log.info("Maps: mapshell-assistant ready URL %s", AppAssistant.url);
			AppAssistant.webViewWidget.mojo.openURL(AppAssistant.url);
		}
	},
	 
	// try to parse out location parameter from the URL and store it in a cookie
	// to be used when we are launched from universal search but current location is not available
	_onWebViewTitleUrlChanged: function(event) {
		Mojo.Log.info("Maps App: _onWebViewUrlChanged title: %s, url: %s", event.title, event.url);
	},
	
	_onWebViewLoadProgress: function(event) {
		Mojo.Log.info("Maps App: _onWebViewLoadProgress %s", event.progress);
	
		if (this.loadTimeoutId && parseInt(event.progress) == 100) {
			/*
			var curr = new Date();
			console.log("@@@@@@@@@@@@@@@@@@@ _onWebViewLoadProgress at 100% diff:" + (curr.getTime() - timer.getTime()));
			console.log("@@@@@@@@@@@@@@@@@@@ _onWebViewLoadProgress at 100% total: " + (curr.getTime() - total.getTime()));
			timer = new Date();
			*/
			Mojo.Log.info("Maps App: _onWebViewLoadProgress transition & clear the timeout");
			// show the scene: unlock transition and 
			// cancel the progress timout
			AppAssistant.prototype.doneLaunch();
			clearTimeout(this.loadTimeoutId);
			this.loadTimeoutId = null;
		}
	},
	
	_onWebViewLoadStopped: function(event) {
		Mojo.Log.info("Maps App: _onWebViewLoadStopped");
		
		// just in case we never got the progress 
		if (this.loadTimeoutId) {
			Mojo.Log.info("Maps App: _onWebViewLoadStopped transition & clear the timeout");
			// show the scene: unlock transition and 
			// cancel the progress timout
			AppAssistant.prototype.doneLaunch();
			clearTimeout(this.loadTimeoutId);
			this.loadTimeoutId = null;
		}
	},
	
	_onWebViewLoadFailed: function(event){
		Mojo.Log.info("Maps App: _onWebViewLoadFailed");
		
		// just in case we never got the progress 
		if (this.loadTimeoutId) {
			Mojo.Log.info("Maps App: _onWebViewLoadFailed call timeout handler");
			// cancel the progress timout and call timout handler
			clearTimeout(this.loadTimeoutId);
			this.loadTimeoutId = null;
			this.handleLoadTimedOut();
		}
	},
	
	_onWebViewCreatePage: function(event) {
		Mojo.Log.info("Maps App: _onWebViewCreatePage %s", event.pageIdentifier);
		this.controller.serviceRequest('palm://com.palm.applicationManager', 
			{
				method: 'open',
				parameters: 
				{
					id: 'com.palm.app.browser',
					params: {pageIdentifier: event.pageIdentifier}
				}
			});
	},

 	// TODO all event handlers are separate functions for now
	// for debugging purposes. They'll eventually be merged into one handler
	_onWebViewMimeNotSupported: function(event) {
		Mojo.Log.info("Maps App: _onWebViewMimeNotSupported %s, %s", event.url, event.mimeType);
		var url = event.url;
		
		if (url == "mapscmd:cardmode") {
			this.goBack = false;
		}
		else if (url == "mapscmd:historyactive") {
			this.goBack = true;
		}
		else if (url.indexOf("mapscmd:ll=") >= 0) {
			Mojo.Log.info("Maps App: _onWebViewMimeNotSupported mapscmd:ll=");
			// parse out location
			var ll = url.substr(url.indexOf("mapscmd:ll=") + "mapscmd:ll=".length);
			var arr = ll.split(",");
			Mojo.Log.info("Maps App: _onWebViewMimeNotSupported ll param: %s", arr);
			
			if (arr[0] && arr[1]) {
				// save location in a cookie to be used with universal search
				var cookie = new Mojo.Model.Cookie("maps-lastviewport");
				var storedCookie = cookie.get();
				if (storedCookie) {
					Mojo.Log.info("Maps: _onWebViewMimeNotSupported cookie already exists, removing...");
					cookie.remove();
				}
				Mojo.Log.info("Maps: _onWebViewMimeNotSupported stored cookie maps-lastviewport");
				if (arr[2]) {
					cookie.put({lat: arr[0], lng: arr[1], acc: arr[2]});
				}
				else {
					cookie.put({lat: arr[0], lng: arr[1]});
				}
			}
		}
		else {
			this.handOffURL(url);
		}
	},
	
	_onWebViewMimeHandoff: function(event){
		Mojo.Log.info("Maps App: _onWebViewMimeHandoff %s, %s", event.url, event.mimeType);
		this.handOffURL(event.url);
	},
	
	handOffURL: function(url) {
		Mojo.Log.info("Maps App: handOffURL %s", url);
		var params = {target: url};
		this.controller.serviceRequest('palm://com.palm.applicationManager', {
				method: 'open',
				parameters: params,
				onSuccess: function() {
					Mojo.Log.info("Successfully handed off '%s'", url);
				},
				onFailure: function(msg) {
					Mojo.Log.error("Failure handing off '%s', msg:'%s'", url, msg);
				}
			});
	},
	
	_onAdapterConnect: function() {
		Mojo.Log.info("Maps: _onAdapterConnect connected to the server, reload %s", AppAssistant.url);
		// hide the spinner
		this.controller.hideWidgetContainer('spinner_scene');
		this.controller.get('spinner_scene').hide();
		this.spinnerModel.spinning = false;
		this.controller.modelChanged(this.spinnerModel);
		
		var wb = this.controller.get('webview');
		if (wb) {
			// reload last URL, TODO for some reason reload doesn't work
			// wb.mojo.reloadPage();
			wb.mojo.openURL(AppAssistant.url);
		}
	},
	
	_onAdapterDisconnect: function() {
		Mojo.Log.error("Maps: _onAdapterDisconnect disconnected from the server");
		// allow transition to happen in case browser died 
		// before giving us any load progress
		AppAssistant.prototype.doneLaunch();
		
		// show the spinner while waiting for browser server to come back
		this.controller.get('spinner_scene').show();
		this.controller.showWidgetContainer('spinner_scene');
		this.spinnerModel.spinning = true;
		this.controller.modelChanged(this.spinnerModel);
	},
	

	handleCommand: function(event) {
		if (event.type == Mojo.Event.back) {
			if (this.goBack) {
				Mojo.Log.info("Maps: handleCommand goBack");
				event.stop();
				var wb = this.controller.get('webview');
				wb.mojo.goBack();	
			}
			else {
				Mojo.Log.info("Maps: handleCommand do nothing... app should go to card mode");
			}
		}
	},
	
	handleLoadTimedOut: function() {
		Mojo.Log.info("Maps App: handleLoadTimedOut");
		Mojo.Controller.stageController.popScene();
		Mojo.Controller.stageController.pushScene("no-wifi");
	},
	
	loadTimeout: 60000, // 60 seconds
});
