var HintedTextField = Class.create(
	{
		initialize: function(input)
		{
			this.input = $(input);

			if (typeof this.input === "undefined")
			{
				throw "Passed input is undefined";
			}

			if (typeof this.input.nodeName === "undefined")
			{
				throw "Passed input lacks a nodeName property";
			}

			var nodeName = this.input.nodeName.toLowerCase().strip();
			this.isInput = (nodeName === "input");
			this.isTextarea = (nodeName === "textarea");

			if (!this.isInput && !this.isTextarea)
			{
				throw "Passed input is not an <input /> or <textarea /> tag";
			}
			
			this.inputType = (this.isInput ? this.input.readAttribute("type").strip().toLowerCase() : null);
			this.isInputText = (this.isInput && this.inputType === "text");
			this.isInputPassword = (this.isInput && this.inputType === "password");

			if (this.isInput && !this.isInputText && !this.isInputPassword)
			{
				throw "Passed input is a <input type=\"" + input.readAttribute("text") + "\" />; must be type \"text\" or \"password\" instead";
			}

			var existing = this.input.retrieve("hintedTextFieldInstance");
			if (existing)
			{
				console.warn("There's already a HintedTextField bound to this input; returning it");
				return existing;
			}

			this.defaultValue = this.input.readAttribute("title");
			if (this.defaultValue === null)
			{
				throw "Passed input lacks a \"title\" attribute";
			}

			// rubbish IE8- requires that you clone the input for passwords; you can't change the type at runtime
			this.cloneInputInstead = false;
			if (Prototype.Browser.IE)
			{
				var match = /MSIE ([0-9]+)/.exec(navigator.userAgent);
				if (parseInt(match[1]) < 9)
				{
					this.cloneInputInstead = true;
				}
			}

			this.observeInput(this.input);
			this.input.up("form").observe("submit", this.onFormSubmit.bind(this));

			this.updateFieldStatus(false);

			this.input.store("hintedTextFieldInstance", this);
		},

		observeInput: function(input)
		{
			input.observe("focus", this.onFocus.bind(this));
			input.observe("blur", this.onBlur.bind(this));
		},

		onFocus: function(e)
		{
			this.updateFieldStatus(true);
		},

		onBlur: function(e)
		{
			this.updateFieldStatus(false);
		},

		cloneInput: function(newType)
		{
			var input = "<" + this.input.nodeName + " type=\"" + newType.escapeHTML() + "\"";
			for (var i = 0; i < this.input.attributes.length; i++)
			{
				var key = this.input.attributes[i].name;
				if (key !== "type")
				{
					var value = this.input.readAttribute(key);
					if (typeof value === "string" && value !== null)
					{
						input += " " + key + "=\"" + value.escapeHTML() + "\"";
					}
				}
			}

			input += " />";

			input = Element.extend(document.createElement(input));
			input.store("hintedTextFieldInstance", this);
					
			this.observeInput(input);

			return input;
		},

		setFieldType: function(newType)
		{
			var currentType = this.input.getAttribute("type");
			if (this.isInput && currentType != newType)
			{
				if (this.cloneInputInstead)
				{
					this.input = this.input.replace(this.cloneInput(newType));
					this.input = $(this.input.identify());
				}
				else
				{
					this.input.setAttribute("type", newType);
				}
			}
		},

		resetFieldType: function()
		{
			if (this.isInput)
			{
				var type = null;
				if (this.isInputText)
				{
					type = "text";
				}
				else if (this.isInputPassword)
				{
					type = "password";
				}
				else
				{
					throw "Can't determine original type of this input";
				}

				this.setFieldType(type);
			}
		},

		updateFieldStatus: function(focus)
		{
			if (focus && $F(this.input) == this.defaultValue)
			{
				this.input.removeClassName("hinted");
				this.input.setValue("");
				this.resetFieldType();
				var focus = function()
				{
					this.input.focus();
				}.bind(this);

				if (this.cloneInputInstead)
				{
					focus.defer();
				}
				else
				{
					focus();
				}
			}
			else if (!focus && $F(this.input) == "")
			{
				this.input.addClassName("hinted");
				this.input.setValue(this.defaultValue);
				this.setFieldType("text");
			}
		},

		onFormSubmit: function(e)
		{
			this.resetFieldType();

			if ($F(this.input) == this.defaultValue)
			{
				this.input.setValue("");
			}
		}
	}
);

HintedTextField.bindAll = function()
{
	var fields = $$("input.autohinted, textarea.autohinted");
	for (var i = 0; i < fields.length; i++)
	{
		new HintedTextField(fields[i]);
	}
};

