function createTestCreationWindow(objParams) {
	var container = $.tmpl("crudTestMain", {
		formAction: objParams.formAction,
		submitButtonTitle: objParams.submitButtonTitle,
		hideImplementation: objParams.bHideImplementation,
		allowCancel: objParams.allowCancel,
		callbackFunction: objParams.callbackFunction
	}).i18n().appendTo(document.body);

	container.find('div.controls input').button();
	container.submit(function(eventObject) {
		onFormSubmitHandler(eventObject);
	});

	initCrudTestButtons();

	$('#steps').sortable({
		axis: 'y',
		containment: $('#steps').parent(),
		cursor: 'move',
		distance: 5,
		placeholder: "ui-state-highlight",
		opacity: 0.65,
		revert: true
	});

	return container.dialog({
		title: objParams.windowTitle,
		height: 440,
		width: 740,
		modal: true,
		close: function(event, ui) {
			// TODO: cancel save - need to confirm.
			$(this).dialog('destroy').remove();
		}
	});
}

// save form data
function onFormSubmitHandler(ev) {
	ev.preventDefault();

	var form = $('#createTestForm');
	var json = {
		// test id
		testId: parseInt($('input[name="testId"][type="hidden"]').val()),
		// test summary
		summary: $('input[name="summary"]').val(),
		// test implementation
		implementation: $('textarea[name="implementation"]').val() || '',
		// test attachments
		attachments: [],
		// bugtracking
		bugRefs: [],
		// test steps
		steps: [],
		// test tags
		tags: []
	};

	// platform
	form.find('input[name="platform"]:checked').each(function(ii, el) {
		json.tags.push("platform_" + el.value);
	});

	// test type
	json.tags.push("testType_" + form.find('select[name="testType"]').val());

	// SDK
	var sdk = $('input[type="hidden"][name="sdkVersion"]');
	if (sdk.size() > 0 && sdk.val().length > 0) {
		json.tags.push("sdk_" + sdk.val());
	}

	// Platform
	var platform = $('input[type="hidden"][name="platformVersion"]');
	if (platform.size() > 0 && platform.val().length > 0) {
		json.tags.push("platform_v_" + platform.val());
	}

	// tags
	$('input[type="hidden"][name="tag"]').each(function(ii, el){json.tags.push(el.value);});

	// bugtracking
	$('input[type="hidden"][name="bugtrackingRef"]').each(function(ii, el) {
		json.bugRefs.push(el.value);
	});

	// already present attachments for test
	$('input[name="testAttachmentId"]').each(function(ii, el) {
		json.attachments.push({'attachmentId': el.value});
	});

	// newly added attachments for test
	$('input[name^="test_attachment_"]').each(function(ii, el) {
		json.attachments.push({'fieldName': el.name});
	});

	// steps: old and new one
	$("#steps li").each(function(ii, el) {
		var container = $(el);
		var objStep = {
			'instructions':
				container.find('textarea').val() ||
				container.find('input[name="stepInstructions"]').val(),
			'stepId': container.find('input[name="stepId"]').val(),
			attachments: []
		};

		container.find('input[type="file"][value!=""]').each(function (ii, el) {
			objStep.attachments.push({'fieldName': el.name});
		});

		container.find('input[name="attachmentId"]').each(function (ii, el) {
			objStep.attachments.push({'attachmentId': el.value});
		});

		if (!objStep.stepId) {
			delete objStep.stepId;
		}

		if (!objStep.attachments.length) {
			delete objStep.attachments;
		}

		if (objStep.instructions) {
			json.steps.push(objStep);
		}
	});

	// validation of summary
	if (json.summary == null || json.summary.length === 0) {
		alert(L("app.crudTest.error.noSummary"));
		return false;
	}

	// validation of steps&implementation
	if (json.implementation && json.steps.length === 0) {
		alert(L("app.crudTest.error.atLeast1Step"));
		return false;
	}

	// test id
	if (!isFinite(json.testId)) {
		delete json.testId;
	}

	// implementation
	if (!json.implementation) {
		delete json.implementation;
	}

	if (json.tags.length === 0) {
		delete json.tags;
	} else {
		json.tags = json.tags.join(" ");
	}

	if (json.attachments.length === 0) {
		delete json.attachments;
	}

	if (json.bugRefs.length === 0) {
		delete json.bugRefs;
	}

	if (json.steps.length === 0) {
		delete json.steps;
	}

	// disable controls
	form.find("input, textarea, select").each(function(ii, el) {
		if (
			!((el.type === "file" && el.value !== "") ||
			el.name === "callbackFunction")
		) {
			el.disabled = true;
		}
	});
	
	var implhash = $('FORM#createTestForm INPUT#implhash').val();
	if (implhash) {
		json.implhash = implhash;
	}
	
	$('<input type="hidden" name="data" />').val(JSON.stringify(json)).appendTo(form);
	form.unbind("submit").submit();
}

