String.prototype.capitalize = function() {
  return( this.substring(0,1).toUpperCase() + this.substring(1) );
}

String.prototype.trim = function() {
  return( this.replace(/^\s+|\s+$/, '') );
};

String.prototype.cleanQuery = function() {
  return( this.replace(/[^a-zA-Z0-9,\r\n\-]/g, "") );
}
  
Array.prototype.removeDuplicates = function () {
  var temp = new Array();
  this.sort();
  for (i = 0; i < this.length; i++) {
    if (this[i] == this[i + 1]) continue;
    temp[temp.length] = this[i];
  }
  return temp;
} // -- http://mickweb.com/javascript/arrays/removeDuplicates.html

function _(str) {
 //$("tracer").innerHTML += str + "<br />";
}

function q(str) {
  var lines = str.split(";");
  var exts = lines.pop();
  ext_list.each( function(ext) {
    $("ext_" + ext).checked = false;
  });
  exts.split(",").each( function(ext) {
    $("ext_" + ext.substring(1)).checked = true;
  });
  $("query").value = lines.join("\n");
  keep_demo = true;
  submitted = true;
  fuse();
}

function show_notice(str) {
  $("notice").innerHTML = str;
  new Effect.Appear('notice');
  setTimeout("hide_notice()", 5000);
}

function hide_notice() {
  new Effect.Fade('notice');
}

function info(domain) {
  alert(domain + " is a good domain!");
}

function init(demo_status) {
  domains   = {};
  groups    = [];
  sizes     = [];
  cursor    = [];
  unknown   = [];
  old_list  = [];
  new_list  = [];
  max_score = 0;
  keep_demo = false;
  querying  = false;
  idle_wait = false;
  idle_time = 0;
  submitted = false;
  show_available = false;
  show_registered = false;
  show_both = false;
  ext_list  = ['com', 'net', 'name', 'biz', 'ws', 'info', 'us', 'cc', 'tv'];
  
  init_demo(demo_status);
  setTimeout("idle_out()", 1000);
  $("query").focus();
}

// entry point
function fuse() {
  
  var msg, qv;
  var ext_checked = [];
  
  if (querying == false) {
  
    _("lock search button");
    querying = true;
    $("query_submit").disabled = true;
  
    _("parse text area into 2d array");
    qv = $("query").value;
    if (qv != qv.cleanQuery()) {
      $("query").value = qv.cleanQuery();
      show_warning("Please use only letters, numbers, dashes and commas");
      done();
      return false;
    }
    if (qv.length > 1024) {
      show_warning("Query is too long!");
      done();
      return false;
    }

    ext_list.each( function(ext) {
      if ($("ext_" + ext).checked) {
        ext_checked.push("." + ext);
      }
    });
    
    if ($("query").value.trim() == "") {
      done();
      return false;
    } else if (ext_checked.length == 0) {
      show_warning("Please select at least one domain extension");
      done();
      return false;
    }    
    
    parse($("query").value + "\n" + ext_checked.join(","));
  
    _("build domain combinations");
    build(0);
  
    _("catch added or removed domains");
    new_list = new_list.removeDuplicates();
    diff();
  
    _("query unknown domains");
    if (unknown.length > 0) {
    
      msg = '<b>';
      msg += unknown.length;
      msg += '</b> domain';
      if (unknown.length != 1) msg += 's';

      $("domain_count").innerHTML = msg;
      $("warning").style.display = "none";
      $("query_loading").style.display = "inline";
      
      if (demo_open == true) {
        if (keep_demo == false) {
          toggle_demo();
        } else {
          keep_demo = false;
        }
      }
    
      _("check unknown domains");
      check(unknown);
      unknown = [];
    } else {
    
      _("done with no check");
      done();
      
      _("- - -");
    }
    
  }

}

// ajax completion callback
function continue_fuse() {

  _("add up scores");
  score();
  
  _("update score indicators");
  progress();
  
  _("sort tables");
  sort_tables();
  
  _("highlight new domains");
  highlight();

  _("done with check");
  done();

  _("- - -");
}

function parse(q) {
  var line, lines, good_lines, i, j;
  lines = q.toLowerCase().replace("\r\n", "\n").split("\n");
  groups = [];
  good_lines = [];
  for (i = 0; i < lines.length; i++) {
    line = lines[i].trim();
    if (line == "") continue;
    good_lines.push(line);
  }
  for (i = 0; i < good_lines.length; i++) {
    groups[i] = good_lines[i].split(",");
    groups[i] = groups[i].removeDuplicates();
    sizes[i] = groups[i].length;
    cursor[i] = 0;
    for (j = 0; j < sizes[i]; j++) {
      groups[i][j] = groups[i][j].trim();
      if (groups[i][j].length > 1) {
        groups[i][j] = groups[i][j].capitalize();
      }
    }
  }
  group_count = groups.length;
}

