// Functions for AIRData geographic selection
// January 2002 (tad)
// Requires: airdata.js (global vars, utility functions)
//           Javascript 1.1 (string.split() method)
//
// 14-nov-2003 (tad) Add CMSA geographic area type
// June 2007 (tad) Make form object references xhtml compatible
// --------------------------------------------------------

// Return the value of the selected radio button
// in group 'radioGroup'.
function whichButtonValue (radioGroup) {
  if (radioGroup) {
    for (var i=0; i<radioGroup.length; i++) {
      if (radioGroup[i].checked)
        return radioGroup[i].value
    }
  }
  return null
}

// Return the index of a radio button in group 'radioGroup'
// whose value matches 'radioVal'.
function whichButtonIndex (radioGroup,radioVal) {
    if (radioGroup) {
      for (var i=0;i<radioGroup.length; i++) {
         if (radioGroup[i].value==radioVal)
           return i
    }
  }
  return -1
}

// Open 'url' in the current browser window.
function goToLocation(url) {
  window.location.href = url;
}

// (geosel.html)
// Validate list-type geographic selection, construct a
// query string containing geographic selection codes,
// and go to (open) the appropriate reports/maps page.
function validateListSelection(theForm) {
  var url = "";  // destination URL
  var g = "";    // selected geo area type (us, re, st, co, ms, cm, zi)
  var n = 0;     // counter
  // get index number of selected geographic area type radio button
  var i = whichButton(theForm.geotype);
  if (i == -1) {
    alert("Please select a geographic area type");
    return false;
  }
  // get code of selected geographic area type
  g = theForm.geotype[i].value.toLowerCase();
  if (g == "us") {    // United States
    optval = "usa";
    opttxt = "United States";
    url = "repsus.html?us~" + escape(optval) + "~" + escape(opttxt);
  }
  else if (g == "re") {    // EPA region
    var n = getOptions(theForm.regionlist);
    if (n < 1) {
      return warnInvalid(theForm.regionlist,
        "Please select an EPA region");
    }
    else if (n > 4) {
      return warnInvalid(theForm.regionlist,
        "Please select no more than 4 EPA regions");
    }
    // Make description like "EPA Regions 9, 10 (AK AZ CA HI ID NV OR WA)"
    url = "repsre.html?re~" + escape(optval) + "~" + escape(reNameList(opttxt));
  }
  else if (g == "st") {    // state
    n = getOptions(theForm.statelist);  // how many selected
    if (n < 1) {
      return warnInvalid(theForm.statelist,
        "Please select a state");
    }
    else if (n > 10) {
      return warnInvalid(theForm.statelist,
        "Please select no more than 10 states");
    }
    url = "repsst.html?st~" + escape(optval) + "~" + escape(opttxt);
  }
  else if (g == "co") {    // county
    var n = getOptions(theForm.statelist);
    if (n < 1) {
      return warnInvalid(theForm.statelist,
        "Please select a state first");
    }
    else if (n > 10) {
      return warnInvalid(theForm.statelist,
        "Please select no more than 10 states");
    }
    else if (n == 1) {
      url = "states/" + optval.toLowerCase() + "list.html?co~" + optval + "~";
    }
    else {
      url = "/cgi-bin/broker?_service=airdata" +
        "&_program=progs.webprogs.cntylist.scl" +
        "&_debug=0&geotype=co&geocode=" + escape(optval);
    }
  }
  else if (g == "ms") {    // MSA
    var n = getOptions(theForm.msalist," ","; ");
    if (n < 1) {
      return warnInvalid(theForm.msalist,
        "Please select a Metropolitan Statistical Area");
    }
    else if (n > 10) {
      return warnInvalid(theForm.msalist,
        "Please select no more than 10 MSAs");
    }
    opttxt += ", MSA";
    if (n > 1) opttxt += "s";
    if (theForm.cntyad.checked) {
      url = "/cgi-bin/broker?_service=airdata" +
        "&_program=progs.webprogs.msacnty.scl" +
        "&_debug=2&geotype=ms&geocode=" + escape(optval);
      }
    else {
      url = "repsms.html?ms~" + escape(optval) + "~" + escape(opttxt);
    }
  }
  else if (g == "cm") {    // CMSA
    var n = getOptions(theForm.cmsalist," ","; ");
    if (n < 1) {
      return warnInvalid(theForm.cmsalist,
        "Please select a Consolidated Metropolitan Statistical Area");
    }
    else if (n > 10) {
      return warnInvalid(theForm.cmsalist,
        "Please select no more than 10 CMSAs");
    }
    opttxt += ", CMSA";
    if (n > 1) opttxt += "s";
    if (theForm.cntyad.checked) {
      url = "/cgi-bin/broker?_service=airdata" +
        "&_program=progs.webprogs.msacnty.scl" +
        "&_debug=2&geotype=cm&geocode=" + escape(optval);
      }
    else {
//      url = "repscm.html?cm~" + escape(optval) + "~" + escape(opttxt);
      return warnInvalid(theForm.cntyad,
        "This selection not available. Please check the 'Amend selection' option.");
    }
  }
  else if (g == "zi") {    // ZIP code
    if (isEmpty(theForm.zipCode.value)) {
      return warnInvalid(theForm.zipCode,
        "Please enter a ZIP code");
    }
    if ((theForm.zipCode.value.length != 5) ||
      (!isInteger(theForm.zipCode.value))) {
      return warnInvalid(theForm.zipCode,
        "ZIP code must be 5 digits");
    }
    optval = theForm.zipCode.value;
    opttxt = "ZIP Code " + optval;
    url = "repszi.html?zi~" + escape(optval) + "~" + escape(opttxt);
  }
  else {   // those famous words... "This can never happen!"
    alert("Invalid geographic area type! (" + g +")");
    return false;
  }
  goToLocation(url);
  return true;
}

