/*
 * Copyright 2008-2009 Palm, Inc. All rights reserved.
 */
/*global Mojo, Class, $L, UrlBar */
/*jslint rhino:true, undef:true */

function UrlBar(controller) {
	this.controller = controller;

	// Any updates to the URL input field.
	this._onPropertyChangeHandler = this._onPropertyChange.bind(this);
	this._onInputFocusHandler = this._onInputFocus.bind(this);
	this._onInputBlurHandler = this._onInputBlur.bind(this);
	this._onPropertyChange = function(){};
	this._urlBarFocused = false;
	this._enableSSLLock = false;

	// Default orientation is portrait
	this._configOrientation('up');
}

UrlBar.defaultHintText = $L('Enter URL or search terms');

UrlBar.Menu = {

	Go: {
		template: 'page/url-go',
		command: 'urlbar-go-pressed'
	},

	TitleTap: {
		template: 'page/page-title',
		command: 'urlbar-title-tap',
		title: UrlBar.defaultHintText,
		sslDisplay: 'none'
	}
};

UrlBar.prototype.validGotoUrlBarChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$-_.+!*'(),{}|\\^~[]`<>#%\";/?:@&=";

UrlBar.prototype.isAGotoUrlBarKey = function(keycode) {

	// Use the frameworks new API to determine if we have a keycode that is a 
	// candidate for the start of either a URL or a search string.
	return Mojo.Char.isPrintableChar(keycode, false);
};

UrlBar.prototype.setOrientation = function(orientation) {

	if (orientation !== 'up') {
		// In landscape and down we ALWAYS hide the BAR so we make sure it's
		// already hidden by calling' 'hide'.
		this._hidePortrait();
	}

	this._configOrientation(orientation);
};

UrlBar.prototype._configOrientation = function(orientation) {

	if (orientation !== 'up') {
		this.show = this._showNoOp;
		this.hide = this._hideNoOp;
	} else {
		// Default is portrait.
		this.show = this._showPortrait;
		this.hide = this._hidePortrait;
	}

	this._orientation = orientation;
};

UrlBar.prototype.setup = function(properties) {

	var visible = properties.visible || false;
	this._onPropertyChange = properties.onPropertyChange || function(){};
	this._configOrientation(properties.orientation || 'up');

	this.models = {
		urlInput: {
			template: 'page/url-field',
			attr: {
				hintText: UrlBar.defaultHintText,
				modelProperty: 'url',
				modifierState: 'none',
				focusMode: Mojo.Widget.focusInsertMode,
				requiresEnterKey: true,
				textFieldName: "urlbar-textfield-input",
				changeOnKeyPress: true,
				textReplacement: false
			},
			model: {
				url: ''
			},

			width: 271
		},

		// Beware: These are shallow copies.
		title: Object.clone(UrlBar.Menu.TitleTap),
		urlGo: Object.clone(UrlBar.Menu.Go)
	};

	this.controller.setupWidget('urlbar-input',
		this.models.urlInput.attr,
		this.models.urlInput.model);

	this.currentModel = {
		mode: 'url',
		model: {
			visible: visible,
			items:[{items: [this.models.urlInput, this.models.urlGo]}, {}]
		}
	};

	this.controller.setupWidget(Mojo.Menu.viewMenu,
		{menuClass:'no-fade'},
		this.currentModel.model);
};

UrlBar.prototype.cleanup = function() {

};

UrlBar.prototype.setTitle = function(title) {
	
	title = title || UrlBar.defaultHintText;
	this.models.title.title = title;
};

UrlBar.prototype.setUrl = function(url) {
	
	url = url || '';
	this.models.urlInput.model.url = url;
};

UrlBar.prototype.enableTitleView = function() {
	
	// During a model change remove any BLUR observers.
	this._stopObservingFocusBlurs();

	// Model changes cause a blur.
	this._urlBarFocused = false;

	// Force a model change ?
	var menuAssistant = this.controller._menu.assistant;
	var spacerHeight = menuAssistant.viewSpacerHeight;

	this.currentModel.mode = 'title';
	this.currentModel.model.items = [this.models.title];

	menuAssistant.viewSpacerHeight = 0;
	this.models.title.sslDisplay = this._enableSSLLock ? 'block' : 'none';
	this.controller.modelChanged(this.currentModel.model);

	// Add the observers
	this.startObserving();	
};

