var TABTJS_SERVER_LOCATION = 'http://tabt.mentalis.org/0.4/';
var TABTJS_SCRIPT_LOCATION = 'http://tabt.mentalis.org/0.4/';

var NO_VIEW = '-=-=-=-=-=-=-=-=-=- NO VIEW -=-=-=-=-=-=-=-=-=-';

AddScript(TABTJS_SCRIPT_LOCATION + 'tabtjs-widgets.js');
AddCss('div.tabtjs { visibility: hidden }');

var originalOnLoad = window.onload;
window.onload = flagDocumentLoaded;

var documentLoaded = false;
var widgetsLoaded = false;

function flagDocumentLoaded() {
	if (originalOnLoad) {
		originalOnLoad();
	}

	documentLoaded = true;
	if (documentLoaded && widgetsLoaded) {
		processWidgets();
	}
}

function flagWidgetsLoaded() {
	widgetsLoaded = true;
	if (documentLoaded && widgetsLoaded) {
		processWidgets();
	}
}

function processWidgets() {
	var widgets = GetElementsByClass('tabtjs', 'div');
	
	for (var i=0; i<widgets.length; i++) {
		var widget = widgets[i];
		
		var classes = GetElementClasses(widget);
		
		var widgetType = false;
		for (var j=0; j<classes.length; j++) {
			if (classes[j] != 'tabtjs' && classes[j] != 'lazy') {
				widgetType = classes[j];
				break;
			}
		}		

		var lazy = false;
		for (var j=0; j<classes.length; j++) {
			if (classes[j] == 'lazy') {
				lazy = true;
				break;
			}
		}
		
		if (!widget.id) {
			errorLog('widget must have an ID');
		} if (widgetType) {
			processWidget(widget, widgetType, lazy);
		} else {
			errorLog('widget with id \'' + widget.id + '\' has no type');
		}
	}
}

function processWidget(widget, widgetType, lazy) {
	var parameterText = widget.innerHTML;
	var parameters = ParseParameters(parameterText);

	var initializeMethodName = widgetType + 'Initialize';
	var requestMethodName = widgetType + 'Request';
	var responseMethodName = widgetType + 'Response';

	parameters['Request'] = requestMethodName;
	parameters['Callback'] = responseMethodName;
	parameters['ObjectId'] = widget.id;

	widget.parameters = parameters;

	widget.innerHTML = '';
	widget.style.visibility = 'visible';
	
	var initializeHtml = eval(initializeMethodName)(parameters);
	if (isDefined(initializeHtml) && initializeHtml != NO_VIEW) {
		widget.innerHTML = initializeHtml;
	}
		
	if (!lazy) {
		var requestHtml = eval(requestMethodName)(parameters);
		if (isDefined(requestHtml) && requestHtml != NO_VIEW) {
			widget.innerHTML = requestHtml;
		}
	}
}

function reloadWidget(widget, overrideParameters) {
	var params = new Object();
	
	for (p in widget.parameters) {
		params[p] = widget.parameters[p];
	}

	if (isDefined(overrideParameters)) {
		for (p in overrideParameters) {
			params[p] = overrideParameters[p];
		}
	}

	eval(params['Request'])(params);
}

function AddScript(scriptUrl) {
	var headID = document.getElementsByTagName('head')[0];         
	var newScript = document.createElement('script');
	newScript.type = 'text/javascript';
	newScript.src = scriptUrl;
	headID.appendChild(newScript);
}

function AddCss(cssCode) {
	var styleElement = document.createElement("style");
	styleElement.type = "text/css";
	if (styleElement.styleSheet) {
		styleElement.styleSheet.cssText = cssCode;
	} else {
		styleElement.appendChild(document.createTextNode(cssCode));
	}
	document.getElementsByTagName("head")[0].appendChild(styleElement);
}


function ExecuteRequest(parameters) {
	var url = TABTJS_SERVER_LOCATION + 'tabtjs.php?';

	for (p in parameters) {
		url = url + p + '=' + escape(parameters[p]) + '&';
	}
	
	//alert(url);
	
	AddScript(url);
}

function GetElementsByClass(searchClass, tagName) {
	var elements = document.getElementsByTagName(tagName);
	
	var needle = ' ' + searchClass + ' ';
	var matches = new Array();
	for (var i=0; i<elements.length; i++) {
		var haystack = ' ' + elements[i].className + ' ';
		if (haystack.indexOf(needle) != -1) {
			matches.push(elements[i]);
		}
	}
	
	return matches;
}

function GetElementClasses(domNode) {
	return domNode.className.split(' ');
}