function build(d) {
  var i, bits;
  for (cursor[d] = 0; cursor[d] < sizes[d]; cursor[d]++) {
    if (d < group_count - 1) build(d + 1);
    else {
      path = [];
      domain = "";
      for (i = 0; i < group_count; i++) {
        path.push(groups[i][cursor[i]]);
        domain += groups[i][cursor[i]];
      }
      if (domain.length < 3) continue;
      bits = domain.split(".");
      if (bits.length < 2) continue;
      if (bits[0] == "") continue;
      new_list.push(domain);
      if (!domains[domain]) {
        domains[domain] = {};
      }
      domains[domain].path = path.slice(0);
    }
  }
}

function check(d) {
  _(d.join(","));
  if (d.length > 256) {
    show_warning("Too many domains! Slow it down a bit =)");
    done();
    return false;
  } else {
    new Ajax.Request('/javascripts/name.js.php?' + (new Date).getTime(), { method: 'post', postBody: 'domains=' + d.join(","), onSuccess:querySuccess, onFailure:queryFailure });
  }
}

var querySuccess = function(xhr) {
  $("query_loading").style.display = "none";
  
  var text, json_valid;
  json_valid = true;
  
  text = xhr.responseText;
  _(text);

  try {
    var json = eval('(' + text + ')');
  } catch(error) {
    json_valid = false;
  }
  
  if (json_valid == true) {
    json["available"].each( function(domain) {
      add_status(domain, "available");
    });
    json["registered"].each( function(domain) {
      add_status(domain, "registered");
    });
    show_tables();
  } else {
    done();
  }
  
  continue_fuse();
}

var queryFailure = function(xhr) {
  _("query failure");
}

function diff() {
  old_pos = 0;
  new_pos = 0;
  while(old_pos < old_list.length && new_pos < new_list.length) {
    if (old_list[old_pos] == new_list[new_pos]) {
      old_pos++;
      new_pos++;
    } else if (old_list[old_pos] < new_list[new_pos]) {
      remove_domain(old_list[old_pos]);
      old_pos++;
    } else if (new_list[new_pos] < old_list[old_pos]) {
      add_domain(new_list[new_pos]);
      new_pos++;
    }
  }
  while(old_pos < old_list.length) {
    remove_domain(old_list[old_pos]);
    old_pos++;
  }
  while(new_pos < new_list.length) {
    add_domain(new_list[new_pos]);
    new_pos++;
  }
  old_list = new_list.slice(0);
  new_list = [];
  show_tables();
}

function score() {
  var scores, total, i, j;
  max_score = 0;
  scores = [];
  
  for (i = 0; i < group_count; i++) {
    scores[i] = {};
    for (j = 0; j < groups[i].length; j++) {
      scores[i][groups[i][j]] = 0;
    }
  }
  
  for (i in domains) {
    if (domains[i].status == 2) {
      for (j = 0; j < group_count; j++) {
        scores[j][domains[i].path[j]]++;
      }
    }
  }
  
  for (i in domains) {
    total = 0;
    for (j = 0; j < group_count; j++) {
      _(domains[i].path[j]);
      _(scores[j][domains[i].path[j]]);
      if (scores[j][domains[i].path[j]]) {
        total += scores[j][domains[i].path[j]];
      }
    }
    domains[i].score = total;
    if (total > max_score) {
      max_score = total;
    }
  }

}

function remove_domain(domain) {
  delete domains[domain];
  Element.remove('row_' + domain);
}

function add_domain(domain) {
  unknown.push(domain);
}

function add_status(domain, status) {
  var tr, td, td;

  if (status == "available") {
    domains[domain].status = 1;
  } else if (status == "registered") {
    domains[domain].status = 2;
  }
  
  tr = document.createElement("tr");
  tr.id = "row_" + domain;
  tr.domain = domain;
  tr.score  = 0;
  tr.is_new = 1;
  tr.status = domains[domain].status;

  td = document.createElement("td");
  if (status == "available") {
    td.innerHTML =  '<img id="full_'  + domain + '" src="/images/fullbar.png"  height="12" width="0" style="width: 0px;" />';
  } else if (status == "registered") {
    td.innerHTML =  '<img id="full_'  + domain + '" src="/images/graybar.png"  height="12" width="0" style="width: 0px;" />';
  }
  td.innerHTML += '<img id="empty_' + domain + '" src="/images/emptybar.png" height="12" width="48" style="width: 48px;" />';
  tr.appendChild(td);
  
  td = document.createElement("td");
  //td.innerHTML = '<a href="#" onclick="info(\'' + domain + '\'); return false;">' + domain + '</a>';
  td.innerHTML = domain;
  tr.appendChild(td);

  $(status + "_body").appendChild(tr);
  
}

