/*
 * Copyright 2008-2009 Palm, Inc. All rights reserved.
 */

function StartpageAssistant(params) {

	this._destinationUrl = params.lastUrl;
	this._orientation = params.orientation || 'up';
	this._bookmarks = [];
	this._maxShowCount = 12;
	this.store = new BookmarkStore({
		database: Mojo.Controller.appController.assistant.getDatabase()
	});

	this._onStartPageTapHandler = this._onStartPageTap.bind(this);
	this._onKeyDownEventHandler = this._onKeyDownEvent.bind(this);
	this._onCardActivateHandler = this._onCardActivate.bind(this);
	this._onCardDeactivateHandler = this._onCardDeactivate.bind(this);
}

StartpageAssistant.prototype.setup = function() {

	this._updateOrientation();

	// Allow override of 'back' gesture in landscape mode.
	this.controller.useLandscapePageUpDown(true);

	// Listen for scene scope keyboard events.
	this.controller.listen(this.controller.sceneElement, Mojo.Event.keydown, this._onKeyDownEventHandler);

	// Create the address bar
	this._addressBar = new AddressBar(this.controller);
	this._addressBar.setup({
		onPropertyChange: this._onAddressBarPropertyChange.bind(this),
		orientation: this._orientation,
		visible: true,
		onSelect: this._onAddressBarSelect.bind(this),
		onEnableSceneScroller: function(enable){}
	});

	// Setup the application menus.
	this.appMenuModel = {
		visible: true,
		items: [
			MenuData.ApplicationMenu.NewCard,
			MenuData.ApplicationMenu.AddBookmark,
			{
				label: $L("Page"),
				items: [
					MenuData.ApplicationMenu.AddToLauncher,
					MenuData.ApplicationMenu.SharePage]
			},
			MenuData.ApplicationMenu.ShowBookmarks,
			MenuData.ApplicationMenu.ShowHistory]
	};

	this.controller.setupWidget(Mojo.Menu.appMenu, undefined, this.appMenuModel);

	this._backModel = {
		label: MenuData.NavigationMenu.Back.label,
		icon: MenuData.NavigationMenu.Back.icon,
		command: MenuData.NavigationMenu.Back.command
	};

	this._forwardModel = {
		label: MenuData.NavigationMenu.Forward.label,
		icon: MenuData.NavigationMenu.Forward.icon,
		command: MenuData.NavigationMenu.Forward.command
	};

	this.cmdMenuModel = {
		visible: true,
		items: [
			this._backModel,
			this._forwardModel,
			{}]};

	this.controller.setupWidget(Mojo.Menu.commandMenu, {menuClass:'no-fade'}, this.cmdMenuModel);
};

StartpageAssistant.prototype.cleanup = function() {

};

StartpageAssistant.prototype._updateOrientation = function() {
	
	var targetWindow = this.controller.window;
	if (targetWindow.PalmSystem && targetWindow.PalmSystem.setWindowOrientation) {
		this._orientation = Mojo.Controller.appController.getScreenOrientation();
		targetWindow.PalmSystem.setWindowOrientation(this._orientation);
	}
};

StartpageAssistant.prototype._onAddressBarSelect = function(selection) {

	if (selection instanceof UrlReference) {
		// It's a bookmark
		this._openBookmark(selection);
	} else {
		// It's a simple string URL otherwise.
		this._openUrl(selection);
	}
};

StartpageAssistant.prototype._onKeyDownEvent = function(event) {

	if ((this._orientation === 'up') && !this._addressBar.hasFocus()) {
		// Only jump to the address bar IF we are a valid event that is
		// allowed to trigger the bar.
		if (this._addressBar.isAGotoAddressBarEvent(event.originalEvent)) {

			// Dismiss any currently viewed searchlist
			this._addressBar.closeSearchResults();

 			// Create/Show the adress bar and set input
			this._addressBar.setAddressAndTitle('', '');
			this._addressBar.enableUrlView();
			this._addressBar.show();
			this._addressBar.focus();
		}
	}
};