function ParseParameters(parameterText) {
	var PADDING_BEFORE_NAME = 1;
	var PARAMETER_NAME = 2;
	var PADDING_AFTER_NAME = 3;
	var EQUALS = 4;
	var PADDING_BEFORE_VALUE = 5;
	var OPEN_TEXT_QUALIFIER = 6;
	var PARAMETER_VALUE = 7;
	var CLOSE_TEXT_QUALIFIER = 8;
	var PADDING_AFTER_VALUE = 9;
	var SEPARATOR = 10;
	
	var state = PADDING_BEFORE_NAME;
	var pos = 0;
	if (parameterText.charCodeAt(0) == 10 || parameterText.charCodeAt(0) == 13) {
		pos = 1;
	}
	
	
	var line = 1;
	var column = 1;
	
	var currentParameterName = '';
	var currentParameterValue = '';
	var textQualifier = false;
	
	var error = false;
	
	var parameters = new Array();
	do {
		var code = parameterText.charCodeAt(pos);
		if (IsEndlineCharacter(code)) {  // TODO: fix in case of CR/LF
			line++;
			column = 1;
		} else {
			column++;
		}
			
		if (state == PADDING_BEFORE_NAME) {
			if (IsValidParameterNameCharacter(code)) {
				currentParameterName = parameterText.charAt(pos);
				state = PARAMETER_NAME;
			} else if (code > 32) {
				error = 'Character not allowed in parameter name at line ' + line + ', column ' + column;
				break;
			}
		} else if (state == PARAMETER_NAME) {
			if (code == 35) {
				state = PADDING_BEFORE_VALUE;
			} else if (code <= 32) {
				state = PADDING_AFTER_NAME;
			} else if (code == 61) {
				state = PADDING_BEFORE_VALUE;
			} else if (IsValidParameterNameCharacter(code)) {
				currentParameterName += parameterText.charAt(pos);
			} else {
				error = 'Character not allowed in parameter name at line ' + line + ', column ' + column;				
			}
		} else if (state == PADDING_AFTER_NAME) {
			if (code == 61) {
				state = PADDING_BEFORE_VALUE;
			} else if (code > 32) {
				error = 'Expected \'=\', but got \'' + parameterText.charAt(pos) + '\' at line ' + line + ', column ' + column;
				break;
			}
		} else if (state == PADDING_BEFORE_VALUE) {
			if (IsValidTextQualifierCharacter(code)) {
				textQualifier = code;
				currentParameterValue = '';
				state = PARAMETER_VALUE;
			} else if (code > 32 && IsValidParameterValueCharacter(code)) {
				textQualifier = false;
				currentParameterValue = parameterText.charAt(pos);
				state = PARAMETER_VALUE;
			} else if (code > 32) {
				error = 'Character not allowed in parameter value at line ' + line + ', column ' + column;				
				break;
			}			
		} else if (state == PARAMETER_VALUE) {
			if (textQualifier && code == textQualifier) {
				state = PADDING_AFTER_VALUE;
			} else if (textQualifier && IsEndlineCharacter(code)) {
				error = 'Expected ' + String.fromCharCode(textQualifier) + ' before the end of line ' + line;
				break;
			} else if (!textQualifier && (code == 44 || IsEndlineCharacter(code) || code == 32)) {
				if (currentParameterName.length == 0) {
					error = 'Empty parameter name at line ' + line;
					break;
				}
				parameters[currentParameterName] = currentParameterValue;
				
				currentParameterName = '';
				currentParameterValue = '';
				
				state = PADDING_BEFORE_NAME;
			} else if (!IsValidParameterValueCharacter(code)) {
				error = 'Character not allowed in parameter value at line ' + line + ', column ' + column;				
				break;
			} else {
				currentParameterValue += parameterText.charAt(pos);
			}
		} else if (state == PADDING_AFTER_VALUE) {
			if (code == 44 || IsEndlineCharacter(code)) {
				if (currentParameterName.length == 0) {
					error = 'Empty parameter name at line ' + line;
					break;
				}
				parameters[currentParameterName] = currentParameterValue;
				
				currentParameterName = '';
				currentParameterValue = '';

				state = PADDING_BEFORE_NAME;
			} else if (code > 32) {
				error = 'Unexpected character at line ' + line + ', column ' + column;
				break;
			}
		}
		pos++;
	} while(pos < parameterText.length);

	if (currentParameterValue.length != 0 && currentParameterName.length == 0) {
		error = 'Empty parameter name at line ' + line;
	} else if (currentParameterName.length != 0) {
		parameters[currentParameterName] = currentParameterValue;
	}

	if (error) {
		alert(error + '\n- last code: ' + code + '\n-last state: ' + state + '\n-currentParameterName: ' + currentParameterName + '\n-currentParameterValue: ' + currentParameterValue);
	}
	
	return parameters;	
}

function IsValidParameterNameCharacter(code) {
	var result =  
		(code >= 16 && code <= 25) ||  // numbers
		(code >= 65 && code <= 90) ||  // capital letters
		(code >= 97 && code <= 122) || // small letters
		code == 95;	                   // Underscore

	return result;
}

function IsValidParameterValueCharacter(code) {
	return code >= 32;
}

function IsValidTextQualifierCharacter(code) {
	return code == 34 || code == 39;
}

function IsEndlineCharacter(code) {
    return code == 13 || code == 10;   
}

function errorLog(message) {
	alert('tabtjs: ' + message);
}

// ============
// SOAP Wrapper
// ============

function GetSeasons(request) {
    request.Method = 'GetSeasons';
    ExecuteRequest(request);
}

function GetClubTeams(request) {
    request.Method = 'GetClubTeams';
    ExecuteRequest(request);
}

function GetDivisionRanking(request) {
    request.Method = 'GetDivisionRanking';
    ExecuteRequest(request);
}

function GetMatches(request) {
    request.Method = 'GetMatches';
    ExecuteRequest(request);
}

function GetMembers(request) {
    request.Method = 'GetMembers';
    ExecuteRequest(request);
}

function GetClubs(request) {
    request.Method = 'GetClubs';
    ExecuteRequest(request);
}




