function seed_is_complete() {
  if (!seed_is_complete.already) {
    document.getElementById("collection").style.display = "none";
    do_generate();
    document.getElementById("generation").style.display = "block";
    seed_is_complete.already = true;
  }
}

function addSeed(x,y) {
  with (addSeed) {
    if (bits == 0 ||
        Math.abs(x - addSeed.lastX) > 2 ||
        Math.abs(y - addSeed.lastY) > 2) {
      ++bits;   // treat each sample as having one bit of entropy
      seed = seed + x + y;
      lastX = x;
      lastY = y;
      
      var validBits = bits;
      if (validBits > goalBits) {
        validBits = goalBits;
        seed_is_complete();
      } else {
        var completed = Math.round(validBits / (goalBits / 100.0));
        if (completed > 100.0) {
          completed = 100.0;
        }
        var progressWidth = document.getElementById("progress").offsetWidth;
        var completedWidth = Math.round((progressWidth-1) * (completed / 100.0));
        document.getElementById("completed").width = completedWidth;
        document.getElementById("incomplete").width = progressWidth-completedWidth;
        document.getElementById("complete-report").innerHTML = ""+completed;
        document.getElementById("bit-count").innerHTML =
          bits + " bit" + (bits != 1 ? "s" : "");
      }
    }
  }
}

addSeed.seed = "";
addSeed.bits = 0;
addSeed.lastX = 0;
addSeed.lastY = 0;
addSeed.goalBits = 128;

function generate_password(elements) {
  var password = "";
  // sha1 generates 5 64 bit values per invocation, so we generate 5 terms per
  //  time we re-invoke sha1
  for (var i=0; i < elements; i += 5) {
    var vals = core_sha1(str2binb(addSeed.seed), addSeed.seed.length * chrsz);
    addSeed.seed = binb2str(vals);
    for (j=i; j < i+5 && j < elements ; ++j) {
      var index = vals[j - i] % words.length;
      if (index < 0) {
        index += words.length;
      }
      if (j > 0) {
        password += "-";
      }
      password += words[index];
    }
  }
  return password;
}

function get_pw_spans() {
  var spans = document.getElementsByTagName('span');
  var pw_spans = new Array();
  for (var i = 0; i < spans.length; ++i ) {
    var span = spans[i];
    if (span.className.search("pw") >= 0) {
      pw_spans.push(span);
    }
  }
  return pw_spans;
}

function do_generate() {
  var pw_spans = get_pw_spans();
  for (var i = 0; i < pw_spans.length; ++i) {
    var span = pw_spans[i];
    span.innerHTML = generate_password(get_password_length());
  }
}

function get_password_length() {
  return document.getElementById("password-length").selectedIndex + 1;
}

addLoadEvent(function() {
  var passwordSelect = document.getElementById("password-length");
  passwordSelect.options.length = 0;
  for (var i = 0; i < 7; ++i) {
    passwordSelect.options[i] = new Option( (i+1) + " word" + (i > 0 ? "s" : "") + 
      ": " + Math.floor( (Math.log(words.length) / Math.LN2) * (i+1)) + " bits", i+1);
  }
  passwordSelect.selectedIndex = 2;
});

addLoadEvent(function() {
  document.body.onmousemove = function(event) {
    if (event) {
      addSeed(event.screenX, event.screenY);
    } else if (window.event) {
      addSeed(window.event.x, window.event.y);
    } else {
      document.getElementById("error").innerHTML = "Can't find event object";
    }
  };
});
