/* 
	To do:
		- URL string needs &s and |s encoding & decoding...
		- When new columns are added, change font size to fit on screen?
 */

function setup() {
	// All fields within <td>s in the table body should clean up on change..
	var myCells = getBody().getElementsByTagName('td') ;
	// Loop through all cells, and find any input inside
	// Add event to any inputs found in <td>s
	var myInput ;
	for (var nCell=0; nCell<myCells.length; nCell++) {
		myInput = myCells[nCell].getElementsByTagName('input')[0] ;
		if (myInput) {
			addEvent(myInput, 'change', validateVal, false) ;
		}
	}
	
	// Add a click event to all anchors in the thead, calling removeColumn
	var myHeadLinks = document.getElementsByTagName('thead')[0].getElementsByTagName('a') ;	
	for (var nHeadLink=0; nHeadLink<myHeadLinks.length; nHeadLink++) {
		addEvent(myHeadLinks[nHeadLink], 'click', removeColumn, false) ;
	}
	
	// Add click event to anchors in rows
	var myBodyLinks = getBody().getElementsByTagName('a') ;
	for (var nBodyLink=0; nBodyLink<myBodyLinks.length; nBodyLink++) {
		addEvent(myBodyLinks[nBodyLink], 'click', removeRow, false) ;
	}
	
	// Add recalculate event to every select
	var mySelects = document.getElementsByTagName('select') ;
	for (var nSelect=0; nSelect<mySelects.length; nSelect++) {
		addEvent(mySelects[nSelect], 'change', calcTotals, false) ;
	}
	
	addEvent(document.getElementById('gridTitle'), 'change', showPermaLink, false) ;
	
	// If data is passed in, decode into table
	if (location.search) decodeInputValues() ;
		
}

function decodeInputValues() {
	var urlArgs = getArgs() ;
	for (nCol=0; nCol<urlArgs['c']; nCol++) {
		addColumn(true) ;
	}
	
	for (nRow=0; nRow<urlArgs['r']; nRow++) {
		addRow(true) ;
	}
	var mySelects = getSelects() ;
	var mySelectVals = urlArgs['w'].split('|') ;
	for (nSel=0; nSel<mySelectVals.length; nSel++) {
		mySelects[nSel].value = mySelectVals[nSel] ;
	}
	var myInputs = getInputs() ;
	var myInputVals = urlArgs['i'].split('|') ;
	for (nInp=0; nInp<myInputs.length; nInp++) {
		if (myInputs[nInp].type != 'button')
			myInputs[nInp].value = myInputVals[nInp+1] ;
	}
	showPermaLink() ;
}

function getArgs() {
    var args = new Object();
    var query = unescape(location.search.substring(1)) ;
    var pairs = query.split("&") ;
    for (var i = 0; i < pairs.length; i++) {
		var pos = pairs[i].indexOf('=') ;
		if (pos == -1) continue ;
		var argname = pairs[i].substring(0,pos) ;
		var value = pairs[i].substring(pos+1) ;
		args[argname] = unescape(value) ;
    }
    return args;                               // Return the object.
}

function getRows() {
	var tRows = getBody().getElementsByTagName('tr') ;
	return tRows ;
}

function getBody() {
	return document.getElementsByTagName('tbody')[0] ;
}

function countRows() {
	return getRows().length ;
}

function countCols() {
	return document.getElementById('items').getElementsByTagName('th').length - 2 ;
}

function getInputs() {
	return document.getElementById('gridForm').getElementsByTagName('input') ;
}

function getSelects() {
	return document.getElementById('gridForm').getElementsByTagName('select') ;
}