UrlBar.prototype.enableUrlView = function() {
	
	// During a model change remove any BLUR observers.
	this._stopObservingFocusBlurs();

	// Model changes cause a blur
	this._urlBarFocused = false;

	// Force a model change ?
	var menuAssistant = this.controller._menu.assistant;
	var spacerHeight = menuAssistant.viewSpacerHeight;

	this.currentModel.mode = 'url';
	this.currentModel.model.items = [{items: [this.models.urlInput, this.models.urlGo]}, {}];

	menuAssistant.viewSpacerHeight = 0;
	this.controller.modelChanged(this.currentModel.model);
	this.controller.modelChanged(this.models.urlInput.model);

	// If we have a URL enable the Go button.
	var url = this.models.urlInput.model.url;
	this._enableGoButton((url && (url.length > 0)));

	// Add the observers
	this.startObserving();
};

UrlBar.prototype.enableSSLLock = function(enable) {

	this._enableSSLLock = enable;
	this._updateSSLLock();
};

UrlBar.prototype._updateSSLLock = function() {

	this.models.title.sslDisplay = this._enableSSLLock ? 'block' : 'none';
	if (this.currentModel.mode !== 'url') {
		this.controller.modelChanged(this.currentModel.model);
	}
};

UrlBar.prototype.startObserving = function() {

	if (this.currentModel.mode === 'url') {
		this._addAllInputObservers();
	} else {
		this._addAllTitleObservers();
	}
};

UrlBar.prototype.stopObserving = function() {

	if (this.currentModel.mode === 'url') {
		this._removeAllInputObservers();
	} else {
		this._removeAllTitleObservers();
	}
};

UrlBar.prototype._stopObservingFocusBlurs = function() {

	if (this.currentModel.mode === 'url') {
		this._removeInputFocusBlurObservers();
	} else {
		this._removeTitleFocusBlurObservers();
	}
};

UrlBar.prototype._addAllTitleObservers = function() {

	var title = this.controller.get('urlbar-title');
	if (title) {
		title.observe(Mojo.Event.tap, this._onTitleTapHandler);
	}

};

UrlBar.prototype._removeAllTitleObservers = function() {

	var title = this.controller.get('urlbar-title');
	if (title) {
		title.stopObserving(Mojo.Event.tap, this._onTitleTapHandler);
	}
};

UrlBar.prototype._addAllInputObservers = function(){

	var element;
	var input = this.controller.get('urlbar-input');
	if (input) {
		input.observe(Mojo.Event.propertyChange, this._onPropertyChangeHandler);

		// Observe the textarea inside it.
		element = input.querySelector('[name="urlbar-textfield-input"]');
		if (element) {
			element.observe('focus', this._onInputFocusHandler);
			element.observe('blur', this._onInputBlurHandler);
		}
	}
};

UrlBar.prototype._removeAllInputObservers = function() {

	var element;
	var input = this.controller.get('urlbar-input');
	if (input) {
		input.stopObserving(Mojo.Event.propertyChange, this._onPropertyChangeHandler);
		element = input.querySelector('[name="urlbar-textfield-input"]');
		if (element) {
			element.stopObserving("focus", this._onInputFocusHandler);
			element.stopObserving("blur", this._onInputBlurHandler);
		}
	}
};

UrlBar.prototype._removeTitleFocusBlurObservers = function() {
	// Do nothing .
};

UrlBar.prototype._removeInputFocusBlurObservers = function() {

	var element;
	var input = this.controller.get('urlbar-input');
	if (input) {

		element = input.querySelector('[name="urlbar-textfield-input"]');
		if (element) {

			element.stopObserving("focus", this._onInputFocusHandler);
			element.stopObserving("blur", this._onInputBlurHandler);
		}
	}
};