function progress() {
  var tbody, domain, score, full, empty;
  ["available", "registered"].each(function(status) {
    tbody = $(status + "_body");
    for (i = 0; i < tbody.rows.length; i++) {
      domain = tbody.rows[i].domain;
      score = domains[domain].score;
      tbody.rows[i].score = score;
      if (max_score > 0) {
        full = Math.round((score / max_score) * 48);
        empty = (48 - full);
        if ($("full_" + domain).style.width != full) {
          $("full_" + domain).style.width = full;
        }
        if ($("empty_" + domain).style.width != empty) {
          $("empty_" + domain).style.width = empty;
        }
      }
    }
  });
}

function highlight() {
  var tbody;
  ["available", "registered"].each(function(status) {
    tbody = $(status + "_body");
    for (i = 0; i < tbody.rows.length; i++) {
      if (tbody.rows[i].is_new == 1) {
        new Effect.Highlight(tbody.rows[i]);
        tbody.rows[i].is_new = 0;
      }
    }
  });
}

function done() {
  $("query_submit").disabled = false;
  querying = false;
  
  if (submitted == true) {
    $("query").focus();
    submitted = false;
  }
}

function catch_idle(e) {

  var key;
  key = (window.event ? e.keyCode : e.which );

  if (querying == false) {
    [188,13,38,40].each(function(code) {
      if (key == code) {
        fuse();
      } else {
      }
    });
  }

  idle_wait = true;
  idle_time = 0;
  
}

function idle_out() {
  if (idle_wait == true) {
    idle_time += 1;
    if (idle_time >= 2) {
      idle_wait = false;
      idle_time = 0;
      if (querying == false) {
        fuse();
      }
    }
  }
  setTimeout("idle_out()", 1000);
}

function sort_tables() {
  var tbody, i, j, next_row;
  ["available", "registered"].each(function(status) {
    tbody = $(status + "_body");
    for (i = 0; i < tbody.rows.length - 1; i++) {
      top_idx = 0;
      top_val = tbody.rows[i].score;
      for (j = i + 1; j < tbody.rows.length; j++) {
        new_val = tbody.rows[j].score;
        if (new_val > top_val) {
          top_idx = j;
          top_val = new_val;
        }
      }
      if (top_idx > i) {
        next_row = tbody.removeChild(tbody.rows[top_idx]);
        tbody.insertBefore(next_row, tbody.rows[i]);
      }
    }
  });
}

function show_tables() {

  var ab = $("available_body");
  if (show_available == false && ab.rows.length > 0) {
    $("available_label").style.display = "block";
    show_available = true;
  } else if (show_available == true && ab.rows.length == 0) {
    $("available_label").style.display = "none";
    show_available = false;
  }
  
  var rb = $("registered_body");
  if (show_registered == false && rb.rows.length > 0) {
    $("registered_label").style.display = "block";
    show_registered = true;
  } else if (show_registered == true && rb.rows.length == 0) {
    $("registered_label").style.display = "none";
    show_registered = false;
  }
  
  if (show_both == false && (show_available == true && show_registered == true)) {
    $("available_cell").style.paddingRight = "12px";
    $("registered_cell").style.paddingLeft = "12px";
    $("registered_cell").style.borderLeft = "1px dashed #ddd";
    show_both = true;
  } else if (show_both == true && (show_available == false || show_registered == false)) {
    $("registered_cell").style.paddingLeft = "0px";
    $("registered_cell").style.borderLeft = "none";
    show_both = false;
  }
}

function save_extension(ext, checked) {
  fuse();
  new Ajax.Request('/setcookie.php?action=extensions&ext=' + ext + '&checked=' + checked + '&' + (new Date).getTime(), { method: 'get' } );
}

function show_warning(str) {
  $("warning").innerHTML = str;
  $("query_loading").style.display = "none";
  $("warning").style.display = "inline";
  new Effect.Highlight('warning');
  setTimeout("hide_warning()", 3000);
}

function hide_warning() {
  $("warning").style.display = "none";
}
