/* -*- java -*-
 *
 * (C) 2007 Alan Donovan.
 *
 * Author: Alan Donovan <adonovan@csail.mit.edu>
 *
 * generate.py -- script to generate Javascript/PHP source code for
 * spreadsheet.
 *
 * Assumes QUESTIONS, DERIVED_CELLS, NUM_SECTIONS are defined in the calling
 * environment.
 */

// Maps cell name -> validated value.  (Note: in Javascript, x[8] and x['8']
// are equivalent, so question-numbers are valid cell names.)
var VALUES = new Array();


// Called when document is first loaded.
function onLoad() {
    showOnlySection(0); // = show nothing.

    var form = document.getElementById('theform');

    for (var question_no in QUESTIONS) {
	// Initialise any cells not defined in the database:
	if (VALUES[question_no] == undefined) {
	    VALUES[question_no] = QUESTIONS[question_no][0]; // (min)
	}
	setFormElement(form, question_no);
    }

    recalculate(form);
}

// Validate a numeric text-entry field and return the valid value.
function validateNumber(input, min, max) {
    var value = parseFloat(input.value); // eg 3 lightbulbs
    if (isNaN(value)) {
	alert('Please type a number.');
	input.value = value = min;
    } else if (value < min || value > max) {
	alert("Value " + value + " is not in range: " + min + "-" + max + ".");
	if (value < min) input.value = value = min;
	if (value > max) input.value = value = max;
    }
    return value;
}

// Returns the value of the specified cell.  Called via eval("formula").
function cell(cellname) {
    if (VALUES[cellname] == undefined) {
	alert('Reference to undefined cell: ' + cellname);
	return 0;
    }
    return VALUES[cellname];
}

// Updates the form UI element named "cellname" to reflect its current value.
function setFormElement(form, cellname) {
    var elem = form.elements["cell-" + cellname];
    if (elem) {
	if (elem.type == 'checkbox') {
	    elem.checked = cell(cellname) != 0;
	} else {
	    // For now, round all decimals to integers.  (If we need it, allow
	    // each dervied cell to specify its own printf format.)
	    elem.value = parseInt(cell(cellname));
	}
    }
}

// Recalculates all derived cells in the spreadsheet.
function recalculate(form) {
    for (var derived_cell in DERIVED_CELLS) {
	VALUES[derived_cell] = eval(DERIVED_CELLS[derived_cell]);
	setFormElement(form, derived_cell);
    }
}

// Called when a numeric-entry cell loses focus after change.  "input" is the
// cell.
function updateNumber(input) {
    var question_no = input.name.substring(5); // remove "cell-" prefix
    var min = QUESTIONS[question_no][0];
    var max = QUESTIONS[question_no][1];
    VALUES[question_no] = validateNumber(input, min, max);
    recalculate(input.form);
}

// Called when a checkbox is toggled.  "input" is the checkbox.
function updateCheckbox(input) {
    var question_no = input.name.substring(5); // remove "cell-" prefix
    VALUES[question_no] = input.checked ? 1 : 0;
    recalculate(input.form);
}

// Called when a <select> dropdown is changed.
function updateSelector(input) {
    updateNumber(input);
}

// Copies the value of <select> element 'input' to the specified question cell
// and updates the corresponding form element.
function copySelectedValueTo(input, question_no) {
    VALUES[question_no] = input.value;
    setFormElement(input.form, question_no);
    recalculate(input.form);
}

// Note: called before onLoad!
function initializeCell(question_no, value) {
    VALUES[question_no] = value;
}

var currentSection = 0; // meaning "no section"

// Yeah, this is less than ideal, but then so are Microsoft's products.
var IS_MSIE = navigator.userAgent && navigator.userAgent.indexOf("MSIE") > -1;

