/**
 * File:        manage_views.js
 * Abstract:    contains all JS for the Views and Edit View pages.
 * Assumptions: g.root_url is defined
 */

var view_ns = {};
view_ns.num_standard_filter_rows = 0; // the number of standard filters currently displayed (overwritten by calling page)
view_ns.num_client_map_filter_rows = 0; // the number of client map filters currently displayed (overwritten by calling page)
view_ns.field_ids = []; // stores the fields IDs currently in the view
view_ns.all_form_fields = []; // all form fields
view_ns.view_tabs = []; // the view tabs. This is change dynamically in the page
view_ns.tabindex_increment = 1000;
view_ns.delete_view_dialog = $("<div id=\"delete_view_dialog\"></div>");


// used internally to create a new group ID for dynamically inserted groups. This is used temporarily
// in the page. When submitted, the server code does the job of assigned appropriate group IDs from the DB
view_ns.curr_new_group_id = 1;

// initialized on page load
view_ns.num_new_submission_default_values = 0;
view_ns.num_view_columns = 0;


$(function () {
	$(".add_field_link").live("click", function () {
		var group_id = $(this).closest(".sortable_group").find(".group_order").val();
		ft.create_dialog({
			dialog: $("#new_view_dialog"),
			title: g.messages["phrase_create_new_view"],
			buttons: [{
				text: g.messages["phrase_create_new_view"],
				click: function () {
					ft.dialog_activity_icon($("#new_view_dialog"), "show");
					var form_id = $("#form_id").val();
					var data_type = (g.js_debug) ? "html" : "json";

					var source_view_id = "";
					if ($("#create_view_from_view_id").length > 0) {
						source_view_id = $("#create_view_from_view_id").val();
					}

					$.ajax({
						url: g.root_url + "/global/code/actions.php",
						type: "POST",
						dataType: data_type,
						data: {
							form_id: form_id,
							group_id: group_id,
							action: "create_new_view",
							view_name: $("#new_view_name").val(),
							create_view_from_view_id: source_view_id
						},
						success: function (data) {
							// check the user wasn't logged out / denied permissions
							if (!ft.check_ajax_response_permissions(data)) {
								return;
							}

							if (g.js_debug) {
								console.log(data);
								return;
							}
							window.location = "?page=edit_view&edit_view_tab=1&form_id=" + form_id + "&view_id=" + data.view_id;
						},
						error: function (jqXHR, textStatus, errorThrown) {
							$("#new_view_dialog").dialog("close");
							ft.error_handler(jqXHR, textStatus, errorThrown);
						}
					});
				}
			},
				{
					text: g.messages["word_cancel"],
					click: function () {
						$(this).dialog("close");
					}
				}]
		});
	});
});


/**
 * Creates a new View group.
 */
view_ns.create_new_group = function () {
	ft.dialog_activity_icon($("#add_group_popup"), "show");
	$.ajax({
		url: g.root_url + "/global/code/actions.php",
		type: "POST",
		dataType: "json",
		data: { group_name: $("#add_group_popup").find(".new_group_name").val(), action: "create_new_view_group" },
		success: view_ns.create_new_group_response,
		error: function (xhr, text_status, error_thrown) {
			ft.dialog_activity_icon($("#add_group_popup"), "hide");
			$("#add_group_popup").dialog("close");
			ft.error_handler(xhr, text_status, error_thrown);
		}
	});
	return false;
}


/**
 * Creates a new View group (on the main Views page).
 */
view_ns.create_new_group_response = function (data) {
	// check the user wasn't logged out / denied permissions
	if (!ft.check_ajax_response_permissions(data)) {
		return;
	}

	ft.dialog_activity_icon($("#add_group_popup"), "hide");
	$("#add_group_popup").dialog("close");
	sortable_ns.insert_new_group({
		group_id: data.group_id,
		group_name: data.group_name,
		is_groupable: true
	});
}


view_ns.delete_view = function (el) {
	var view_id = $(el).closest(".row_group").find(".sr_order").val();

	ft.create_dialog({
		dialog: view_ns.delete_view_dialog,
		title: g.messages["phrase_delete_view"],
		content: g.messages["confirm_delete_view"],
		popup_type: "warning",
		buttons: [{
			text: g.messages["word_yes"],
			click: function () {
				ft.dialog_activity_icon($("#delete_view_dialog"), "show");
				$.ajax({
					url: g.root_url + "/global/code/actions.php",
					type: "POST",
					dataType: "json",
					data: { view_id: view_id, action: "delete_view" },
					success: view_ns.delete_view_response,
					error: function (xhr, text_status, error_thrown) {
						ft.dialog_activity_icon($("#add_group_popup"), "hide");
						$("#delete_view_dialog").dialog("close");
						ft.error_handler(xhr, text_status, error_thrown);
					}
				});
			}
		},
			{
				text: g.messages["word_no"],
				click: function () {
					$(this).dialog("close");
				}
			}]
	});
}