function processResponseOnTestSave(objResponse) {
	// enable controls
	$('#createTestForm').find('input, textarea, select').each(function(ii, el) {
		el.disabled = false;
	}).end().submit(function(eventObject) {
		onFormSubmitHandler(eventObject);
	});

	if (!parseResponse(objResponse)) {
		// hide & remove DOM of the dialog
		$('#createTestForm').dialog('destroy').remove();

		var gridEl = $('#testsListGridContainer');
		var testObject = $.extend({}, objResponse.tests[0]);
		var testId = testObject.testId;

		if ($.isEmptyObject(gridEl.jqGrid('getRowData', testId))) {
			Integrity.Tests.data.push(testObject);

			gridEl.jqGrid(
				'addRowData',
				1,
				Integrity.Tests.extendRow($.extend({}, testObject))
			);
			// lets show notification
			showInfo(L('app.crudTest.successfulCreateMessage'));
		} else {
			var objTestOrig = Integrity.Tests.getTestById(testId);
			var oldName = objTestOrig.summary;
			Integrity.Tests.updateTest(testObject);

			gridEl.jqGrid(
				'setRowData',
				testId,
				Integrity.Tests.extendRow($.extend({}, testObject))
			);
			showInfo(L('app.crudTest.successfulSaveMessage'));
		}

		if (oldName !== testObject.summary) {
			gridEl.trigger("reloadGrid");
		}
	}
}

function editTest(testId){
	var objTest = Integrity.Tests.getTestById(testId);
	return editTestObject(objTest);
}

function editTestObject(objTest, objParams) {
	if (typeof objTest !== 'object') {
		return;
	}

	var createTestWindowOptions = {
		windowTitle: L("app.crudTest.editTitle"),
		submitButtonTitle: L('app.crudTest.saveButton'),
		formAction: 'api.php?method=edit-test',
		callbackFunction: 'window.parent.processResponseOnTestSave'
	};

	var container = createTestCreationWindow(
		$.extend(createTestWindowOptions, objParams)
	);

	$('input[type="hidden"][name="testId"]').val(objTest.testId);
	$('input[name="summary"]').val(objTest.summary);

	var userTags = [];
	var sdk = null, platform_version = null;
	$.each(objTest.tags.split(/\s+/), function(ii, tag){
		var md;
		if(md = tag.match(/platform_v_(.*)/)){
			platform_version = md[1];
		} else if(md = tag.match(/platform_(.*)/)){
			container.find('input[name="platform"][value="' + md[1] + '"]').get(0).checked = true;
		} else if(md = tag.match(/sdk_(.*)/)){
			sdk = md[1];
		} else if(md = tag.match(/testType_(.*)/)){
			container.find('select[name="testType"] option[value="' + md[1] + '"]').get(0).selected = true;
		} else {
			userTags.push(tag);
		}
	});

	if(sdk){
		insertSDKResult(sdk);
		hideAddButton('#addSDK');
	}

	if(platform_version){
		insertPlatformResult(platform_version);
		hideAddButton('#addPlatform');
	}

	if(userTags.length > 0){
		insertTagsResult(userTags);
	}

	if(objTest.bugRefs != null){
		for(var ii = 0; ii < objTest.bugRefs.length; ii++){
			insertBugtrackingResult(objTest.bugRefs[ii], objTest.bugRefs[ii]);
		}
	}

	if(objTest.implementation){
		insertImplementation(objTest.implementation);
		hideAddButton('#addImplementation');
	}

	if (objTest.attachments != null) {
		for (var ii = 0; ii < objTest.attachments.length; ii++) {
			insertAttachmentResult(objTest.attachments[ii]);
		}
	}

	if(objTest.steps != null){
		for(var ii = 0; ii < objTest.steps.length; ii++){
			insertStepResult(objTest.steps[ii], ii + 1);
		}
	}

	return container;
	
};

