var LoginController = function(loginUrl, keepAliveUrl, keepAliveInterval, requestTimeout) {

	var E_FORM = "login_form";
	var E_LOGOOUT = "login_logout";
	var E_LOGOOUT_VALUE = "login_logout_value";
	var E_LOADING = "login_loading";
	var E_TIMEOUT = "login_timeout";
	var E_EWRONGREQUEST = "login_e_wrongrequest";
	var E_EEMPTY = "login_e_empty";
	var E_ESTATUS = "login_e_status";
	var E_ESTATUS_VALUE = "login_e_status_value";
	var E_EERROR = "login_e_error";
	var E_LOGIN = "login_login";
	var E_PASSWORD = "login_password";
	var E_EXPIRED = "login_expired";
	var C_VALID = "";
	var C_INVALID = "error";

	this.listeners = [];
	this.keepAliveTimer = null;

	this.validateUsername = function(ignoreLength) {
		var element = getElement(E_LOGIN);
		var value = element.value;
		var pattern = (ignoreLength) ? (/^[a-zA-Z0-9_.]+$/) : (/^[a-zA-Z0-9_.]{4,}$/)
		if (value.match(pattern)) {
			setElementClassName(E_LOGIN, C_VALID);
			return true;
		} else {
			setElementClassName(E_LOGIN, C_INVALID);
			return false;
		}
	}

	this.validatePassword = function() {
		var element = getElement(E_PASSWORD);
		var value = element.value;
		if (value != "") {
			setElementClassName(E_PASSWORD, C_VALID);
			return true;
		} else {
			setElementClassName(E_PASSWORD, C_INVALID);
			return false;
		}
	}

	this.onEnterPressed = function(event) {
		if (event.keyCode == 13)
			this.login();
	}

	this.login = function() {
		if (!this.validateUsername(false) | !this.validatePassword())
			return;
		hideElement(E_FORM);
		showElement(E_LOADING);
		this.loginRequest(getElementValue(E_LOGIN), getElementValue(E_PASSWORD));
	}

	this.hideMessage = function() {
		hideElement(E_TIMEOUT);
		hideElement(E_EWRONGREQUEST);
		hideElement(E_EEMPTY);
		hideElement(E_ESTATUS);
		hideElement(E_EERROR);
		hideElement(E_EXPIRED);
		showElement(E_FORM);
	}

	this.loginRequest = function(login, password) {
		var request = ((typeof XMLHttpRequest != 'undefined') ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
		var url = loginUrl + '?requestId=' + (new Date().getTime());
		request.open("POST", url, true);
		request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		var thisClosure = this;
		request.onreadystatechange = function() {
			if (request.readyState == 4) {
				if (request.status == 200) {
					thisClosure.processResponse(login, request.responseText);
				}
			}
		}
		request.send('login=' + encodeURIComponent(login) + '&password=' + encodeURIComponent(password));
		setTimeout((function() {thisClosure.processTimeout(request)}), requestTimeout);
	}

	this.processResponse = function(login, responseText) {
		hideElement(E_LOADING);
		try {
			var responseHash = eval("[" + responseText + "]")[0];
			var response = new LoginResponse(responseHash);
			if (!response.isResultOk()) {
				if (response.isStatusError()) {
					showElement(E_EERROR);
				} else if (response.isStatusWrongrequest()) {
					showElement(E_EWRONGREQUEST);
				} else if (response.isStatusEmpty()) {
					showElement(E_EEMPTY);
				} else {
					setElementContent(E_ESTATUS_VALUE, response.getStatus());
					showElement(E_ESTATUS);
				}
			} else {
				setElementContent(E_LOGOOUT_VALUE, login);
				showElement(E_LOGOOUT);
				this.notifyListeners(true, login);
				this.initKeepAlive();
			}
		} catch (e) {
			showElement(E_EERROR);
		}
	}

	this.processTimeout = function(request) {
		if (request.readyState == 4 && request.status == 200)
			return;
		request.abort();
		hideElement(E_LOADING);
		showElement(E_TIMEOUT);
	}

	this.initKeepAlive = function() {
		var thisClosure = this;
		this.keepAliveTimer = setTimeout((function() {thisClosure.requestKeepAlive()}), keepAliveInterval);
	}

	this.requestKeepAlive = function() {
		var request = ((typeof XMLHttpRequest != 'undefined') ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
		var url = keepAliveUrl + "?requestId=" + (new Date().getTime());
		request.open("GET", url, true);
		var thisClosure = this;
		request.onreadystatechange = function() {
			if (request.readyState == 4) {
				if (request.status == 200) {
					thisClosure.processKeepAliveResponse(request.responseText);
				}
			}
		}
		request.send(null);
		setTimeout((function() {thisClosure.processKeepAliveTimeout(request)}), requestTimeout);
	}

	this.processKeepAliveResponse = function(responseText) {
		try {
			var response = eval("[" + responseText + "]")[0];
			if (!response["isAuthorized"]) {
				hideElement(E_LOGOOUT);
				setElementContent(E_LOGOOUT_VALUE, "");
				showElement(E_EXPIRED);
				this.notifyListeners(false, null);
				return;
			}
		} catch (e) {}
		this.initKeepAlive();
	}

	this.processKeepAliveTimeout = function(request) {
		if (request.readyState == 4 && request.status == 200)
			return;
		request.abort();
		this.initKeepAlive();
	}

	this.registerListener = function(listener) {
		this.listeners.push(listener);
	}

	this.notifyListeners = function(loggedIn, login) {
		for (var i in this.listeners)
			this.listeners[i].loginNotify(loggedIn, login);
	}
}

var LoginResponse = function(hash) {

	var R_OK = "ok";
	var S_ERROR = "error";
	var S_WRONGREQUEST = "wrongrequest";
	var S_EMPTY = "empty";

	this.getResult = function() {
		return hash["result"];
	}

	this.getStatus = function() {
		return hash["status"];
	}


	this.isResultOk = function() {
		return (this.getResult() == R_OK);
	}

	this.isStatusError = function() {
		return (this.getStatus() == S_ERROR);
	}

	this.isStatusWrongrequest = function() {
		return (this.getStatus() == S_WRONGREQUEST);
	}

	this.isStatusEmpty = function() {
		return (this.getStatus() == S_EMPTY);
	}
}

var LoginControllerListener = function() {
	this.loginNotify = function(loggedIn, login) {}
}