view_ns.delete_view_response = function (data) {
	// check the user wasn't logged out / denied permissions
	if (!ft.check_ajax_response_permissions(data)) {
		return;
	}

	ft.dialog_activity_icon($("#delete_view_dialog"), "hide");
	$("#delete_view_dialog").dialog("close");
	sortable_ns.delete_row("view_list", $(".sr_order[value=" + data.view_id + "]"));
	ft.display_message("ft_message", 1, g.messages["notify_view_deleted"]);

	// one final thing: delete the now-orphaned reference to this deleted View in the Add View dialog source
	$("#create_view_from_view_id option[value=" + data.view_id + "]").remove();
}


/**
 * Hides/shows the custom client list.
 */
view_ns.toggle_custom_client_list = function (val) {
	if (val == "yes") {
		$("#custom_clients").hide();
	} else {
		$("#custom_clients").show();
	}
}


/**
 * Enables / disables all fields in the View.
 */
view_ns.toggle_editable_fields = function (may_edit) {
	if (may_edit) {
		$(".editable_fields").attr({ disabled: "" });
	} else {
		$(".editable_fields").attr({ disabled: "disabled" });
	}
}


/**
 * Called after the user changes the tab content.
 */
view_ns.update_tab_dropdowns = function () {
	var tabs = view_ns.get_tab_dropdown_contents();
	$(".tabs_dropdown").each(function () {
		var curr_dropdown_selection = this.value;
		if (tabs.length == 0) {
			$(this).html("<option value=\"\">" + g.messages["validation_no_tabs_defined"] + "</option>");
		} else {
			var options = [];
			for (var i = 0; i < tabs.length; i++) {
				var is_selected = (tabs[i].tab == curr_dropdown_selection) ? " selected" : "";
				options.push($("<option value=\"" + tabs[i].tab + "\"" + is_selected + ">" + tabs[i].label + "</option>"));
			}
			var optgroup = $("<optgroup label=\"" + g.messages["phrase_available_tabs"] + "\"></optgroup>").append(ft.group_nodes(options));
			$(this).html(optgroup);
		}
	});
}


/**
 * Looks at the contents of the tabs and constructs and returns
 */
view_ns.get_tab_dropdown_contents = function () {
	var tabs = [];
	$(".tab_label").each(function (i) {
		var curr_tab_label = $.trim($(this).val());
		if (curr_tab_label == "") {
			return;
		}
		var tab_num = i + 1;
		tabs.push({ tab: tab_num, label: curr_tab_label });
	});

	return tabs;
}


/**
 * Hides / shows the sortable checkbox for a particular field. Called whenever a user clicks a
 * "column" checkbox.
 *
 * @param integer field_id
 * @param bool show hide/show the field
 */
view_ns.toggle_sortable_field = function (field_id, show) {
	$("#sortable_" + field_id).css("display", ((show) ? "block" : "none"));
}


/**
 * Helper function to get the field name out of the view_ns.all_form_fields array.
 *
 * @param integer field_id
 */
view_ns.get_field_name = function (field_id) {
	var field_name = null;
	for (var i = 0; i < view_ns.all_form_fields.length; i++) {
		if (view_ns.all_form_fields[i].field_id == field_id) {
			field_name = view_ns.all_form_fields[i].display_name;
			break;
		}
	}
	return field_name;
}


/**
 * Removes the view field from the view field table, on the Edit View page and decrements the order
 * values for all fields found after this item.
 *
 * @param integer field_id the unique field ID
 */
view_ns.remove_view_field = function (field_id) {
	var tbody = $("#view_fields_table").getElementsByTagName("tbody")[0];

	for (var i = tbody.childNodes.length - 1; i > 0; i--) {
		// ignore any whitespace "nodes"
		if (tbody.childNodes[i].nodeName == '#text') {
			continue;
		}

		if (tbody.childNodes[i].id == "field_row_" + field_id) {
			tbody.removeChild(tbody.childNodes[i]);
			break;
		}

		var curr_field_id = tbody.childNodes[i].id.replace(/field_row_/, "");
		var curr_order = parseFloat($("field_" + curr_field_id + "_order").value);
		$("field_" + curr_field_id + "_order").value = curr_order - 1;
	}

	// remove it from view_ns.field_ids
	view_ns.field_ids = $(view_ns.field_ids).without(field_id);

	// update the available field dropdown
	view_ns.update_available_view_fields();

	return false;
}


/**
 * Used to add rows to the standard filters table on the Edit View page (the first table). This is separated from the
 * client map filter table because the content is sufficiently different.
 *
 * @param integer num_rows the number of rows to add
 */