StartpageAssistant.prototype.ready = function() {

	var self = this;
	
	// Set the initial orientation.
	this._setOrientation(this._orientation);
	
	// Define the network alert function that's run when we have no
	// network available.
	var netAlert = function(params){

		// Show a custom network alert dialog.
		self.controller.showAlertDialog({
			
			onChoose: function(value) {
	
				if (value === 'help') {
					AppAssistant.launchNetworkHelp();
				}
			},
			
			title: $L('No Internet Connection'),
			message: $L('Please enable networking before using the browser.'),
			choices: [{
					label: $L('Help'),
					value: 'help',
					type: 'dismiss',
					buttonClass: 'secondary'
				}, {
					label: $L('OK'),
					value: 'OK',
					type: 'alert',
					buttonClass: 'primary'
				}]
		});
		
		// We have shown a dialog so defocus anything on the scene to avoid
		// input.
		self._addressBar.blur();		
	};

	AppAssistant.Network.addNetworkCheckedMethods({
		target: this,
		methods: ['_openUrl', '_processForwardCommand', '_openBookmark'],
		onNetworkDown: netAlert
	});

	// On first launch we alway attempt to connect to the network if we
	// are not online.
	if (!AppAssistant.Network.online) {
		
		ConnectionWidget.connect({
			type: 'data',
			onSuccess: function(response){
				// If the connection widget was previously cancelled and we
				// are under its internal timeout limit then popup the network
				// alert dialog.
				if (response === "WiFi-UserCancelled") {
					// Show the simple alert
					netAlert({});
				}
			}
		}, self.controller.stageController);
	}
	
	this._addressBar.closeSearchResults();
};

StartpageAssistant.prototype.activate = function(message) {

	// Update the current orientaton
	this._updateOrientation();

	// Listen for taps on the start page icons
	Mojo.Event.listen(this.controller.get('bookmarks'), Mojo.Event.tap, this._onStartPageTapHandler, true);
	this.controller.document.addEventListener(Mojo.Event.activate, this._onCardActivateHandler, false);
	this.controller.document.addEventListener(Mojo.Event.deactivate, this._onCardDeactivateHandler, false);

	this._isActivated = true;	
	this._addressBar.enableUrlView();
	if (message) {
		switch (message.type) {

			case 'history':
				this._openUrl.bind(this, message.payload).defer();
				break;

			case 'bookmarks':
				this._openBookmark.bind(this, message.payload).defer();
				break;

			default:
				this.refreshView();
				this._addressBar.show();
				this._addressBar.startObserving();
		}
	} else {

		this.refreshView();
		this._addressBar.show();
		this._addressBar.startObserving();
	}
};

StartpageAssistant.prototype.deactivate = function() {

	// Stop listening for taps on the start page icons
	Mojo.Event.stopListening(this.controller.get('bookmarks'), Mojo.Event.tap, this._onStartPageTapHandler, true);

	// Cleanup focus handlers.
	this.controller.document.removeEventListener(Mojo.Event.activate, this._onCardActivateHandler, false);
	this.controller.document.removeEventListener(Mojo.Event.deactivate, this._onCardDeactivateHandler, false);

	this._isActivated = false;
	this._addressBar.stopObserving();
	this._addressBar.closeSearchResults();
};

StartpageAssistant.prototype._refreshControls = function() {

	this.cmdMenuModel.items = $A();

	// If the assistant was constructed with a destination URL
	// then we need to activate and enable the forward button.
	if (this._destinationUrl) {
		this._backModel.disabled = true;
		this.cmdMenuModel.items.push(this._backModel);
		this._forwardModel.disabled = false;
		this.cmdMenuModel.items.push(this._forwardModel);
	} else {
		this.cmdMenuModel.items.push({});
		this.cmdMenuModel.items.push({});
	}
	this.cmdMenuModel.items.push({});

	this.controller.modelChanged(this.cmdMenuModel);
};