// (geosel.html)
// Reformat the string containing selected region descriptions
// from "Region 9 (AZ CA HI NV), Region 10 (AK ID OR WA)"
// to "EPA Regions 9, 10 (AK AZ CA HI ID NV OR WA)" - for example.
function reNameList (rgnlist) {
  var names = "";   // region names (return value)
  var stabbrs = ""; // list of states in a region
  var rgnNm = new Array();  // region numbers
  var rgnSt = new Array();  // states in one region
  var allSt = new Array();  // states in all selected regions
  var i = 0, j = 0, k = 0, r = 0, s = 0, t=0;
  // Build list of selected regions and states in them
  while ((i = rgnlist.indexOf("Region ",k)) != -1) {
    j = i + "Region ".length;   // first char of region number
    k = rgnlist.indexOf(" ",j); // space following region number
    rgnNm[r++] = rgnlist.substring(j,k);
    j = rgnlist.indexOf("(",k) + 1; // start of state list
    if (j == -1) j = k + 1;
    k = rgnlist.indexOf(")",j);     // end of state list
    if (k == -1) k = rgnlist.length;
    stabbrs = rgnlist.substring(j,k);
    rgnSt = stabbrs.split(" ");
    for (j=0; j<rgnSt.length; j++) {
      allSt[s++] = rgnSt[j];
    }
  }
  // List region numbers followed by states:
  // "EPA Regions 9, 10 (AK AZ CA HI ID NV OR WA)"
  if (r > 0) {
    allSt.sort();
    names = "EPA Region";
    if (r > 1) names += "s";
    names += " " + rgnNm.join(", ");
    names += " (" + allSt.join(" ") + ")";
  }
  return names;
}