function initCrudTestButtons(){
	$("#cancelButton").click(function(){
		$('#createTestForm').dialog('close');
	});

	function updatePlatformVersions(){
		// update SELECT box with SDK versions to show only SDK for selected platforms
	}

	$("#platforms input").each(function(ii, input){
		$(input).blur(function(){
			updatePlatformVersions();
		})
	});

	$("#addBugtracking").click(function(){
		hideAddButton(this);
		insertBugtracking();
	});

	$("#addSDK").click(function(){
		hideAddButton(this);
		insertSDK();
	});

	$("#addPlatform").click(function(){
		hideAddButton(this);
		insertPlatform();
	});

	$("#addImplementation").click(function(){
		hideAddButton(this);
		insertImplementation();
	});

	$("#addTags").click(function(){
		hideAddButton(this);
		insertTags();
	});

	$("#addAttachment").click(function(){
		insertAttachment();
	});

	$("#addStep").click(function(){
		insertStep();
	});
}

function hideAddButton(buttonName){
	$(buttonName).removeClass("visible");
}

function showAddButton(buttonName){
	$(buttonName).addClass("visible");
}

function insertBugtracking(ref, refHRF){
	var container = $.tmpl("crudTestBugtracking", {
		ref: ref,
		refHRF: refHRF
	}).i18n().appendTo($("#paneContainer"));

	container.find('input[name="bugtrackingRef"]').focus();

	container.find("input.add").click(function() {
		showAddButton("#addBugtracking");
		var ref = container.find('input[name="bugtrackingRef"]').val();
		if (ref.length > 0) {
			// TODO fetch description from remote server
			insertBugtrackingResult(ref, ref, container);
			container.remove();
		}
	});

	container.find("input.cancel").click(function() {
		container.remove();
		showAddButton("#addBugtracking");
	});

	return container;
}

function insertBugtrackingResult(ref, refHRF, insertAfter){
	var el = $.tmpl("crudTestBugtrackingResult", {
		ref: ref,
		refHRF: refHRF
	}).i18n()
	.find("input.remove").click(function(){
		$(this).closest(".bugtrackResultContainer").remove();
	}).end();

	if(insertAfter){
		el.insertAfter(insertAfter);
	} else {
		el.appendTo($("#paneContainer"));
	}

	return el;
}

function insertSDK(sdk){
	var container = $.tmpl("crudTestSDK", {sdk: sdk}).i18n().appendTo($("#paneContainer"));
	return container.find('input[name="sdkVersion"]').focus().end()
	.find("input.add").click(function(){
		var sdk = container.find('select[name="sdkVersion"]').val();
		if(sdk.length === 0){
			// ignore add if nothing entered
			return;
		}
		insertSDKResult(sdk, container);
		container.remove();
	}).end()
	.find("input.cancel").click(function(){
		container.remove();
		showAddButton("#addSDK");
	}).end();
}

function insertSDKResult(sdk, insertAfter){
	var el = $.tmpl("crudTestSDKResult", {sdk: sdk}).i18n()
	.find("input.remove").click(function(){
		$(this).closest(".sdkResultContainer").remove();
		showAddButton('#addSDK');
	}).end();

	if(insertAfter){
		el.insertAfter(insertAfter);
	} else {
		el.appendTo($("#paneContainer"));
	}

	return el;
}

function insertPlatform(platform) {
	var container = $.tmpl("crudTestPlatform", {
		platform: platform
	}).i18n().appendTo($("#paneContainer"));

	return container.find('select[name="platformVersion"]').focus().end()
	.find("input.add").click(function() {
		var platform = container.find('select[name="platformVersion"]').val();

		if (platform.length > 0) {
			insertPlatformResult(platform, container);
			container.remove();
		}
	}).end()
	.find("input.cancel").click(function(){
		container.remove();
		showAddButton("#addPlatform");
	}).end();
}

function insertPlatformResult(platform, insertAfter){
	var el = $.tmpl("crudTestPlatformResult", {platform: platform}).i18n()
	.find("input.remove").click(function(){
		$(this).closest(".platformResultContainer").remove();
		showAddButton('#addPlatform');
	}).end();

	if(insertAfter){
		el.insertAfter(insertAfter);
	} else {
		el.appendTo($("#paneContainer"));
	}

	return el;
}

function insertImplementation(implementation) {
	var container = $('#implementationContainer');
	
	if (container.size() != 0) {
		container.remove();
	}

	container = $.tmpl("crudTestImplementation", {
		implementation: implementation
	}).i18n().appendTo($("#paneContainer"));
	
	container.find('textarea').autoGrow().focus();
	container.find("input.validate").click(function(){
		// TODO validation
	});

	container.find("input.remove").click(function(){
		container.remove();
		showAddButton("#addImplementation");
	});

	return container;
}