function calcTotals() {
	var myVals = new Object ;
	var myRows = getRows() ;
	var nRows = myRows.length ;
	var nCols = countCols() ;
	var maxScore = 0 ;
	
	// Initialise tally
	for (var colN=0; colN<nCols; colN++) {
		myVals[colN] = 0 ;
	}
	
	// Loop through rows, get weighting of current row, then add weighting * score to relevant place in myVals
	for (var rowN=0; rowN<nRows; rowN++) {
		var rowWeight = myRows[rowN].getElementsByTagName('select')[0].value ;
		maxScore += parseFloat(rowWeight) ;
		var currRow = myRows[rowN] ;
		for (var colN=0; colN<nCols; colN++) {
			myVal = parseInt(currRow.getElementsByTagName('td')[colN].getElementsByTagName('input')[0].value) ;
			if (isNaN(myVal)) myVal = 0 ;
			myVals[colN] += myVal * rowWeight ;
		}
	}
	// Put values into final row
	if (!maxScore > 0) return false ;
	var myTotals = document.getElementsByTagName('tfoot')[0].getElementsByTagName('input') ;
	for (totN=0; totN<myTotals.length; totN++) {
		myTotals[totN].value = roundNumber(myVals[totN]*100/(maxScore*10),1) + '%' ;
	}
	showPermaLink() ;
}

function permitChars(inVal) {
	var returnString = "";
	for (var i = 0; i < inVal.length; i++) {
		var c = inVal.charAt(i);
		if ('0123456789.'.indexOf(c) != -1) returnString += c;
	}
	return returnString;
}

function roundNumber(rNum,dPlaces) {
	if (rNum > 8191 && rNum < 10485) {
		rNum = rNum-5000;
		var newnumber = Math.round(rNum * Math.pow(10,dPlaces)) / Math.pow(10,dPlaces);
		newnumber = newnumber+5000;
	}
	else {
		var newnumber = Math.round(rNum*Math.pow(10,dPlaces))/Math.pow(10,dPlaces);
	}
	return newnumber ;
}

function validateVal(e) {
	var fieldObj = getTarget(e) ;
	var cleanVal = parseInt(permitChars(fieldObj.value)) ;
	if (isNaN(cleanVal)) cleanVal = 0 ;
	else if (cleanVal > 10) cleanVal = 10 ;
	fieldObj.value = cleanVal ;
	calcTotals() ;
}

function addColumn(dontFocus) {
	// Create a new <th> in the table head (penultimate place), containing an input for the option
	var myHead = document.getElementsByTagName('thead')[0] ;
	var numCols = countCols() ;
	var myRows = getRows() ;
	var numRows = myRows.length ;
	
	var newTH = document.createElement('th') ;
	var newChoice = document.createElement('input') ;
	newChoice.value = "Option" ;
	newChoice.type = 'text' ;
	newChoice.className = 'transp' ;
	addEvent(newChoice, 'change', showPermaLink, false) ;
	
	var newLink = document.createElement('a') ;
	newLink.title="Delete this option" ;
	addEvent(newLink, 'click', removeColumn, false) ;
	var newLinkText = document.createTextNode("X") ;
	newLink.appendChild(newLinkText) ;
	
	newTH.appendChild(newLink) ;
	newTH.appendChild(newChoice) ;
	myHead.getElementsByTagName('tr')[0].insertBefore(newTH, myHead.getElementsByTagName('th')[numCols+1]) ;
	
	for (nRow=0; nRow<numRows; nRow++) {
		myRows[nRow].appendChild(createCell()) ;
	}
	
	// Add a new <th> in the final foot
	var newTH2 = document.createElement('th') ;
	var newTotal = document.createElement('input') ;
	newTotal.type = 'text' ;
	newTH2.appendChild(newTotal) ;
	
	document.getElementById('footRow').appendChild(newTH2) ;
	
	if (!dontFocus)
		newChoice.focus() ;

	showFoot() ;
}

