/**
 * This code is used for managing the Edit Option List pages; most notably, it contains the Smart
 * Fill code for parsing HTML files (and uploading them, if need be).
 */

sf_ns = {}; // Smart Fill namespace... (old naming scheme)
sf_ns.num_rows = null; // set by onload function
sf_ns.tmp_deleted_field_option_rows = [];
sf_ns.manual_file_upload_attempted = false;
sf_ns.error_dialog = $("<div></div>");
sf_ns.delete_option_list_dialog = $("<div></div>");
sf_ns.delete_group_dialog = $("<div></div>");
sf_ns.num_new_groups = 0; // keeps track of the number of new groups added to the page


/**
 * Deletes an Option List. The second "may_delete" boolean parameter is determined by whether this
 * field option group is used by any fields. If it is, they can't delete it: they need to re-assign the fields
 * to other option groups or change the field types.
 *
 * @param integer list_id
 * @param boolean may_delete
 */
sf_ns.delete_option_list = function (list_id, may_delete) {
	var content = g.messages["confirm_delete_option_list"];
	if (!may_delete) {
		content = "<div class=\"red\">" + g.messages["validation_delete_non_empty_option_list"] + "</div>" + content;
	}

	ft.create_dialog({
		dialog: sf_ns.delete_option_list_dialog,
		popup_type: "warning",
		title: g.messages["phrase_please_confirm"],
		content: content,
		buttons: [{
			"text": g.messages["word_yes"],
			"click": function () {
				ft.dialog_activity_icon(this, "show");
				window.location = "index.php?delete=" + list_id;
			}
		},
			{
				"text": g.messages["word_no"],
				"click": function () {
					$(this).dialog("close");
				}
			}]
	});

	return false;
}


/**
 * Called during Smart Fill. It removes the entire content of the page.
 */
sf_ns.delete_all_rows = function () {
	$(".sortable_group").remove();
	sf_ns.num_rows = 0;
}


/**
 * Adds a field option for the currently selected field (dropdown, radio or checkbox).
 */
sf_ns.add_field_options = function (num_rows, target_el) {
	var num_rows = $.trim(num_rows);

	// check num_rows is an integer
	if (num_rows.match(/\D/) || num_rows == 0 || num_rows == "") {
		ft.create_dialog({
			dialog: sf_ns.error_dialog,
			popup_type: "error",
			title: g.messages["word_error"],
			content: g.messages["validation_num_rows_to_add"],
			buttons: [{
				"text": g.messages["word_okay"],
				"click": function () {
					$(this).dialog("close");
					$("#num_rows_to_add").focus().select();
				}
			}]
		});
		$("#num_rows_to_add").focus().select();
		return false;
	}

	var num_rows = parseInt(num_rows);

	for (var i = 0; i < num_rows; i++) {
		var curr_row = ++sf_ns.num_rows;

		var li0 = $("<li class=\"col0\"></li>");
		var li1 = $("<li class=\"col1 sort_col\">" + curr_row + "</li>");
		var li2 = $("<li class=\"col2\"><input type=\"text\" name=\"field_option_value_" + curr_row + "\" /></li>");
		var li3 = $("<li class=\"col3\"><input type=\"text\" name=\"field_option_text_" + curr_row + "\" /></li>");
		var li4 = $("<li class=\"col4 colN del\"></li>");

		var ul = $("<ul></ul>");
		ul.append(li0);
		ul.append(li1);
		ul.append(li2);
		ul.append(li3);
		ul.append(li4);

		var main_div = $("<div class=\"row_group\"><input type=\"hidden\" class=\"sr_order\" value=\"" + curr_row + "\" /></div>");
		main_div.append(ul);
		main_div.append("<div class=\"clear\"></div>");

		$(target_el).append(sortable_ns.get_sortable_row_markup({ row_group: main_div }));
		sortable_ns.reorder_rows(target_el, false);
	}

	// always hide the empty group item
	$(target_el).find(".empty_group").hide();

	return false;
}


/**
 * This attempts to smart fill a single field, based on a form field name and a website page. It
 * assumes the page_ns.scrape_page value has been set ("file_get_contents", "curl" or "redirect") to
 * indicate the method by which the Smart Fill will be used. This is determined automatically by
 * system compatibility.
 */
sf_ns.smart_fill_field = function () {
	var smart_fill_source_form_field = $("#smart_fill_source_form_field").val();
	var smart_fill_source_url = $("#smart_fill_source_url").val();

	if (smart_fill_source_form_field == "" || smart_fill_source_url == "") {
		ft.display_message("smart_fill_messages", false, g.messages["validation_no_smart_fill_values"]);
		return false;
	}

	if (!ft.is_valid_url(smart_fill_source_url)) {
		ft.display_message("smart_fill_messages", false, g.messages["validation_invalid_url"]);
		return false;
	}

	// find out the appropriate scrape method to extract this field's contents
	sf_ns.log_activity(true);
	$.ajax({
		url: g.root_url + "/global/code/actions.php",
		data: { action: "get_js_webpage_parse_method", url: smart_fill_source_url },
		type: 'POST',
		dataType: "json",
		success: sf_ns.process_js_webpage_parse_method_response,
		error: ft.error_handler
	});
}


