/**
 *  @fileoverview This .js file contains functions for public and and admin
 *  updates to the arts directory.
 *
 *    hideForm(name)
 *    makeFormArray(form)---to be deprecated
 *    markChanges(form)---to be deprecated
 *    setIsChanged()
 *    showForm(name)
 *    submitData(els, spanId)
 *    toggleDisplay(name)
 *    uncheck(els, name)
 *    unsetIsChanged()
 *    verifyEmail(el)
 *    verifyPhone(el)
 *  AJAX functions
 *    handleResponse()
 *    update(id, values)
 *    updateContent(name)
 *
 *  @todo   remove alert(e) in catch blocks;
 */

/**
 *  True if a form field has been changed.
 *  @type   Boolean
 */
var isChanged = false;

/**
 *  Sets isChanged true;
 *
 *  @type   void
 */
function setIsChanged()
{
  isChanged = true;
}

/**
 *  Sets isChanged false;
 *
 *  @type   void
 */
function unsetIsChanged()
{
  isChanged = false;
}

/**
 *  Processed array of form elements. Used by old update pages.
 *  @type   Array
 */
var formArray = new Array();

/**
 *  Populates formArray[] with selected form elements. Used by old update pages.
 *
 *  @param  {HTMLFormElement} form
 *  @type   void
 */
function makeFormArray(form)
{
  var els = form.elements;
  var options, optValues, is1st;

  for (var i = 0; i < els.length; i++) {
    if (els[i].type == "select-multiple") {
      options = els[i].options;
      is1st = true;
      optValues="";
      for (var j = 0; j < options.length; j++) {
        if (options[j].selected) {
          if (is1st) {
            is1st = false;
          }
          else {
            optValues += ",";
          }
          optValues += options[j].value;
        }
      }
      formArray[i] = optValues;
    }
    else {
      formArray[i] = els[i].value;
    }
  }
}

/**
 *  Sets the value of hidden 'changes' field. Used by old update pages.
 *
 *  @param  {HTMLFormElement} form
 *  @type   Boolean
 *  @return If field passes validation then true else false.
 */
function markChanges(form)
{
  if (!verifyADUpdate(form)) {
    return false;
  }

  var el, is1stOpt, optValues;
  var is1stChange = true;
  var changes = form.elements["changes"];

  changes.value = "";

  for (var i = 0; i < formArray.length; i++) {
    el = form.elements[i];

    if (el.name != "changes") {
      if (el.type == "select-multiple") {
        is1stOpt = true;
        optValues = "";
        for (var j = 0; j < el.options.length; j++) {
          if (el.options[j].selected) {
            if (is1stOpt) {
              is1stOpt = false;
            }
            else {
              optValues += ",";
            }
            optValues += el.options[j].value;
          }
        }
        if (formArray[i] != optValues) {
          if (is1stChange) {
            is1stChange = false;
          }
          else {
            changes.value += ",";
          }
          changes.value += el.name;
        }
      }
      else if (formArray[i] != el.value) {
        if (!is1stChange) {
          changes.value += ",";
        }
        else {
          is1stChange = false;
        }
        changes.value += el.name;
      }
    }
  }
  return true;
}

/**
 *  Toggles form and div view.
 *
 *  @param  {String} name   div/form to toggle
 *  @type   void
 */
function toggleDisplay(name)
{
  if (currentName && currentName != name) {
    hideForm(currentName);
  }

  if (document.getElementById(name + "_div").style.display == "none") {
    hideForm(name);
  }
  else {
    showForm(name);
  }
}

/**
 *  Name of form currently displayed.
 *  @type   mixed   Boolean/String
 */
var currentName = false;

/**
 *  Hides the named form and shows its associated div.
 *
 *  @param  {String} name
 *  @type   void
 */
function hideForm(name)
{
  try {
    document.getElementById(name + "_div").style.display = "block";
    document.getElementById(name + "_form").style.display = "none";
  }
  catch (e) { alert(e); }

  currentName = false;
}

/**
 *  Shows the named form and hides its associated div.
 *
 *  @param  {String} name
 *  @type   void
 */
function showForm(name)
{
  try {
    document.getElementById(name + "_div").style.display = "none";
    document.getElementById(name + "_form").style.display = "block";
  }
  catch (e) { alert(e); }

  currentName = name;
}

/**
 *  Sets the checked attributes of the named elements to false.
 *
 *  @param  {array HTMLFormElement} els   a collection of elements
 *  @param  {String} name                 element name to target
 */
function uncheck(els, name)
{
  for (var i = 0; i < els.length; i++) {
    if (els[i].name == name) {
      try {
        els[i].checked = false;
      }
      catch (e) {}
    }
  }
}

/**
 *  Prepares data for submission: builds array, updates page text, and calls
 *  update();
 *
 *  @param  {Array} data          updates form element data as retrieved from DB
 *  @param  {HTMLCollection} els  collection of form elements
 *  @param  {String} spanId       id of span containing page content
 *  @type   void
 */