view_ns.add_standard_filters = function (num_rows) {
	var num_rows = num_rows.toString();
	if (num_rows.match(/\D/) || num_rows == 0 || num_rows == "") {
		ft.display_message("ft_message", false, g.messages["validation_num_rows_to_add"]);
		$("#num_standard_filter_rows").focus();
		return;
	}

	for (var i = 1; i <= num_rows; i++) {
		var curr_row = ++view_ns.num_standard_filter_rows;

		var row = document.createElement("tr");
		row.setAttribute("id", "standard_row_" + curr_row);

		// [1] first <td> cell: form field dropdown (defaulted to "please select")
		var td2 = document.createElement("td");
		var dd2 = document.createElement("select");
		dd2.setAttribute("name", "standard_filter_" + curr_row + "_field_id");
		dd2.setAttribute("id", "standard_filter_" + curr_row + "_field_id");
		$(dd2).bind("change", { curr_row: curr_row }, function (e) {
			view_ns.change_standard_filter_field(e.data.curr_row);
		});

		var default_option = document.createElement("option");
		default_option.setAttribute("value", "");
		default_option.appendChild(document.createTextNode(g.messages["phrase_please_select"]));
		dd2.appendChild(default_option);

		// now add all form fields (even if they're not included in the View)
		for (var j = 0; j < view_ns.all_form_fields.length; j++) {
			field_id = view_ns.all_form_fields[j].field_id;
			field_name = view_ns.all_form_fields[j].display_name;
			dd2.options[j + 1] = new Option(field_name, field_id);
		}
		td2.appendChild(dd2);

		// [3] third <td> cell: operator dropdown

		// TODO What if a date field is first?
		var td3 = document.createElement("td");

		// -- first section: DATE operators
		var first_div = document.createElement("div");
		first_div.setAttribute("id", "standard_filter_" + curr_row + "_operators_dates_div");
		first_div.style.cssText = "display: none";
		var operator_dd = document.createElement("select");
		operator_dd.setAttribute("name", "standard_filter_" + curr_row + "_operator_date");
		var option1 = document.createElement("option");
		option1.setAttribute("value", "before");
		option1.appendChild(document.createTextNode(g.messages["word_before"]));
		var option2 = document.createElement("option");
		option2.setAttribute("value", "after");
		option2.appendChild(document.createTextNode(g.messages["word_after"]));
		operator_dd.appendChild(option1);
		operator_dd.appendChild(option2);
		first_div.appendChild(operator_dd);

		// -- second section: REGULAR operators
		var second_div = document.createElement("div");
		second_div.setAttribute("id", "standard_filter_" + curr_row + "_operators_div");
		var operator_dd = document.createElement("select");
		operator_dd.setAttribute("name", "standard_filter_" + curr_row + "_operator");
		var option1 = document.createElement("option");
		option1.setAttribute("value", "equals");
		option1.appendChild(document.createTextNode(g.messages["word_equals"]));
		var option2 = document.createElement("option");
		option2.setAttribute("value", "not_equals");
		option2.appendChild(document.createTextNode(g.messages["phrase_not_equal"]));
		var option3 = document.createElement("option");
		option3.setAttribute("value", "like");
		option3.appendChild(document.createTextNode(g.messages["word_like"]));
		var option4 = document.createElement("option");
		option4.setAttribute("value", "not_like");
		option4.appendChild(document.createTextNode(g.messages["phrase_not_like"]));
		operator_dd.appendChild(option1);
		operator_dd.appendChild(option2);
		operator_dd.appendChild(option3);
		operator_dd.appendChild(option4);
		second_div.appendChild(operator_dd);
		td3.appendChild(first_div);
		td3.appendChild(second_div);

		// [4] fourth <td> cell: user defined values textbox
		var td4 = document.createElement("td");

		// -- first section: DATE textbox & select image
		var first_div = document.createElement("div");
		first_div.setAttribute("id", "standard_filter_" + curr_row + "_values_dates_div");
		first_div.style.cssText = "display: none";
		$(first_div).addClass("cf_date_group");

		var inp = document.createElement("input");
		inp.setAttribute("type", "text");
		inp.setAttribute("name", "standard_filter_" + curr_row + "_filter_date_values");
		inp.setAttribute("id", "standard_date_" + curr_row);

		var img = document.createElement("img");
		img.setAttribute("src", g.root_url + "/global/images/calendar.png");
		img.setAttribute("id", "standard_date_image_" + curr_row);
		img.setAttribute("border", "0");
		$(img).addClass("ui-datepicker-trigger");

		first_div.appendChild(inp);
		first_div.appendChild(img);

		// -- second section: REGULAR textbox
		var second_div = document.createElement("div");
		second_div.setAttribute("id", "standard_filter_" + curr_row + "_values_div");
		var inp2 = document.createElement("input");
		inp2.setAttribute("type", "text");
		inp2.setAttribute("name", "standard_filter_" + curr_row + "_filter_values");
		inp2.setAttribute("style", "width: 144px;");
		second_div.appendChild(inp2);
		td4.appendChild(first_div);
		td4.appendChild(second_div);

		// [5] a delete column
		var td5 = document.createElement("td");
		td5.setAttribute("align", "center");
		td5.setAttribute("class", "del"); // for Mozilla
		td5.className = "del"; // for IE
		var delete_link = document.createElement("a");
		delete_link.setAttribute("href", "#");
		$(delete_link).bind("click", { curr_row: curr_row }, function (e) {
			return view_ns.delete_filter_row("standard", e.data.curr_row);
		});
		td5.appendChild(delete_link);

		// add the table data cells to the row
		row.appendChild(td2);
		row.appendChild(td3);
		row.appendChild(td4);
		row.appendChild(td5);

		// add the row to the table
		$("#standard_filters_table tbody").append(row);
		$("#standard_date_" + curr_row).datetimepicker({
			showSecond: true,
			timeFormat: "hh:mm:ss",
			dateFormat: "yy-mm-dd"
		});
	}

	// update the filter count
	$("#num_standard_filters").val(view_ns.num_standard_filter_rows);
}