sf_ns.process_js_webpage_parse_method_response = function (data) {

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

	// if their server doesn't support any of the page scraping methods, offer them the option
	// of uploading the file manually
	if (data.scrape_method == "") {
		ft.display_message("smart_fill_messages", false, $("#upload_files_text").html());
		sf_ns.log_activity(false);
	} else {
		var page_url = g.root_url + "/global/code/actions.php?action=smart_fill&scrape_method=" + data.scrape_method
			+ "&url=" + $("#smart_fill_source_url").val();
		$("#hidden_iframe").attr("src", page_url);
	}
}


/**
 * When the contents of the iframe are fully loaded (and, namely, the content is now available to JS), this
 * function is called. It logs the page as loaded. Once all form pages are loaded, it loads all the form
 * field information into memory for analyzing by the Smart Fill function.
 */
sf_ns.log_form_page_as_loaded = function () {
	sf_ns.log_activity(false);
	if (!page_ns.page_initialized) {
		page_ns.page_initialized = true;
		return;
	}

	// try to smart fill the field requested
	var iframe_element = hidden_iframe.window.document;
	var field_name = $("#smart_fill_source_form_field").val();
	var num_forms = iframe_element.forms.length;

	var form_index = null;
	for (var i = 0; i < num_forms; i++) {
		if (iframe_element.forms[i][field_name] || iframe_element.forms[i][field_name + "[]"]) {
			form_index = i;
		}
	}

	if (form_index == null) {
		ft.display_message("smart_fill_messages", false, g.messages["validation_smart_fill_no_field_found"]);
		return;
	}

	// if this was the result of manually uploading a file, be optimistic and tell them it worked (this is
	// overwritten if anything fails)
	if (sf_ns.manual_file_upload_attempted) {
		ft.display_message("smart_fill_messages", true, g.messages["notify_field_options_smart_filled"]);
	}

	sf_ns.delete_all_rows();


	// get our field (checks for myField[] syntax, too)
	if (iframe_element.forms[form_index][field_name]) {
		var field = iframe_element.forms[form_index][field_name];
	} else {
		var field = iframe_element.forms[form_index][field_name + "[]"];
	}

	// if field.type is undefined, it's probably an array
	if (field.type == undefined) {
		field.type = field[0].type;
	}

	// if field.type is still undefined, Smart Fill won't work. Alert the user
	if (field.type == undefined) {
		ft.display_message("smart_fill_messages", false, g.messages["validation_smart_fill_cannot_fill"]);
		return;
	}

	// okay! We're about to add in all the default items. Tot them all up here. We'll add them to the page
	// at the end
	var has_option_lists = false;
	var grouped_fields = [];

	switch (field.type) {
		case "select-one":
		case "select-multiple":
			has_option_lists = ($(field).find("optgroup").length > 0) ? true : false;
			if (has_option_lists) {
				$(field).find("optgroup").each(function () {
					var group_name = $(this).attr("label");
					var fields = [];
					$(this).find("option").each(function () {
						fields.push({ "value": this.value, "label": $(this).html() });
					});
					grouped_fields.push({
						"group_name": group_name,
						"fields": fields
					});
				});
			} else {
				var fields = [];
				for (var i = 0; i < field.length; i++) {
					fields.push({ "value": field[i].value, "label": field[i].text });
				}
				grouped_fields.push({
					"group_name": "",
					"fields": fields
				});
			}
			break;

		case "checkbox":
		case "radio":
			is_single = true;
			if (field.length != undefined) {
				is_single = false;
			}

			// single checkbox
			if (is_single) {
				grouped_fields.push({
					"group_name": "",
					"fields": [{ "value": field.value, "label": "" }]
				});

				// multiple checkboxes
			} else {
				var fields = [];
				for (var i = 0; i < field.length; i++) {
					fields.push({ "value": field[i].value, "label": "" });
				}
				grouped_fields.push({
					"group_name": "",
					"fields": fields
				});
			}
			break;

		default:
			ft.display_message("smart_fill_messages", false, g.messages["validation_smart_fill_invalid_field_type"]);
			break;
	}

	if (grouped_fields[0].fields.length == 0) {
		alert("no fields found!"); // ...!
	} else {
		// create the groups
		// *** bit concerned about timing issues here, but haven't encountered problems in FF 3.6 ***
		var row_count = 1;
		for (var i = 0; i < grouped_fields.length; i++) {
			sf_ns.num_new_groups++;
			var info = {
				group_id: "NEW" + sf_ns.num_new_groups,
				group_name: grouped_fields[i].group_name
			}
			sortable_ns.insert_new_group(info);

			// add the right number of blank rows
			sf_ns.add_field_options(grouped_fields[i].fields.length, $(".sortable_group:last .rows"));

			// now add the actual items. This relies on sf_ns.num_rows having being reset to 0 earlier on
			for (var j = 0; j < grouped_fields[i].fields.length; j++) {
				$("input[name=field_option_value_" + row_count + "]").val(grouped_fields[i].fields[j].value);
				$("input[name=field_option_text_" + row_count + "]").val(grouped_fields[i].fields[j].label);
				row_count++;
			}
		}

		if (has_option_lists) {
			$(".add_ungrouped_rows").hide();
			$(".sortable_group_header, .sortable_group_footer").removeClass("hidden");
			$(".add_group_section").removeClass("hidden");
			$("#go1").attr("checked", "checked");
		} else {
			$(".add_ungrouped_rows").show();
			$(".sortable_group_header, .sortable_group_footer").addClass("hidden");
			$(".add_group_section").removeClass("hidden");
			$("#go2").attr("checked", "checked");
		}
	}
}