// Hide all <tr> elements whose class is not equal to "section<n>".
function showOnlySection(n) {
    pressButton(currentSection, false); // deselect previous

    currentSection = n;

    pressButton(currentSection, true);

    urchinTracker('/' + escape(SECTION_TITLES[n])); // Google Analytics

    var spreadsheet = document.getElementById("spreadsheet");
    var intro = document.getElementById("intro");

    // Browser issues: IE7 doesn't support display: 'table' or 'table-row'.
    // However, it does allow the empty string to be assigned from JavaScript,
    // causing the default display attribute from the stylesheet to apply.
    // (However, this does mean we can't assign display:none in the
    // stylesheet.)

    if (currentSection == 0) { // hide everything
  	spreadsheet.style.display = 'none';
  	intro.style.display = 'block';

                  grand_total.style.visibility="hidden"; 
	  grand_total.style.display="none";

           for (i=1; i<11; i++){

	  if (document.all) {
                  cap = eval("row_section" + i + ".style"); 
                  } 

	  if (document.getElementById) {
                  cap = eval('document.getElementById("row_section' + i + '").style'); 
                  }

	  cap.visibility="hidden"; 
	  cap.display="none";
           }

  	return;
    } else {
  	spreadsheet.style.display = IS_MSIE ? '' : 'table';
  	intro.style.display = 'none';

	var table_rows = document.getElementsByTagName("tr");

	for (var i in table_rows) {
	    var row = table_rows[i];

	    if (hasClass(row, 'section' + n)) {
		row.style.display = IS_MSIE ? '' : 'table-row';
	    } else if (row.className &&
		       row.className.indexOf('section') == 0) {
		row.style.display = 'none';
	    }
	}


  var cap; 
  var ante; 
 
  for (i=1; i<11; i++){
                  grand_total.style.visibility="visible"; 
	  grand_total.style.display="";

	  if (document.all) {
                  cap = eval("row_section" + i + ".style"); 
                  } 

	  if (document.getElementById) {
                  cap = eval('document.getElementById("row_section' + i + '").style'); 
                  }

	  if ((cap.visibility == "hidden") || (cap.visibility == "hide"))  {
	      if (i==n){
		  cap.visibility="visible"; 
		  cap.display="";
		  }else { 
		  cap.visibility="hidden"; 
		  cap.display="none";
		  }
	  } else { 
  	      if (i==n ){
		  cap.visibility="visible"; 
		  cap.display="";		  
		  }else{
		  cap.visibility="hidden"; 
		  cap.display="none";
		  }
	  }
}

    }
}

function nextSection() {
    showOnlySection(currentSection == 10 ? 1 : currentSection + 1);
    scroll(0, 0);
}

function prevSection() {
    showOnlySection(currentSection == 1 ? 10 : currentSection - 1);
    scroll(0, 0);
}

// Returns true iff 'element' has class 'className'.
function hasClass(element, className) {
    return element.className &&
	element.className.match(new RegExp("\\b" + className + "\\b"));
}

// Sets the "pressed" state of the specified button.
function pressButton(sectionNumber, pressed) {
    var button = document.getElementById('sectionButton' + sectionNumber);
    if (button) {
      button.src = 'images/button' + sectionNumber 
          + (pressed ? '-contrast' : '') + '.png';
    }
}

// Called when the mouse enters/leaves the button area.
function onSectionButtonHover(button, sectionNumber, isEnter) {
    var message_elem = document.getElementById('hovermessage');
    var message = isEnter ? SECTION_TITLES[sectionNumber] : "";
    message_elem.innerHTML = message;
    pressButton(sectionNumber, currentSection == sectionNumber || isEnter);
}

// Called when the mouse enters/leaves the bottom navbutton area.
function onBottomButtonHover(button, isEnter) {
    var id = button.id;
    button.src = 'images/' + id + (isEnter ? '-contrast' : '') + '.png';
}

// Called when one of the three bottom buttons (or the middle
// "CLICK HERE TO ADD YOUR CO2 REDUCTIONS" button) is clicked.
function onBottomButtonClick(button) {
    if (button.id == "contribution" || button.id == "contributionaddco") {
	document.getElementById('theform').submit();
    } else if (button.id == "back") {
	prevSection();
    } else if (button.id == "next") {
	nextSection();
    }
}