/**
 * Used to add rows to the client map filters table on the Edit View page.
 *
 * @param integer num_rows the number of rows to add
 */
view_ns.add_client_map_filters = function (num_rows) {
	if (num_rows.match(/\D/) || num_rows == 0 || num_rows == "") {
		ft.display_message("ft_message", false, g.messages["validation_num_rows_to_add"]);
		$("#num_client_map_filter_rows").focus();
		return;
	}

	var tbody = $("#client_map_filters_table tbody")[0];
	for (var i = 1; i <= num_rows; i++) {
		var curr_row = ++view_ns.num_client_map_filter_rows;
		var row = document.createElement("tr");
		row.setAttribute("id", "client_map_row_" + curr_row);

		// [1] first <td> cell: form field dropdown (defaulted to "please select")
		var td2 = document.createElement("td");
		var dd2 = document.createElement("select");
		dd2.setAttribute("name", "client_map_filter_" + curr_row + "_field_id");
		dd2.setAttribute("id", "client_map_filter_" + curr_row + "_field_id");

		// now add all form fields (even if they're not included in the View)
		var options = "<option value=\"\">" + g.messages["phrase_please_select"] + "</option>";
		for (var j = 0; j < view_ns.all_form_fields.length; j++) {
			var field_id = view_ns.all_form_fields[j].field_id;
			var field_name = view_ns.all_form_fields[j].display_name;
			options += "<option value=\"" + field_id + "\">" + field_name + "</option>";
		}
		$(dd2).append(options);
		td2.appendChild(dd2);

		// [3] third <td> cell: operator dropdown

		// TODO What if a date field is first?
		var td3 = document.createElement("td");

		// -- second section: REGULAR operators
		var div = document.createElement("div");
		div.setAttribute("id", "client_map_filter_" + curr_row + "_operators_div");
		var operator_dd = document.createElement("select");
		operator_dd.setAttribute("name", "client_map_filter_" + curr_row + "_operator");
		var option1 = document.createElement("option");
		option1.setAttribute("value", "equals");
		option1.appendChild(document.createTextNode(g.messages["word_equals"]));
		var option2 = document.createElement("option");
		option2.setAttribute("value", "not_equals");
		option2.appendChild(document.createTextNode(g.messages["phrase_not_equal"]));
		var option3 = document.createElement("option");
		option3.setAttribute("value", "like");
		option3.appendChild(document.createTextNode(g.messages["word_like"]));
		var option4 = document.createElement("option");
		option4.setAttribute("value", "not_like");
		option4.appendChild(document.createTextNode(g.messages["phrase_not_like"]));
		operator_dd.appendChild(option1);
		operator_dd.appendChild(option2);
		operator_dd.appendChild(option3);
		operator_dd.appendChild(option4);
		div.appendChild(operator_dd);
		td3.appendChild(div);

		// [4] fourth <td> cell: select dropdown
		var td4 = document.createElement("td");
		var dd = document.createElement("select");
		dd.setAttribute("style", "width: 160px;");
		dd.setAttribute("name", "client_map_filter_" + curr_row + "_client_field");

		var default_option = document.createElement("option");
		default_option.setAttribute("value", "");
		default_option.appendChild(document.createTextNode(g.messages["phrase_please_select"]));
		dd.appendChild(default_option);

		// add in the contents of the page_ns.clientFields array. For extensibility with
		// other modules, the options are grouped in optgroups.
		var current_section = null;
		var optgroup = null;
		for (var j = 0; j < page_ns.clientFields.length; j++) {
			if (page_ns.clientFields[j].section != current_section) {
				if (current_section != null) {
					dd.appendChild(optgroup);
				}

				optgroup = document.createElement("optgroup");
				current_section = page_ns.clientFields[j].section;
				optgroup.setAttribute("label", current_section);
			}

			var option = document.createElement("option");
			option.setAttribute("value", page_ns.clientFields[j].val);
			option.appendChild(document.createTextNode(page_ns.clientFields[j].text));
			optgroup.appendChild(option);
		}

		dd.appendChild(optgroup);

		// add any additional fields defined in the page (from the Extended Client Fields module)
		td4.appendChild(dd);

		// [5] a delete column
		var td5 = document.createElement("td");
		td5.setAttribute("align", "center");
		td5.setAttribute("class", "del"); // for Mozilla
		td5.className = "del"; // for IE
		var delete_link = document.createElement("a");
		delete_link.setAttribute("href", "#");
		$(delete_link).bind("click", { curr_row: curr_row }, function (e) {
			return view_ns.delete_filter_row("client_map", e.data.curr_row);
		});
		td5.appendChild(delete_link);

		// add the table data cells to the row
		row.appendChild(td2);
		row.appendChild(td3);
		row.appendChild(td4);
		row.appendChild(td5);

		// add the row to the table
		tbody.appendChild(row);
	}

	// update the filter count
	$("#num_client_map_filters").val(view_ns.num_client_map_filter_rows);
}