StartpageAssistant.prototype.orientationChanged = function(orientation) {

	// Switch the orientation of the menu spacer or other components..
	var targetWindow = this.controller.window;
	if (this._orientation === orientation) {
		return;
	}

	// Update the web browser UI components to reflect the new orientation.
	// Setting 'free' after an override doesn't currently work so we are
	// always explicit.
	this._orientation = orientation;
	if (targetWindow.PalmSystem && targetWindow.PalmSystem.setWindowOrientation && this._isActivated) {
		// Calling this will cause another orientationChanged event to we
		// protect against recursion by testing current orientation against
		// the new setting on re-entry.
		targetWindow.PalmSystem.setWindowOrientation(this._orientation);
	}

	this._setOrientation(this._orientation);
};

StartpageAssistant.prototype._setOrientation = function(orientation) {

	try {
		// Notify the URL bar of orientation change
		this._addressBar.setOrientation(orientation);
		
		// 3 modes - portrait-up, landscape and portrait down  - Need to think
		// about this a little more to encapsulate it better.
		var have_bookmarks = this.controller.get('have-bookmarks');
		if (orientation === 'left' || orientation === 'right') {
			// Force a hide of any visible spacer.
			have_bookmarks.addClassName('landscape');
			have_bookmarks.removeClassName('down');
		} else if (orientation === 'down') {
			// Force a hide of any visible spacer.
			have_bookmarks.removeClassName('landscape');
			have_bookmarks.addClassName('down');
		}
		else {
			have_bookmarks.removeClassName('landscape');
			have_bookmarks.removeClassName('down');
			// Special case is the start page. If we get an orientation
			// change in the startpage we have to redisplay the URL bar
			this._addressBar.show();
			this._addressBar.focus();
		}
	}
	catch (e) {
		Mojo.Log.logException(e, "StartpageAssistant#_setOrientation");
	}
};

StartpageAssistant.prototype._onCardActivate = function(event) {

	// Update the startpage. It could of been changed by another
	// instance. 
	this.refreshView();
};

StartpageAssistant.prototype._onCardDeactivate = function(event) {

};

StartpageAssistant.prototype.handleCommand = function(event) {

	switch (event.type) {
		case Mojo.Event.back:
			// If the searchlist is showing then hide it.
			// If it's not showing then switch to card view.
			if (this._addressBar.areSearchResultsVisible()) {
				this._addressBar.closeSearchResults();
				event.preventDefault();
			}
			else if (this._addressBar.hasFocus()) {
				this._addressBar.enableTitleView();
				event.preventDefault();
			} else {
				this.controller.stageController.deactivate();
			}
			event.stopPropagation();

			break;
			
		case Mojo.Event.forward: 

			// NOTE: According to HI we should keep this simple and 
			// just move forward.
			if (this._destinationUrl) {
				this._addressBar.enableTitleView();
				this._addressBar.closeSearchResults();

				event.preventDefault();
				event.stopPropagation();
				this._processForwardCommand();			
			}
			break;

		case Mojo.Event.command:

			switch (event.command) {

				case MenuData.ApplicationMenu.ShowHistory.command:
					this._openHistoryView();
					break;

				case MenuData.ApplicationMenu.ShowBookmarks.command:
					this._openBookmarkView();
					break;

				case MenuData.ApplicationMenu.NewCard.command:
					this._openNewBrowser();
					break;

				case MenuData.NavigationMenu.Forward.command:
					this._processForwardCommand();
					break;

				case UrlBar.Menu.TitleTap.command:
					this._processTitleTapCommand();
					break;

				case UrlBar.Menu.Go.command:
					this._processGoCommand();
					break;

				case Mojo.Menu.prefsCmd:
					this._openPreferencesView();
					break;

				case Mojo.Menu.helpCmd:
					this._showHelpCommand();
					break;
			}
			break;

		case Mojo.Event.commandEnable:

			// Standard Application Menu commands.
			if (event.command === Mojo.Menu.prefsCmd ||
				event.command === Mojo.Menu.helpCmd) {

				event.stopPropagation(); // Enable the chosen menuitems
				return;
			}

			// Application specific Applicaiton Menu commands.
			if (event.command === MenuData.ApplicationMenu.SharePage.command) {

				event.preventDefault();
				return;
			}

			if (event.command === MenuData.ApplicationMenu.AddToLauncher.command ||
				event.command === MenuData.ApplicationMenu.AddBookmark.command) {

				event.preventDefault();
				return;
			}
			break;
	}
};