/**
 * This is called whenever starting or ending any potentially lengthy JS operation. It hides/shows the
 * ajax loading icon.
 */
sf_ns.log_activity = function (is_busy) {
	sf_ns.is_busy = is_busy;

	if (is_busy) {
		$("#ajax_activity").show();
		$("#ajax_no_activity").hide();
	} else {
		$("#ajax_activity").hide();
		$("#ajax_no_activity").show();
	}
}


/**
 * This function can be optionally called by the user if the Smart Fill couldn't read the web pages. It
 * uploads copies of the forms to the server.
 */
sf_ns.validate_upload_file = function (f) {
	// check all the fields have been entered
	if (!f["form_page_1"].value) {
		alert(g.messages["validation_smart_fill_no_page"]);
		return false;
	}

	// check it's a .html or .htm file
	if (!f["form_page_1"].value.match(/(\.htm|\.html)$/)) {
		alert(g.messages["validation_upload_html_files_only"]);
		return false;
	}

	// show the processing icon; this is turned off when the custom onload handler is executed for the
	// upload_files_iframe
	sf_ns.log_activity(true);
	sf_ns.manual_file_upload_attempted = true;

	return true;
}


/**
 * Called when submitting the Edit Field Option Group main tab. It just
 * ensures the option list name is valid.
 */
sf_ns.submit_update_field_option_group_page = function () {
	var option_list_field = $("#option_list_name");
	var group_name = $.trim(option_list_field.val());
	if (group_name == "") {
		$("#delete_group_dialog").dialog("close"); // just in case
		ft.create_dialog({
			dialog: sf_ns.error_dialog,
			popup_type: "error",
			title: g.messages["word_error"],
			content: g.messages["validation_no_option_list_name"],
			buttons: [{
				"text": g.messages["word_okay"],
				"click": function () {
					$(this).dialog("close");
					option_list_field.focus().select();
				}
			}]
		});
		option_list_field.focus().select();
		return false;
	}

	// check to see if the list group name is already taken
	for (var i = 0; i < page_ns.option_list_names.length; i++) {
		if (group_name == page_ns.option_list_names[i]) {
			$("#delete_group_dialog").dialog("close"); // just in case
			ft.create_dialog({
				dialog: sf_ns.error_dialog,
				popup_type: "error",
				title: g.messages["word_error"],
				content: g.messages["validation_option_list_name_taken"],
				buttons: [{
					"text": g.messages["word_okay"],
					"click": function () {
						$(this).dialog("close");
						option_list_field.focus().select();
					}
				}]
			});
			option_list_field.focus().select();
			return false;
		}
	}

	return true;
}


sf_ns.add_group = function () {
	sf_ns.num_new_groups++;
	var info = {
		group_id: "NEW" + sf_ns.num_new_groups,
		group_name: $(".new_group_name").val()
	}
	sortable_ns.insert_new_group(info);
	$("#add_group_popup").dialog("close");
}


/**
 * For option lists, it's very possible that the user wants to delete an entire option list - including
 * the contents - in one click. The default behaviour of the grouped sortables is to only permit it
 * if the group is empty. This custom delete handler overrides the default behaviour.
 *
 * @param node the delete group icon that was clicked
 */
sf_ns.delete_group = function (el) {
	$(el).closest(".sortable_group").remove();
}

sf_ns.toggle_advanced_settings = function () {
	var display_setting = $("#option_lists_advanced_settings").css("display");
	if (display_setting == "none") {
		$("#option_lists_advanced_settings").slideDown(200);
		$("#smart_fill_source_form_field").focus();
	} else {
		$("#option_lists_advanced_settings").slideUp(200);
	}
	return false;
}