// (geosel.html)
// This is the onFocus event handler for state, region, and MSA
// selection lists. When you make a selection in one of these lists,
// we select (check) the corresponding type-of-geographic-area radio
// button automatically, so you don't have to do it. Also, we clear
// any selections in the lists for other geographic area types.
// Function argument 'gtype' identifies which geographic area type
// radio button to select.
//
// Optional parameter 'keeptype' is a kludge to handle the selection
// list of states. We select the radio button associated with 'gtype'
// UNLESS the currently selected button is 'keeptype'. (In other words,
// when the list of states gets focus, select the state radio button
// unless the county radio button is already checked.)
function selectGeoType(gtype,keeptype) {
	// shorthand reference to the form containing geographic selection lists
	var f = document.forms["geolist"];
  // get the button value for the geo type to select
  var g = gtype.toLowerCase();
  // get the "exception" button value (optional)
  var k = (selectGeoType.arguments.length > 1) ? keeptype.toLowerCase() : "";
  // get the button value for the geo type currently selected
  var v = whichButtonValue(f.geotype);
  // get the button index for the geo type to select
  var i = whichButtonIndex(f.geotype,g);
  if (i > -1) {  // valid button-to-select value?
    // if now-selected isn't the exception, select the button requested
    if (v != k) f.geotype[i].checked = true;
    // clear all lists not associated with the requested geo type
    if (g != "st") f.statelist.selectedIndex = -1;
    if (g != "re") f.regionlist.selectedIndex = -1;
    if (g != "ms") f.msalist.selectedIndex = 0;
    if (g != "cm") f.cmsalist.selectedIndex = 0;
    // if selected type is CMSA, set the add/drop counties option
    if (g == "cm") f.cntyad.checked = true;
  }
}

// (geosel.html)
// County selection via "Go" link in text near county radio button:
// Force the county radio button to be checked, then simulate
// clicking the form "Go" (submit) button.
function goCounty() {
	var f = document.forms["geolist"];
  var i = whichButtonIndex(f.geotype,"co");
  if (i >= 0) {
    f.geotype[i].checked = true;
    f.submit.click();
  }
  return false;
}

// (county selection list pages - states/??list.html)
// (MSA/CMSA county selection list page)
// Returns a state name based on FIPS state code.
function stateName(stfips) {
  // Define an associative array of state names and FIPS codes
  var stName = new Array();
  stName["01"] = "Alabama";
  stName["02"] = "Alaska";
  stName["04"] = "Arizona";
  stName["05"] = "Arkansas";
  stName["06"] = "California";
  stName["08"] = "Colorado";
  stName["09"] = "Connecticut";
  stName["10"] = "Delaware";
  stName["11"] = "District of Columbia";
  stName["12"] = "Florida";
  stName["13"] = "Georgia";
  stName["15"] = "Hawaii";
  stName["16"] = "Idaho";
  stName["17"] = "Illinois";
  stName["18"] = "Indiana";
  stName["19"] = "Iowa";
  stName["20"] = "Kansas";
  stName["21"] = "Kentucky";
  stName["22"] = "Louisiana";
  stName["23"] = "Maine";
  stName["24"] = "Maryland";
  stName["25"] = "Massachusetts";
  stName["26"] = "Michigan";
  stName["27"] = "Minnesota";
  stName["28"] = "Mississippi";
  stName["29"] = "Missouri";
  stName["30"] = "Montana";
  stName["31"] = "Nebraska";
  stName["32"] = "Nevada";
  stName["33"] = "New Hampshire";
  stName["34"] = "New Jersey";
  stName["35"] = "New Mexico";
  stName["36"] = "New York";
  stName["37"] = "North Carolina";
  stName["38"] = "North Dakota";
  stName["39"] = "Ohio";
  stName["40"] = "Oklahoma";
  stName["41"] = "Oregon";
  stName["42"] = "Pennsylvania";
  stName["72"] = "Puerto Rico";
  stName["44"] = "Rhode Island";
  stName["45"] = "South Carolina";
  stName["46"] = "South Dakota";
  stName["47"] = "Tennessee";
  stName["48"] = "Texas";
  stName["49"] = "Utah";
  stName["50"] = "Vermont";
  stName["78"] = "Virgin Islands";
  stName["51"] = "Virginia";
  stName["53"] = "Washington";
  stName["54"] = "West Virginia";
  stName["55"] = "Wisconsin";
  stName["56"] = "Wyoming";
  return stName[stfips];
}