/**
 * Called by the form field dropdown onchange handler on the standard View filters table; shows the appropriate
 * operators and values section.
 *
 * @param integer row the row number
 * @param integer field_id the unique field ID
 */
view_ns.change_standard_filter_field = function (row) {
	var field_id = $("#standard_filter_" + row + "_field_id").val();

	// find out if this field is the submission date or not
	var is_date_field = false;
	for (var i = 0; i < view_ns.all_form_fields.length; i++) {
		var curr_field_id = view_ns.all_form_fields[i].field_id;
		if (curr_field_id == field_id) {
			is_date_field = view_ns.all_form_fields[i].is_date_field;
		}
	}

	if (is_date_field) {
		$("#standard_filter_" + row + "_operators_div, #standard_filter_" + row + "_values_div").hide();
		$("#standard_filter_" + row + "_operators_dates_div, #standard_filter_" + row + "_values_dates_div").show();
	} else {
		$("#standard_filter_" + row + "_operators_div, #standard_filter_" + row + "_values_div").show();
		$("#standard_filter_" + row + "_operators_dates_div, #standard_filter_" + row + "_values_dates_div").hide();
	}
}


/**
 * This function deletes an individual row. Note that this does NOT re-id all the other fields (e.g.
 * after deleting row 5, row 6 still has an id of row_6) nor does it decrement the filter row
 * counter "view_ns.num_filter_rows". This is done for simplicity. The PHP function that handles the
 * update discards any rows without a FORM specified, so the absent row(s) are not important. The
 * num_filters hidden field (which stores the view_ns.num_filter_rows value) IS important, though -
 * that lets the PHP function know how the MAX rows to loop over. It ignored the empty rows.
 * So again, it's fine that the actual number of rows passed is less.
 *
 * @param string table "standard", "client_map"
 * @param integer row the row number
 */
view_ns.delete_filter_row = function (table, row) {
	// get the current table
	var table_id = null;
	if (table == "standard") {
		table_id = "standard_filters_table";
		row_id_prefix = "standard_";
	} else {
		table_id = "client_map_filters_table";
		row_id_prefix = "client_map_";
	}

	$("#" + row_id_prefix + "row_" + row).remove();

	return false;
}


/**
 * Called whenever the user clicks the "Update View" button. It does some elementary field
 * validation and ensures the data is in a state ready for the PHP.
 *
 * @param the form element
 */
view_ns.process_form = function (f) {
	var rules = [];
	rules.push("required,view_name," + g.messages['validation_no_view_name']);
	rules.push("required,num_submissions_per_page," + g.messages['validation_no_num_submissions_per_page']);
	if (!rsv.validate(f, rules)) {
		return ft.change_inner_tab(1, "edit_view"); // this always returns false
	}

	// select all clients
	ft.select_all("selected_user_ids");

	return true;
}


view_ns.toggle_filter_section = function (section) {
	var section_id = null;
	if (section == "client_map") {
		section_id = "client_map_filters";
	} else {
		section_id = "standard_filters";
	}

	var display_setting = $("#" + section_id).css("display");
	if (display_setting == 'none') {
		$("#" + section_id).show("blind");
	} else {
		$("#" + section_id).hide("blind");
	}

	return false;
}


/**
 * Open the Add Fields dialog after the user clicks on the Add Fields(s) >> link for a specific group.
 */