function removeColumn(e) {
	// Which column?
	var callingCell = climbDom(getTarget(e), 'th') ;
	var myTHead = document.getElementsByTagName('thead')[0] ;
	// Loop through all th's in head to find current one
	var myTHs = myTHead.getElementsByTagName('th') ;
	for (nTH=0; nTH<myTHs.length; nTH++) {
		if (myTHs[nTH] == callingCell) {
			
			// Remove the th from the thead
			myTHs[nTH].parentNode.removeChild(myTHs[nTH]) ;
			
			// Remove th from tfoot
			myFootTR = document.getElementsByTagName('tfoot')[0].getElementsByTagName('tr')[0] ;
			myFootTHs = myFootTR.getElementsByTagName('th') ;
			myFootTR.removeChild(myFootTHs[nTH]) ;
			
			// Now, loop through the rows and remove the relevant td from each row
			var myRows = getRows() ;
			for (nRow=0; nRow<myRows.length; nRow++) {
				myRowTDs = myRows[nRow].getElementsByTagName('td') ;
				myRows[nRow].removeChild(myRowTDs[nTH-1]) ;
			}
			
		}
	}
}

function addRow(dontFocus) {
	// Create new select group
	var newSelect = document.createElement('select') ;
	for (var a=0; a<=10; a++) {
		var newOption = document.createElement('option') ;
		newOption.value = a ;
		if (a==0) {
			newOption.appendChild(document.createTextNode('Weight')) ;
		}
		else {
			newOption.appendChild(document.createTextNode(a)) ;
		}
		newSelect.appendChild(newOption) ;
	}
	addEvent(newSelect, 'change', calcTotals, false) ;
	// Create new criteria name field
	var newCriteriaField = document.createElement('input') ;
	newCriteriaField.value = 'Criteria' ;
	newCriteriaField.className = 'transp' ;
	addEvent(newCriteriaField, 'change', showPermaLink, false) ;
	// Create new anchor
	var newLink = document.createElement('a') ;
	newLink.title="Delete this criterion" ;
	addEvent(newLink, 'click', removeRow, false) ;
	var newLinkText = document.createTextNode("X") ;
	newLink.appendChild(newLinkText) ;
	
	// Create new th and put other children in it
	var newTH = document.createElement('th') ;
	newTH.appendChild(newLink) ;
	newTH.appendChild(newCriteriaField) ;
	newTH.appendChild(newSelect) ;
	
	// Create new row and append new th
	var newRow = document.createElement('tr') ;
	newRow.appendChild(newTH) ;
	// Create appropriate number of tds with inputs in
	for (nNewCol=0; nNewCol<countCols(); nNewCol++) {
		newRow.appendChild(createCell()) ;
	}
	// Insert new row
	getBody().appendChild(newRow) ;	
	
	if (!dontFocus)
		newCriteriaField.focus();

	showFoot() ;
}

function removeRow(e) {
	var callingRow = climbDom(getTarget(e), 'tr') ;
	getBody().removeChild(callingRow) ;
}

function createCell() {
	var newTD = document.createElement('td') ;
	var newInput = document.createElement('input') ;
	newInput.className = 'userScore' ;
	addEvent(newInput, 'change', validateVal, false) ;
	newTD.appendChild(newInput) ;
	return newTD ;
}

function showFoot() {
	if (countCols()>0 && countRows()>0)	{
		document.getElementById('theFoot').className = '' ;
	}
}

function showPermaLink() {
	var pL = '' ;
	// Show how many columns there should be
	pL += 'c=' + countCols() ;
	// Indicate number of rows
	pL += '&r=' + countRows();
	// Get all select values
	var mySelects = getSelects() ;
	pL += '&w=' ;
	for (nSel=0; nSel<mySelects.length; nSel++) {
		if (nSel>0) pL += '|' ;
		pL += mySelects[nSel].value ;
	}
	// Get all input values
	var myInputs = getInputs() ;
	pL += '&i=' ;
	for (nInp=0; nInp<myInputs.length; nInp++) {
		if (nSel>0) pL += '|' ;
		if (myInputs[nInp].type == 'button')
			pL += '' ;
		else
			pL += myInputs[nInp].value ;
	}
	
	document.getElementById('permaLink').getElementsByTagName('a')[0].href = '?' + escape(pL) ;
	document.getElementById('permaLink').className = '' ;
}


addEvent(window, 'load', setup, false) ;