StartpageAssistant.prototype._processForwardCommand = function() {

	this.controller.stageController.popScene({type: 'startpage'});
};

StartpageAssistant.prototype._processTitleTapCommand = function() {

	try {
		this._addressBar.enableUrlView();
		this._addressBar.focus();
		this._addressBar.select();
	} catch (e) {
		Mojo.Log.logException(e, '_processTitleTapCommand');
	}
};

StartpageAssistant.prototype._processGoCommand = function() {

	var value = this._addressBar.getValue();
	if (value) {
		this._openUrl(this._addressBar.convertInputToUrl(value));
	} else {
		// We did nothing so switch focus back to the URL bar
		this._addressBar.focus();
	}
};

StartpageAssistant.prototype.refreshView = function() {

	// Enable/Disable the user navigation controls.
	this._refreshControls();

	// Read the bookmarks and render the content
	this.store.readBookmarks(
		new BookmarkFolder(),
		null,
		this._render.bind(this),
		function() {
			Mojo.Log.error("Error reading bookmarks");
		},
		0,
		this._maxShowCount);
};

StartpageAssistant.prototype._render = function(bookmarkFolder) {

	// Warning:
	// This is the callback to a bookmark request to the bookmarks
	// database. As such it's async so we need to be sure the controller
	// and startpage elements still exist before we try and update.
	// This can happen if switch from a webpage to a startpage and
	// back again in quick succession.
	try {
		if (this.controller) {
			var bookmarksDiv = this.controller.get('bookmarks');
			var no_bookmarks = this.controller.get('no-bookmarks');
			var have_bookmarks = this.controller.get('have-bookmarks');
			if (bookmarksDiv && no_bookmarks && have_bookmarks) {
				var count = 0;
				this._bookmarks = [];

				// We don't load all bookmarks into the start page - just a subset.
				for (var d = 0; d < bookmarkFolder.contents.length && d < this._maxShowCount; d++) {

					var item = bookmarkFolder.contents[d];
					if (item instanceof UrlReference) {

						item.startPageIndex = count++;
						if (!item.title || item.title.empty()) {
							item.title = "&nbsp;";
						}
						else {
							item.title = item.title.escapeHTML();
						}

						this._bookmarks.push(item);
					}
				}

				// Render the bookmarks into a list
				var items = Mojo.View.render({
					collection: this._bookmarks,
					template: 'page/start-page'
				});

				if (count <= 0) {
					no_bookmarks.style.display = 'block';
					have_bookmarks.style.display = 'none';
				}
				else {
					// Insert the bookmarks into the DOM
					bookmarksDiv.update(items);
					no_bookmarks.style.display = 'none';
					have_bookmarks.style.display = 'block';
				}
			}
		}
	}
	catch (e) {
		Mojo.Log.logException(e, "_render");
	}
};

StartpageAssistant.prototype._onStartPageTap = function(event) {

	try {
		// Make sure the tap was on a bookmark (not the space between them)
		if (!event.down.target || !event.down.target.title) {
			return;
		}

		// Open the URL
		this._openBookmark(this._bookmarks[parseInt(event.down.target.title, 10)]);

	} catch (e) {

		Mojo.Log.logException(e, "#_handleStartPageTap()");
	}
};