view_ns.add_fields_dialog = function () {
	view_ns.curr_group = $(this).closest(".sortable_group");

	$("#add_fields_popup .error").addClass("hidden");

	// figure out what fields haven't already been added and add the HTML into the dialog
	var available_field_info = view_ns.get_available_view_fields();
	$("#add_fields_popup_available_fields").html(available_field_info.html);

	var buttons = [{
		text: g.messages["word_close"],
		click: function () {
			view_ns._close_add_fields_dialog(this);
		}
	}];

	if (available_field_info.num_fields > 0) {
		$("#add_fields_popup .two_buttons input").attr("disabled", "");
		buttons.unshift({
			text: g.messages["phrase_add_fields"],
			click: function () {
				var field_ids = [];
				$('#add_fields_popup .adding_field_ids').each(function () {
					if (!this.checked) {
						return;
					}
					field_ids.push(this.value);
				});

				if (!field_ids.length) {
					$("#add_fields_popup .error div").html(g.messages["validation_no_view_fields_selected"]).parent().removeClass("hidden");
				} else {
					view_ns.add_view_fields(field_ids);
					view_ns._close_add_fields_dialog(this);
				}
			}
		});
	} else {
		$("#add_fields_popup .two_buttons input").attr("disabled", "disabled");
	}

	ft.create_dialog({
		dialog: $("#add_fields_popup"),
		title: g.messages["phrase_add_fields"],
		min_width: 500,
		min_height: 360,
		buttons: buttons
	});

	return false;
}


view_ns._close_add_fields_dialog = function (dialog) {
	$("#add_fields_popup_available_fields").html("");
	$(dialog).dialog("close");
}


/**
 * Figures out how many fields are left that aren't currently used in the View. This function
 * return an object with the following keys:
 *
 * @return object {
 *                  "num_fields": the number of rows available
 *                  "html":       the HTML of the rows to insert in the dialog
 *                }
 */
view_ns.get_available_view_fields = function () {
	var selected_field_ids = [];
	$(".inner_tab_content3 .sr_order").each(function () {
		selected_field_ids.push(parseInt(this.value));
	});

	var html = "";
	var num_fields = 0;
	if (selected_field_ids.length < view_ns.all_form_fields.length) {
		html = "<ul>";
		for (var i = 0; i < view_ns.all_form_fields.length; i++) {
			if ($.inArray(view_ns.all_form_fields[i].field_id, selected_field_ids) != -1) {
				continue;
			}
			html += "<li><input type=\"checkbox\" class=\"adding_field_ids\" value=\"" + view_ns.all_form_fields[i].field_id + "\" "
				+ "id=\"r" + i + "\" /><label for=\"r" + i + "\">" + view_ns.all_form_fields[i].display_name + "</label></li>";
			num_fields++;
		}
		html += "</ul>";
	} else {
		html += "<div class=\"light_grey margin_left_small\">" + g.messages["phrase_all_fields_displayed"] + "</div>";
	}

	return {
		num_fields: num_fields,
		html: html
	};
}


/**
 * Adds one or more fields to the appropriate View group.
 */
view_ns.add_view_fields = function (field_ids) {
	var rows = [];

	for (var i = 0; i < field_ids.length; i++) {
		var field_id = field_ids[i];
		var field_name = view_ns.get_field_name(field_id);

		// a little irksome. All fields may be editable except Last Modified and Submission ID
		var field_info = {};
		for (var j = 0; j < view_ns.all_form_fields.length; j++) {
			if (view_ns.all_form_fields[j].field_id != field_id) {
				continue;
			}
			field_info = view_ns.all_form_fields[j];
		}
		var is_editable = true;
		if ($.inArray(field_info.col_name, ["submission_id", "last_modified_date"]) != -1) {
			is_editable = false;
		}

		var row_html = '<div class="row_group">'
			+ '<input type="hidden" value="' + field_id + '" class="sr_order">'
			+ '<ul>'
			+ '<li class="col0"></li>'
			+ '<li class="col1 sort_col"></li>'
			+ '<li class="col2">' + field_name + '</li>'
			+ '<li class="col3 medium_grey">' + view_ns.field_type_map["ft" + field_info.field_type_id] + '</li>'

		if (is_editable) {
			row_html += '<li class="col4 check_area"><input type="checkbox" checked="checked" class="editable_fields" value="' + field_id + '" name="editable_fields[]" /></li>';
		} else {
			row_html += '<li class="col4"></li>';
		}

		row_html += '<li class="col5 check_area"><input type="checkbox" checked="checked" value="' + field_id + '" name="searchable_fields[]" /></li>'
			+ '<li class="col6 colN del"><a onclick="return view_ns.remove_view_field(' + field_id + ')" href="#"></a></li>'
			+ '</ul>'
			+ '<div class="clear"></div>'
			+ '</div>';

		rows.push(sortable_ns.get_sortable_row_markup({ row_group: row_html, is_grouped: true }));
	}

	view_ns.curr_group.find(".rows").append(ft.group_nodes(rows));
	sortable_ns.reorder_rows(view_ns.curr_group, false);
}


/**
 * This opens the Add Group dialog window, allowing users to create a new group and assign fields in one
 * go. Note that this does NOT use the default add group functionality defined in sortables.js - we needed
 * more control, hence the customized version.
 */