UrlBar.prototype._activateGoButton = function(activate) {

	var value;
	var goButton = this.controller.select('div.urlbar-menu-go-button');
	if (goButton && goButton[0] && this.currentModel.mode === 'url') {
		if (activate) {
			goButton[0].addClassName('active');
			this._enableGoButton(!!this.getValue());

		} else {
			goButton[0].removeClassName('active');
			goButton = this.controller.select('div.urlbar-go-button');
			if (goButton && goButton[0]) {
				this._enableGoButton(!!this.getValue());
			}
		}
	}
};

UrlBar.prototype._enableGoButton = function(enabled) {

	var goButtons = this.controller.select('div.urlbar-go-button');
	if (goButtons && goButtons[0] && this.currentModel.mode === 'url') {
		if (enabled) {
			goButtons[0].removeClassName('disabled');
			goButtons[0].addClassName('enabled');
		} else {
			goButtons[0].removeClassName('enabled');
			goButtons[0].addClassName('disabled');
		}
	}
};

UrlBar.prototype._onPropertyChange = function(event) {

	try {
		// We use the property change handler to determine the state of
		// the Go buttons.
		this._enableGoButton(event.value.length > 0);

		// Now we call the listener
		this._onPropertyChange(event);
	}
	catch (e) {
		Mojo.Log.logException(e, 'UrlBar#_onPropertyChange');
	}
};

// Default orientation is portrait mode.
UrlBar.prototype.show = UrlBar.prototype._showPortrait;
UrlBar.prototype.hide = UrlBar.prototype._hidePortrait;

UrlBar.prototype._showPortrait = function() {

	var menuAssistant = this.controller._menu.assistant;
	var spacerHeight = menuAssistant.viewSpacerHeight;

	menuAssistant.viewSpacerHeight = 0;
	this.controller.setMenuVisible(Mojo.Menu.viewMenu, true);
};

UrlBar.prototype._hidePortrait = function() {

	var menuAssistant = this.controller._menu.assistant;
	var spacerHeight = menuAssistant.viewSpacerHeight;

	menuAssistant.viewSpacerHeight = 0;
	this.controller.setMenuVisible(Mojo.Menu.viewMenu, false);
};

UrlBar.prototype._showNoOp = function() {
	// DO NOTHING - We don't show anything in landscape.
};

UrlBar.prototype._hideNoOp = function() {
	// DO NOTHING - We should not be displayed in landscape.
};

UrlBar.prototype.isVisible = function() {
	return this.controller.getMenuVisible(Mojo.Menu.viewMenu);
};

UrlBar.prototype.focus = function() {

	switch (this.currentModel.mode) {

		case 'url':
			this.controller.get('urlbar-input').mojo.focus();
			break;

		case 'title':
			this.controller.get('urlbar-title').focus();
			break;
		default:
			Mojo.Log.error("Unknown model for FOCUS");
			break;
	}
};

UrlBar.prototype.blur = function() {

	switch (this.currentModel.mode) {

		case 'url':
			this.controller.get('urlbar-input').mojo.blur();
			break;

		case 'title':
			this.controller.get('urlbar-title').blur();
			break;
		default:
			Mojo.Log.error("Unknown model for BLUR");
			break;
	}
};

UrlBar.prototype.select = function() {

	var element;
	var input;

	if (this.currentModel.mode === 'url') {

		input = this.controller.get('urlbar-input');
		if (input) {
			element = input.querySelector('[name="urlbar-textfield-input"]');
			if (element) {
				element.select();
			}
		}
	}
};

UrlBar.prototype._onInputFocus = function(event) {

	this._urlBarFocused = true;
	this._activateGoButton(true);
};

UrlBar.prototype._onInputBlur = function(event) {

	this._urlBarFocused = false;

	// Switch the GO button view
	this._activateGoButton(false);

	// Notify the owner of a blur through the propertyChange
	// callback.
	this._onPropertyChange(event);
};

UrlBar.prototype.hasFocus = function() {

	return this._urlBarFocused;
};

UrlBar.prototype.getValue = function() {

	// We use the stored value rather that the element
	// because our models can change.
	return this.models.urlInput.model.url;
};

UrlBar.prototype.isInUrlMode = function() {
	var urlFlag = (this.currentModel.mode === 'url');
	return urlFlag;
};

UrlBar.prototype.getBarHeight = function() {

	return this.controller._menu.assistant.kMenuHeight;
};