function submitData(els, spanId)
{
  // if form has no changes then do nothing
  if (!isChanged) {
    return;
  }

  var data = new Object();
  data.VisualArt = new Array();
  data.Performance = new Array();
  data.School = new Array();
  data.Offerings = new Array();
  data.InstructChild = new Array();
  data.InstructAdult = new Array();
  data.ExhibitTypes = new Array();
  data.OrgType = new Array();

  var s = "";
  var v, item, count = 0;

  unsetIsChanged();

  for (var i = 0; i < els.length; i++) {
    switch (els[i].name) {
      case "submit":
      case "cancel":
        break;

      case "VisualArt":
      case "Performance":
      case "School":
      case "Offerings":
      case "InstructChild":
      case "InstructAdult":
      case "ExhibitTypes":
      case "OrgType":
        if (els[i].checked) {
          data[els[i].name].push(els[i].value);
        }
        break;

      case "visual_art_nix":
        if (els["visual_art_nix"].checked) {
          data["VisualArt"] = null;
        }
        break;

      case "performance_nix":
        if (els["performance_nix"].checked) {
          data["Performance"] = null;
        }
        break;

      default:
        if ((v = els[i].value.trim()) != "") {
          data[els[i].name] = (els[i].tagName == "TEXTAREA") ? addBreaks(v) : v;
        }
        else {
          data[els[i].name] = null;
        }
    }
  }

  // update page content to match form
  for (item in data) {
    switch (item) {
      case "section_name":
        break;

      case "Fax":
        if (data[item]) {
          s += data[item] + " <em>fax</em><br />";
        }
        break;

      case "City":
      case "State":
        if (data[item]) {
          s += data[item] + " ";
        }
        break;
        
      case "NonProfit":
        s += "This is " +
          ((data[item] == 0) ? "not " : "") +
          "a 501(c)(3) organization.";
        break;

      case "VisualArt":
      case "Performance":
      case "School":
      case "Offerings":
      case "InstructChild":
      case "InstructAdult":
      case "ExhibitTypes":
      case "OrgType":
        if (data[item]) {
          count = data[item].length;

          for (i = 0; i < data[item].length; i++) {
            s += data[item][i] + ((--count) ? "<br />" : "");
          }
        }
        else {
          switch (item) {
            case "VisualArt":
              s += "Add visual-art items";
              break;

            case "Performance":
              s += "Add performance items";
              break;

            case "School":
              s += "Add school-program items";
              break;

            case "Offerings":
              s += "Add miscellaneous offerings";
              break;

            case "InstructChild":
              s += "Add child-instruction items";
              break;

            case "InstructAdult":
              s += "Add adult-instruction items";
              break;

            case "ExhibitTypes":
              s += "Add exhibit-type items";
              break;

            case "OrgType":
              s += "Add organization-type items";
              break;
          }
        }
        break;

      default:
        if (data[item]) {
          s += data[item] + "<br />";
        }
    }
  }
  update(orgId, data);
  document.getElementById(spanId).innerHTML = s;
}

/**
 *  Verifies email format.
 *
 *  @param  {HTMLInputElement} el   text input field
 *  @type   void
 */
function verifyEmail(el)
{
  var emailf;
  var errmsg = "Something may be wrong with the email.\n" +
    "Please correct if necessary.";

  if (el.value && !isEmail(el.value)) {
    alert(errmsg);
  }
}

/**
 *  Verifies phone is correct format.
 *
 *  @param  {HTMLInputElement} el   text input field
 *  @type   void
 */
function verifyPhone(el)
{
  var phonef;
  var errmsg = "Something was wrong with the phone number.\n" +
    "Please include the area code.";

  if (el.value) {
    phonef = formatPhone(el.value);
    if (phonef == -1) {
      el.value = "";
      unsetIsChanged();
      alert(errmsg);
    }
    else {
      el.value = phonef;
    }
  }
}

/**
 *  Verifies phone is correct format.
 *
 *  @param  {HTMLInputElement} el   text input field
 *  @type void
 */
function verifyZip(el)
{
  var zipf;
  var errmsg = "Something was wrong with the zipcode.\n" +
    "Please try again.";

  if (el.value) {
    zipf = formatZip(el.value);
    if (zipf == -1) {
      el.value = "";
      unsetIsChanged();
      alert(errmsg);
    }
    else {
      el.value = zipf;
    }
  }
}

// AJAX FUNCTIONS FOR UPDATING DIRECTORY

/**
 *  Uses an xml-http request to update a field in the artist directory.
 *
 *  @param  {String} table
 *  @param  {int} id          organization table row identifier
 *  @param  {Array} values    field-value pairs
 *  @type   void
 */
function update(id, values)
{
  if (!makeXMLHttpRequest()) {
    return;
  }

  var item;
  var xhUrl = upDir + "xh_rsp/update_adir.php"; // responder on server
  var query = "id=" + encodeURIComponent(id);

  for (item in values) {
    switch (item) {
      case "section_name":
        xhRequest.elName = values[item];
        break;

      case "VisualArt":
      case "Performance":
      case "School":
      case "Offerings":
      case "InstructChild":
      case "InstructAdult":
      case "ExhibitTypes":
      case "OrgType":
        if (values[item] && values[item].length || values[item] == null) {
          query += "&values[" + encodeURIComponent(item) + "]=" +
            encodeURIComponent(values[item]);
        }
        break;

      default:
        query += "&values[" + encodeURIComponent(item) + "]=" +
          encodeURIComponent(values[item]);
    }
  }
  xhRequest.onreadystatechange = handleResponse;
  xhRequest.open('POST', xhUrl, true);
  xhRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  xhRequest.send(query);
}

/*
 *  State-change handler: waits for the 'complete' status of the request, tests
 *  the server response, and calls the content processor.
 *
 *  @global {Object XMLHttpRequest} xhRequest
 *  @type   void
 */
function handleResponse()
{
  if (xhRequest.readyState == 4) {
    if (xhRequest.status == 200) {
      updateContent(xhRequest.elName);
    }
    else {
      alert('Error: the xml-http request failed.');
    }
  }
}

/**
 *  Content processor: hides the form, shows the div and updates its text.
 *
 *  @param {String} name
 */
function updateContent(name)
{
  var xmlRsp = xhRequest.responseXML;
  var rsp = xmlRsp.getElementsByTagName("rsp").item(0).firstChild.data;

  if (parseInt(rsp) == 0) {
    alert("database update failed");
  }
  else {
    alert(rsp);
    toggleDisplay(name);
  }
}