view_ns.add_field_group = function () {
	var available_field_info = view_ns.get_available_view_fields();
	$("#add_group_popup_available_fields").html(available_field_info.html);
	$(".new_group_name").val("");

	ft.create_dialog({
		dialog: $("#add_group_popup"),
		title: $(".add_group_popup_title").val(),
		min_width: 500,
		buttons: [{
			"text": g.messages["phrase_create_group"],
			"click": function () {
				// note we use a custom insert_new_group function, defined on the view_ns namespace
				view_ns.insert_new_group({
					group_id: "NEW" + view_ns.curr_new_group_id,
					group_name: $(".new_group_name").val()
				});
				view_ns.curr_new_group_id++;

				$("#no_view_fields_defined").hide();
				$("#allow_editable_fields_toggle").show();

				// now insert all selected rows
				var field_ids = [];
				$('#add_group_popup .adding_field_ids').each(function () {
					if (!this.checked) {
						return;
					}
					field_ids.push(this.value);
				});
				view_ns.curr_group = $(".sortable_group:last");
				view_ns.add_view_fields(field_ids);

				// we clear the markup because both the add group and fields popup add the same markup with
				// the same IDs for the labels
				$("#add_group_popup_available_fields").html("");
				$(this).dialog("close");
			}
		},
			{
				"text": g.messages["word_cancel"],
				"click": function () {
					$("#add_group_popup_available_fields").html("");
					$(this).dialog("close");
				}
			}]
	});

	return false;
}


/**
 * Our custom insert_new_group function. Normally you'd use sortable_ns.insert_new_group, but the
 * View field groups contain custom header: i.e. the tabs dropdown.
 */