// Determine which options of a selection list are selected, and
// return the count. The value and text attributes of each selected
// option are stored in arrays 'vals' and 'txts', respectively.
function getOptionsArray(list,vals,txts) {
  var n = 0;
  if (list) {  // can't do anything if the list doesn't exist
    // fix for single-choice selection lists -
    // get first/only selected option
    var j = list.selectedIndex;
    for (var i=0; i<list.length; i++) {
      if (((i == j) || (list.options[i].selected)) && (!isEmpty(list.options[i].value))) {
        vals[n] = list.options[i].value;
        txts[n] = list.options[i].text;
        n++;
      }
    }
  }
  return n;
}

// (county selection list pages - states/??list.html)
// Construct a query string containing geographic selection codes,
// and display the appropriate reports/maps page. 'theList' is an
// object reference to a selection list of county names and FIPS codes.
// 'numCharDel' is the number of characters to remove from the beginning
// of option values (county names).  This permits displaying state
// abbreviations in a county selection list, but removing them from
// the county name list (query string) that is displayed on AIRData
// selection criteria pages.
// nov 2003 - increase max number of county selections from 10 to 50.
function selectCounty(theList,numCharDel) {
  // Put codes and names of selected counties in 'optval' and 'opttxt'
  var n = getOptions(theList);
  if (n == 0) return false;    // no county selected
  if (n > 50) {
    return warnInvalid(theList,
      "Please select no more than 50 counties");
  }
  var coCode = new Array();  // FIPS county codes from 'optval'
  // **NOTE** County codes must be grouped by state for this function to work!
  var coName = new Array();  // County names from 'opttxt'
  var stCode = new Array();  // distinct FIPS state codes in 'coCode'
  var stFrst = new Array();  // index in 'coCode' where each state begins
  var coNames = "";  // massaged version of 'opttxt'
  var st = "";       // state code holder
  var i,j = 0;       // counters
  var nDel = 0;      // number of chars to remove from 'coName' values
  coCode = optval.split(" ");  // extract space-delimited county codes
  coName = opttxt.split(", "); // extract comma-delimited county names
  // The number of codes and names must be equal, and at least one of each
  if ((coCode.length != coName.length) || ((coCode.length + coName.length) < 2))
    return false;
  // Remove 'numCharDel' characters from the beginning of each
  // 'coName' value. (Strip off leading state abbreviation, used in
  // multi-state county selection list.)
  if ((!isEmpty(numCharDel)) && (isInteger(numCharDel))) {
    nDel = parseInt(numCharDel);
    nDel = Math.abs(nDel);
  }
  // Get a list of distinct state codes contained in the county codes
  stCode[0] = coCode[0].substring(0,2);
  stFrst[0] = 0;
  for (i=1; i<coCode.length; i++) {
    st = coCode[i].substring(0,2);
    if (stCode[j] != st) {   // compare this (i-th) state code with "old" code
      stCode[++j] = st;    // save "new" state code and its index
      stFrst[j] = i;
    }
  }
  stFrst[++j] = coCode.length;
  // Intersperse state name(s) in county names:
  // "Alpha, Bravo, State One; Alpha, State Two"
  for (i=0; i<stCode.length; i++) {
    if (i > 0) coNames += "; ";
    for (j=stFrst[i]; j<stFrst[i+1]; j++) {
      coNames += coName[j].substring(nDel) + ", ";
    }
    coNames += stateName(stCode[i]);
  }
  // Append geographic info to the reports/maps page URL, and go there
  var url = "repsco.html?co~" + escape(optval) + "~" + escape(coNames);
  if (location.protocol == "file:") url = "../" + url;
  else url = "/air/data/" + url;
  goToLocation(url);
  return true;
}

