// (c) Stephen P. Morse, 2003

var SEPARATOR = " ";
var GROUPSEPARATOR = " ";

// provide alternate entry point so that dm.js and soundex.js can be called the same way
function getSoundex(MyStr) {
  return soundex(MyStr);
}

function soundex(MyStr) {

  // replace certain text in strings with a slash
  var re = / v | v\. | vel | aka | f | f. | r | r. | false | recte | on zhe /gi;
  MyStr = MyStr.replace(re, '/');

  // append soundex of each individual word
  var result = "";
  var MyStrArray = MyStr.split(/[\s|,]+/); // use space or comma as token delimiter
  for (var i in MyStrArray) {
    if (MyStrArray[i].length > 0) { // ignore null at ends of array (due to leading or trailing space)
      if (i != 0) {
        result += GROUPSEPARATOR;
      }
      result += soundex2(MyStrArray[i]);
    }
  }
  return result;
}

function soundex2(MyStr) {
  MyStr = MyStr.toLowerCase();
  var MyStr3 = MyStr;

  dm3 = "";
  while (MyStr3.length > 0) {
    MyStr2 = "";
    LenMyStr3 = MyStr3.length;

    for (i=0; i < MyStr3.length; i++) {
      if ((MyStr3.charAt(i) >= firstLetter && MyStr3.charAt(i) <= lastLetter) || MyStr3.charAt(i) == '/') {
        if (MyStr3.charAt(i) == '/') {
          MyStr3 = MyStr3.slice(i + 1);
          break;
        } else {
          MyStr2 = MyStr2 + MyStr3.charAt(i);
        }
      } else {
        if (MyStr[i] == "(" || MyStr[i] == SEPARATOR) {
          break;
        }
      }
    }
    if (i == LenMyStr3) {
      MyStr3 = ""; // finished
    }

    MyStr = MyStr2;
    dm = "";
    var allblank = true;
    for (k=0; k<MyStr.length; k++) {
      if (MyStr.charAt[k] != ' ') {
        allblank = false;
        break;
      }
    }
    if (!allblank) {

      dim_dm2 = 1;
      dm2 = new Array(16);
      dm2[0] = "";

      first = 1;
      lastdm = new Array(16);
      lastdm[0] = "";

      while (MyStr.length > 0) {

        for (i=0; i<newrules.length; i++) { // loop through the rules
          if (MyStr.slice(0, newrules[i][0].length) == newrules[i][0]) { // match found
            //check for xnewrules branch
            xr = "!" + newrules[i][0] + "!";
            if (xnewruleslist.indexOf(xr) != -1) {
              xr = xnewruleslist.indexOf(xr) / 3;
              for (dmm = dim_dm2; dmm < 2 * dim_dm2; dmm++) {
                dm2[dmm] = dm2[dmm - dim_dm2];
                lastdm[dmm] = lastdm[dmm - dim_dm2];
              }
              dim_dm2 = 2 * dim_dm2;
            } else {
              xr = -1;
            }
   
            dm = dm + "_" + newrules[i][0];
            if (MyStr.length > newrules[i][0].length) {
              MyStr = MyStr.slice(newrules[i][0].length);
            } else {
              MyStr = "";
            }

            if (first == 1) {
              dm2[0] = newrules[i][1];
              first = 0;
              lastdm[0] = newrules[i][1];

              if (xr >= 0) {
                dm2[1] = xnewrules[xr][1];
                lastdm[1] = xnewrules[xr][1];

              }
            } else {
              dmnumber = 1;
              if (dim_dm2 > 1) {
                dmnumber = dim_dm2 / 2;
              }
              if (MyStr.length > 0 && vowels.indexOf(MyStr.charAt(0)) != -1) { // followed by a vowel
                for (ii=0; ii<dmnumber; ii++) {
                  if (newrules[i][2] != "999" && newrules[i][2] != lastdm[ii]) {
                    // vowel following, non-branching case, not a vowel and different code from previous one
                    lastdm[ii] = newrules[i][2];
                    dm2[ii] += newrules[i][2];
                  } else if (newrules[i][3] == 999) { // should this be newrules[i][2] ?
                    // vowel following, non-branching case, is a vowel, so reset previous one to blank
                    lastdm[ii] = "";
                  }
                  // else non-branching case, not a vowel and same code from previous one -- do nothing
                }

                if (dim_dm2 > 1) {
                  for (ii=dmnumber; ii<dim_dm2; ii++) {
                    if (xr >= 0 && xnewrules[xr][2] != "999" && xnewrules[xr][2] != lastdm[ii]) {
                      // vowel following, branching case, not a vowel and different code from prevous case
                      lastdm[ii] = xnewrules[xr][2];
                      dm2[ii] += xnewrules[xr][2];

                    // not in original code -- added for dm hebrew, never encountered used in dm latin
                    // occurs only when a vowel is in the branching case (e.g., the VAV in hebrew)
                    } else if (xr >= 0 && xnewrules[xr][2] == "999") {
                      // vowel following, branching case, is a vowel, so reset previous one to blank
                      lastdm[ii] = "";

                    } else {
                      if (xr < 0 && newrules[i][2] != "999" && newrules[i][2] != lastdm[ii]) {
                        // vowel following, non-branching case, not a vowel and different code from prevous case
                        lastdm[ii] = newrules[i][2];
                        dm2[ii] += newrules[i][2];
                      } else if (newrules[i][3] == 999) { // should this be newrules[i][2] ?
                        // vowel following, non-branching case, is a vowel, so reset previous one to blank
                        lastdm[ii] = "";
                      }
                    }
                  }
                }
      
              } else {
                for (ii=0; ii<dmnumber; ii++) {
                  if (newrules[i][3] != "999" && newrules[i][3] != lastdm[ii]) {
                    // non-branching case, not a vowel and different code from prevous case
                    lastdm[ii] = newrules[i][3];
                    dm2[ii] += newrules[i][3];
                  } else if (newrules[i][3] == 999) {
                    // non-branching case, is a vowel, so reset previous one to blank
                    lastdm[ii] = "";
                  }
                  // else non-branching case, not a vowel and same code from previous one -- do nothing
                }
                if (dim_dm2 > 1) {
                  for (ii=dmnumber; ii<dim_dm2; ii++) {
                    if (xr >= 0 && xnewrules[xr][3] != "999" && xnewrules[xr][3] != lastdm[ii]) {
                      // branching case, not a vowel and different code from prevous case
                      lastdm[ii] = xnewrules[xr][3];
                      dm2[ii] += xnewrules[xr][3];

                    // not in original code -- added for dm hebrew, never encountered used in dm latin
                    // occurs only when a vowel is in the branching case (e.g., the VAV in hebrew)
                    } else if (xr >= 0 && xnewrules[xr][3] == "999") {
                      // branching case, is a vowel, so reset previous one to blank
                      lastdm[ii] = "";

                    } else {
                      if (xr < 0 && newrules[i][3] != "999" && newrules[i][3] != lastdm[ii]) {
                        // non-branching case, not a vowel and different code from prevous case
                        lastdm[ii] = newrules[i][3];
                        dm2[ii] += newrules[i][3];
                      } else if (newrules[i][3] == 999) {
                        // non-branching case, is a vowel, so reset previous one to blank
                        lastdm[ii] = "";
                      }
                    }
                  }
                }
              }
            }

            break; // stop looping through rules
          } // end of match found

        } // end of looping through the rules
      } // end of while (MyStr.length) > 0)
      dm = ""
      for (ii=0; ii<dim_dm2; ii++) {
        dm2[ii] = (dm2[ii] + "000000").substr(0, 6);
        if (ii == 0 && dm.indexOf(dm2[ii]) == -1 && dm3.indexOf(dm2[ii]) == -1) {
          dm = dm2[ii];
        } else {
          if (dm.indexOf(dm2[ii]) == -1 && dm3.indexOf(dm2[ii]) == -1) {
            if (dm.length > 0) {
              dm = dm + SEPARATOR + dm2[ii];
            } else {
              dm = dm2[ii];
            }
          }
        }
      }

      if (dm3.length > 0 && dm3.indexOf(dm) == -1) {
        dm3 = dm3 + SEPARATOR + dm;
      } else {
        if (dm.length > 0) {
          dm3 = dm;
        }
      }

    }

  } // end of while

  dm = dm3;
  return dm;
}