function insertTags(tagsArr){
	var container = $.tmpl("crudTestTags", {tags: tagsArr}).i18n().appendTo($("#paneContainer"));
	return container.find('input[name="tags"]').focus().end()
	.find("input.add").click(function(){
		var sTags = container.find('input[name="tags"]').val() || '';
		var aSplitTags = null;

		// process if tags are not empty
		if (sTags) {
			aSplitTags = sTags.split(/\s+/);
			for (var ii = aSplitTags.length - 1; ii >= 0; ii--) {
				if (_.include(Integrity.Tests.forbiddenTags, aSplitTags[ii])) {
					showError(L('app.crudTest.tags.forbiddenWord'));
					return;
				}
			}

			insertTagsResult(aSplitTags, container);
			container.remove();
			showAddButton("#addTags");
		}
	}).end()
	.find("input.cancel").click(function(){
		container.remove();
		showAddButton("#addTags");
	}).end();
}

function insertTagsResult(tagsArr, insertAfter){
	var el = $.tmpl("crudTestTagsResult", {tags: tagsArr}).i18n()
	.find(".removeTag").click(function(){
		$(this).closest(".tag").remove();
	}).end()
	.find("input.remove").click(function(){
		$(this).closest(".tagsResultContainer").remove();
	}).end();

	if(insertAfter){
		el.insertAfter(insertAfter);
	} else {
		el.appendTo($("#paneContainer"));
	}

	return el;
}

function insertAttachment() {
	var container = $.tmpl(
		"crudTestAttachment",
		{ 'attachmentUid': new Date().getTime() }
	);

	container.i18n();
	container.appendTo($("#paneContainer"));
	container.find("input.cancel").click(function() {
		container.remove();
	});

	return container;
}

function insertAttachmentResult(oAttachment) {
	var nAttachment = $.tmpl('crudTestAttachmentResult', {
		attachmentId: oAttachment.attachmentId,
		attachmentHRF: oAttachment.filename
	});
	nAttachment.i18n();
	nAttachment.appendTo($('#paneContainer'));

	nAttachment.find("input.remove").click(function() {
		nAttachment.remove();
	});

	return nAttachment;
}

function insertStep(objStep, stepIndex) {
	if (typeof objStep !== 'object') {
		objStep = {};
	}

	var container = $.tmpl("crudTestStep", {stepObject: objStep}).i18n();

	if (typeof stepIndex !== 'undefined') {
		container.insertAfter($('#steps > li:nth-child(' + stepIndex + ')'));
	} else {
		$("#steps").append(container);
	}

	// remove of already added attachment
	container.find('.addedBlock .ui-icon-closethick').click(function() {
		$(this).closest('li').remove();
	});

	// focus textarea with instructions
	container.find('textarea').autoGrow().focus();

	// add new attachment
	container.find('.ui-icon-plusthick').parent().click(function() {
		// adding input for new attachment
		$.tmpl("crudTestStepAttachment", {
			'attachmentUid': generateAttachmentUid($(this))
		}).i18n().appendTo($(this).closest('td').find(".addBlock"))
		// remove of new attachment
		.find('.ui-icon-closethick').click(function() {
			$(this).closest('.stepAttachment').remove();
		});
	});

	// remove of this step
	container.find("input.remove").click(function(){
		container.remove();
	});

	// for webkit-based browsers and msie we need to add this hack
	// since they render table inside li with a little bug
	if ($.browser.webkit || $.browser.msie) {
		container.closest('ol').find('li > table').css('margin-top', '-1.3em');
	}

	return container;
}

function insertStepResult(objStep) {
	if (typeof objStep !== 'object') {
		return;
	}

	// create html for step, localize it, append to parent container
	var stepResultContainer = $.tmpl("crudTestStepResult", {
		stepObject: objStep
	}).i18n().appendTo($("#steps"));

	stepResultContainer.find("input.remove").click(function(){
		// TODO: hide container if none left
		$(this).closest("li").remove();
	});

	stepResultContainer.find('[name="edit"]').click(function() {
		var testId = $('#createTestForm input[name="testId"]').val();
		var stepId = $(this).closest('li').find('input[name="stepId"]').val();
		var stepObject = Integrity.Tests.getStepFromTest(testId, stepId);

		insertStep(stepObject, $(this).closest('li').index() + 1);
		stepResultContainer.find("input.remove").click();
	});
}

function insertImplementationHash(hash) {
	if (!hash) {
		return;
	}
	$('FORM#createTestForm INPUT#implhash').val(hash);
};