// (MSA/CMSA county selection list - dynamic page)
// Construct a query string containing county geographic selection
// codes, and display the appropriate reports/maps page. 'cntyin' and
// 'cntyout' are object references to two selection lists of counties
// within and around a selected MSA or CMSA.
function selectMSACounty(cntyin,cntyout) {
  var i = 0, j = 0, k = 0;
  var cntyinCodes = new Array();
  var cntyinNames = new Array();
  var cntyoutCodes = new Array();
  var cntyoutNames = new Array();
  var cntys = new Array();
  var stCode = new Array();  // distinct FIPS state codes in 'cntys'
  var stFrst = new Array();  // index in 'cntys' where each state begins
  var coCodes = "";  // codes of selected counties
  var coNames = "";  // names of selected counties
  var st = "";       // state code holder
  var cntyinNum = getOptionsArray(cntyin,cntyinCodes,cntyinNames);
  var cntyoutNum = getOptionsArray(cntyout,cntyoutCodes,cntyoutNames);
  i = cntyinNum + cntyoutNum;
  if (i < 1)
    return warnInvalid(cntyin,"Please select at least one county");
  if (i > 50)
    return warnInvalid(cntyin,"Please select no more than 50 countes." +
                       "\n(" + i + " are selected.)");
  // Combine in/out lists and remove state abbreviation from county names.
  // Some county names include "(part)" after state abbreviation, and that
  // also is removed.
  for (i=0; i<cntyinNum; i++) {
    k = cntyinNames[i].lastIndexOf(", ");
    if (k == -1) k = cntyinNames[i].length;
    cntys[i] = cntyinCodes[i] + cntyinNames[i].substring(0,k);
  }
  for (i=0; i<cntyoutNum; i++) {
    k = cntyoutNames[i].lastIndexOf(", ");
    if (k == -1) k = cntyoutNames[i].length;
    cntys[cntyinNum+i] = cntyoutCodes[i] + cntyoutNames[i].substring(0,k);
  }
  // Sort the combined array by county code
  cntys = cntys.sort();
  // Get a list of distinct state codes contained in the county codes,
  // and remove state abbreviation from county names.  Some county names
  // include "(part)" after state abbreviation, and that also is removed.
  stCode[0] = cntys[0].substring(0,2);
  stFrst[0] = 0;
  for (i=1; i<cntys.length; i++) {
    st = cntys[i].substring(0,2);
    if (stCode[j] != st) {   // compare this (i-th) state code with "old" code
      stCode[++j] = st;    // save "new" state code and its index
      stFrst[j] = i;
    }
  }
  stFrst[++j] = cntys.length;
  // Create 'geocode' and 'geoname' values from county codes
  // and names. Include state name in 'geoname' at the end of
  // each state group of counties:
  // County One, County Two, Alabama; County One, Georgia
  for (i=0; i<stCode.length; i++) {
    if (i > 0) coNames += "; ";
    for (j=stFrst[i]; j<stFrst[i+1]; j++) {
      coCodes += cntys[j].substring(0,5) + " ";
      coNames += cntys[j].substring(5,cntys[j].length) + ", ";
    }
    coNames += stateName(stCode[i]);
  }
  // Append geographic info to the reports/maps page URL, and go there.
  // Note that the type of geographic selection is changed to "county"
  // from "MSA" or "CMSA".
  var url = "repsco.html?co" +
            "~" + escape(coCodes.substring(0,coCodes.length-1)) +
            "~" + escape(coNames);
  if (location.href.indexOf("service=airdatadev") != -1) url = "/air/datad/" + url;
  else url = "/air/data/" + url;
  goToLocation(url);
  return true;
}