StartpageAssistant.prototype._onAddressBarPropertyChange = function(propertyChangeEvent) {

	try {
		// With the new TextField widget we can query the action that
		// caused this event on the URL text field by looking at the
		// originalEvent property. Nice.
		var url;
		switch (propertyChangeEvent.type) {

			case 'keyCode':

				url = propertyChangeEvent.value;
				
				// Update the title ...
				this._addressBar.setAddressAndTitle(url, UrlUtil.cleanup(url));

				if (propertyChangeEvent.keyCode === Mojo.Char.enter) {

					// Clear the timers and hide the search list.
					this._addressBar.closeSearchResults();

					// Check we have a URL and if not then don't do anything.
					if (url) {
						this._openUrl(this._addressBar.convertInputToUrl(url));
					}
				}
				break;

			case 'blur':

				// Always switch to title mode on a blur.
				this._addressBar.enableTitleView();
				this._addressBar.closeSearchResults();
				break;

			case 'mojo-property-change':
			
				// Update the title with the new URL resulting from a copy/paste action.
				url = propertyChangeEvent.value;
				this._addressBar.setAddressAndTitle(url, UrlUtil.cleanup(url));
				break;

			default:
				Mojo.Log.warn("Unknown propertyChangeEvent");
				break;
		}
	}
	catch (e) {
		Mojo.Log.logException(e, '_onAddressBarPropertyChange');
	}
};

StartpageAssistant.prototype._openUrl = function(url) {

	// Application could of now been launched as just a startpage so
	// we need to be aware how we should handle open requests.
	this._addressBar.setAddressAndTitle(url, UrlUtil.cleanup(url));
	this._addressBar.enableTitleView();
	if (this._destinationUrl) {
		this.controller.stageController.popScene({
			type: 'startpage',
			payload: url
		});
	}
	else {
		
		this.controller.stageController.swapScene({
				name: 'page',
				transition: Mojo.Transition.crossFade
			}, 
			{
				launchParams: {
					target: url,
					orientation: this._orientation	
				}
			});
	}
};

StartpageAssistant.prototype._openBookmark = function(bookmark) {

	// Application could of now been launched as just a startpage so
	// we need to be aware how we should handle open requests.
	var url = bookmark.url;
	this._addressBar.setAddressAndTitle(url, UrlUtil.cleanup(url));
	this._addressBar.enableTitleView();
	if (this._destinationUrl) {
		this.controller.stageController.popScene({
			type: 'startpage-bookmark',
			payload: bookmark
		});
	}
	else {
		// Currently, a Launch will not handle the update count so we
		// perform this task ourselves before creating the page assistant.
		this.store.updateVisitCount(
			bookmark,
			function() {},
			function() {});

		this.controller.stageController.swapScene({
				name: 'page',
				transition: Mojo.Transition.crossFade
			}, 
			{
				launchParams: {
					target: url,
					bookmark: bookmark,
					orientation: this._orientation	
				}
			});
	}
};

StartpageAssistant.prototype._openBookmarkView = function() {

	var targetWindow = this.controller.window;
	if (targetWindow.PalmSystem && targetWindow.PalmSystem.setWindowOrientation) {
		targetWindow.PalmSystem.setWindowOrientation("up");
	}

	this.controller.stageController.pushScene('bookmarks', AppAssistant.WebPreferences);
};

StartpageAssistant.prototype._openHistoryView = function() {

	var targetWindow = this.controller.window;
	if (targetWindow.PalmSystem && targetWindow.PalmSystem.setWindowOrientation) {
		targetWindow.PalmSystem.setWindowOrientation('up');
	}

	this.controller.stageController.pushScene('history', AppAssistant.WebPreferences);
};

StartpageAssistant.prototype._openPreferencesView = function(){

	var targetWindow = this.controller.window;
	if (targetWindow.PalmSystem && targetWindow.PalmSystem.setWindowOrientation) {
		targetWindow.PalmSystem.setWindowOrientation('up');
	}

	this.controller.stageController.pushScene('preferences', AppAssistant.WebPreferences);
};

StartpageAssistant.prototype._openNewBrowser = function() {

	var params = {};
	this.controller.serviceRequest('palm://com.palm.applicationManager', {
		method: 'open',
		parameters: {
			'id': 'com.palm.app.browser',
			'params': params
		}
	});
};

StartpageAssistant.prototype._showHelpCommand = function() {

	// Launch the help system.
	AppAssistant.launchHelp();
};
