/***************************************************************************
 *   Copyright (C) 2008, Paul Lutus                                        *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

if (typeof document.attachEvent!='undefined') {
  window.attachEvent('onload',sieve_setup);
}
else {
  window.addEventListener('load',sieve_setup,false);
}

var rows = 10;
var columns = 10;
var top = rows * columns;
var table = null;
var cell_array;
var sieve_array;
var timer = null;
var sieve_interval_milliseconds = 15;

function max(a,b) {
  return (a < b)?b:a;
}

// just once!

function sieve_setup() {
  clearTimeout(timer);
  cell_array = new Array();
  sieve_array = new Array();
  rows = document.getElementById("sieve_h").value;
  columns = document.getElementById("sieve_w").value;
  rows = max(rows,1);
  columns = max(columns,1);
  document.getElementById("sieve_h").value = rows;
  document.getElementById("sieve_w").value = columns;
  top = rows * columns;
  var sieve_div = document.getElementById("sieve_wrapper");
  if(table != null) {
    sieve_div.removeChild(table);
  }
  table =  document.createElement("table");
  sieve_div.appendChild(table);
  var tbody =  document.createElement("tbody");
  table.appendChild(tbody);
  for(i = 0;i < rows;i++) {
    var row =  document.createElement("tr");
    tbody.appendChild(row);
    for(j = 0;j < columns;j++) {
      var cell =  document.createElement("td");
      cell.className = "sieve_cell";
      row.appendChild(cell);
      tn = document.createTextNode("" + ((i*columns)+j+1));
      cell.appendChild(tn);
      cell_array.push(cell);
      sieve_array.push(true);
    }
  }
  sieve_array[0] = false;
  update_sieve_display(-1,true);
}

function update_sieve_display(n,initial) {
  for(i = 0;i < top;i++) {
    cell = cell_array[i];
    state = sieve_array[i];
    if((i+1) == n) {
      cell.style.backgroundColor = "#8080ff";
    }
    else {
      if(state) {
        cell.style.backgroundColor = "#c0ffc0"
        cell.style.color = "black";
      }
      else {
        cell.style.backgroundColor = "#ffffe0";
        cell.style.color = "#e0e0e0";
      }
    }
  }
}

// This routine is required to compute and display at once
// using a callback arrangement, therefore it is
// best implemented as a state machine

function animate_sieve_display(state,i,n) {
  pause = sieve_interval_milliseconds;
  switch(state) {
    case 0: // set up initial value
      n = 2;
    state++;
    break;
    case 1: // show n, set up index i
      i = n+n;
    state++;
    break;
    case 2: // clear multiples of n
    if(i <= top) {
        sieve_array[i-1] = false;
      i += n;
    }
    else {
      state++;
    }
    break;
    case 3: // scan for next valid n
      n++;
    if(n*n >= top || sieve_array[n-1]) {
      state++;
    }
    else {
      pause *= 20;
    }
    break;
    case 4: // pause at last valid number
    if(n*n >= top) {
      state++;
      pause *= 20;
    }
    else {
      state = 1;
    }
    break;
    case 5: // exit state clears the test position
      update_sieve_display(-1,false);
    return; // exit this routine
    break;
  }
  update_sieve_display(n,false);
  timer = setTimeout("animate_sieve_display(" + state + "," + i + "," + n + ")",pause);
}

function sieve_perform() {
  sieve_setup();
  animate_sieve_display(0);
}