view_ns.insert_new_group = function (info) {
	var new_group_name = info.group_name;
	var new_group_id = info.group_id;

	var group_label = $(".sortable__new_group_name").val();
	var sortable_class = $(".sortable__class").val();

	// for the tab dropdown, see if it's already defined in the page. If so, just copy the contents - otherwise
	// we need to manually construct it [TODO: check this on IE... I think the selected value of the first group's
	// tab will be passed over]
	var tabs_dropdown = $(".tabs_dropdown");
	var tab_options = "";
	if (tabs_dropdown.length) {
		tab_options = $(".tabs_dropdown:first").html();
	} else {
		var tabs = view_ns.get_tab_dropdown_contents();
		if (tabs.length == 0) {
			tab_options = "<option value=\"\">" + g.messages["validation_no_tabs_defined"] + "</option>";
		} else {
			tab_options = "<optgroup label=\"" + g.messages["phrase_available_tabs"] + "\">";
			for (var i = 0; i < tabs.length; i++) {
				tab_options += "<option value=\"" + tabs[i].tab + "\">" + tabs[i].label + "</option>";
			}
			tab_options += "</optgroup>";
		}
	}

	var html = "<div class=\"sortable_group\">\n"
		+ "<div class=\"sortable_group_header\">\n"
		+ "<div class=\"sort\"></div>\n"
		+ "<label>" + group_label + "</label>\n"
		+ "<input type=\"text\" name=\"group_name_" + new_group_id + "\" class=\"group_name\" value=\""
		+ new_group_name.replace(/"/, "&quot;") + "\" />\n"
		+ "<select name=\"group_tab_" + new_group_id + "\" class=\"tabs_dropdown\">"
		+ tab_options
		+ "</select>"
		+ "<div class=\"delete_group\"></div>\n"
		+ "<input type=\"hidden\" class=\"group_order\" value=\"" + new_group_id + "\" />\n"
		+ "<div class=\"clear\"></div>\n"
		+ "</div>\n"
		+ "<div class=\"sortable " + sortable_class + "\">\n";

	html += $("#sortable__new_group_header").html();

	html += "<div class=\"clear\"></div>\n"
		+ "<ul class=\"rows connected_sortable\">\n"
		+ "<li class=\"sortable_row rowN empty_group\"><div class=\"clear\"></div></li>"
		+ "</ul>\n"
		+ "</div>\n"
		+ "<div class=\"clear\"></div>\n";

	if ($("#sortable__new_group_footer").length) {
		html += $("#sortable__new_group_footer").html();
	}

	html += "</div>\n";

	sortable_ns.append_new_sortable_group(html);
}

view_ns.add_fields_select_all = function () {
	$('.adding_field_ids').each(function () {
		this.checked = true;
		$(this).closest("li").addClass("selected_row");
	});
}
view_ns.add_fields_unselect_all = function () {
	$('.adding_field_ids').each(function () {
		this.checked = false;
		$(this).closest("li").removeClass("selected_row");
	});
}


/**
 * We keep the delete View group really simple: just remove it from the DOM. I don't want to
 * pester the user with confirmation requests for *anything* on the Edit View fields page: it should
 * be as speedy as possible.
 *
 * @param node the delete_group link node.
 */
view_ns.delete_field_group = function (el) {
	var sortable_group = $(el).closest(".sortable_group");
	var group_id = sortable_group.find(".group_order").val();
	sortable_group.remove();

	var deleted_groups_str = $("#deleted_groups").val();
	var updated_str = (deleted_groups_str == "") ? group_id : deleted_groups_str + "," + group_id;
	$("#deleted_groups").val(updated_str);

	// if there are no other groups in the page, show the default message
	if ($(".sortable_group").length == 0) {
		$("#no_view_fields_defined").show();
		$("#allow_editable_fields_toggle").hide();
	}
}


view_ns.add_default_values_for_submission = function () {
	var row_html = "<tr><td><select name=\"new_submissions[]\" class=\"new_submission_default_val_fields\">"
		+ "<option value=\"\">" + g.messages["phrase_please_select"] + "</option>";
	for (var i = 0; i < view_ns.all_form_fields.length; i++) {
		if (view_ns.all_form_fields[i].is_system_field) {
			continue;
		}
		row_html += "<option value=\"" + view_ns.all_form_fields[i].field_id + "\">" + view_ns.all_form_fields[i].display_name + "</option>";
	}
	row_html += "</select></td><td><input type=\"text\" name=\"new_submissions_vals[]\" class=\"new_submission_default_vals\" /></td>"
		+ "<td class=\"del\"><a href=\"#\" onclick=\"return view_ns.delete_new_view_submission_vals(this)\"></a></td></tr>";

	$("#new_view_default_submission_vals tbody").append(row_html);
	return false;
}


view_ns.delete_new_view_submission_vals = function (el) {
	$(el).closest("tr").remove();

	// if there are no more rows, hide the entire section (the first row is the heading)
	if ($("#new_view_default_submission_vals tr").length <= 1) {
		$("#no_new_submission_default_values").removeClass("hidden");
		$("#new_submission_default_values").addClass("hidden");
	}

	return false;
}


/**
 * Helper function to empty the 6 tab label fields (with "tab_label" class).
 */
view_ns.remove_tabs = function () {
	$(".tab_label").val("");
	view_ns.update_tab_dropdowns();
}


/* Submission Listing tab code */


/**
 * Adds a new row to the Submission List tab so that it will appear as a column on the Submission Listing page.
 */
view_ns.add_view_column = function () {
	$("#no_view_columns_defined").hide();
	$("#submission_list").show();

	var row_num = ++view_ns.num_view_columns;
	var row_html = '<div class="row_group">'
		+ '<input type="hidden" value="' + row_num + '" class="sr_order">'
		+ '<ul>'
		+ '<li class="col1 sort_col"></li>'
		+ '<li class="col2">'
		+ '<select name="field_id_' + row_num + '">'
		+ '<option value="">' + g.messages["phrase_please_select"] + '</option>';

	// now add all form fields (even if they're not included in the View)
	for (var j = 0; j < view_ns.all_form_fields.length; j++) {
		field_id = view_ns.all_form_fields[j].field_id;
		field_name = view_ns.all_form_fields[j].display_name;
		row_html += '<option value="' + field_id + '">' + field_name + '</option>';
	}

	row_html += '</select>'
		+ '</li>'
		+ '<li class="col3 check_area"><input type="checkbox" name="is_sortable_' + row_num + '" checked /></li>'
		+ '<li class="col4 light_grey">'
		+ '<input type="checkbox" name="auto_size_' + row_num + '" id="auto_size_' + row_num + '" class="auto_size" checked />'
		+ '<label for="auto_size_' + row_num + '" class="black">' + g.messages["phrase_auto_size"] + '</label>'
		+ ' &#8212; ' + g.messages["word_width_c"] + ' '
		+ '<input type="text" name="custom_width_' + row_num + '" class="custom_width" disabled />px'
		+ '</li>'
		+ '<li class="col5">'
		+ '<select name="truncate_' + row_num + '">'
		+ '<option value="truncate">' + g.messages["word_yes"] + '</option>'
		+ '<option value="no_truncate">' + g.messages["word_no"] + '</option>'
		+ '</select>'
		+ '</li>'
		+ '<li class="col6 colN del"></li>'
		+ '</ul>'
		+ '<div class="clear"></div>'
		+ '</div>';

	var new_row = sortable_ns.get_sortable_row_markup({ row_group: row_html, is_grouped: false });

	$("#submission_list").find(".rows").append(new_row);
	sortable_ns.reorder_rows($("#submission_list"), false);

	return false;
}


/**
 * A custom delete View column handler, added to detect if there are any columns left. If not, it shows the sortable
 * section altogether and shows a message telling them to add. It uses the Core delete row function.
 */
view_ns.delete_view_column = function (el) {

	// if there are no other groups in the page, show the default message
	if ($(".submission_list .rows .sortable_row").length == 0) {
		$("#no_view_columns_defined").show();
		$("#submission_list").hide();
	}

	sortable_ns.delete_row("submission_list", el);
}

