var names, scores, winners, draws, maxes, raw, wiki, warnings;
var currentRoundEdit = -1;

function resetGlobals(){
  names = [ '', '' ];
  scores = [0,0,0];
  winners = [0,0];
  draws = [0,0];
  maxes = [0,0,0];
  raw = [0,0];
  wiki = '';
  warnings = [];
}


//////////////////////// AJAXY STUFF /////////////////////////////////


function getXmlHttpObject( ){ 
	if( window.XMLHttpRequest ){
		return new XMLHttpRequest();
	}else if( window.ActiveXObject ){
		return new ActiveXObject("Microsoft.XMLHTTP");
	}else{
		return null;
	}
}

function sendToServer( text ){
	var http = getXmlHttpObject();
	if( !http ){ return; }	//silent fail, don't want to annoy the user
	
	var url = "wikicapsubmit.php";
	var params = '';
	for( key in text ){
		if( params !== '' ){ params += '&'; }
		params += key + "=" + encodeURIComponent( text[key] );
	}
	http.open("POST", url, true);
	
	//Send the proper header information along with the request
	http.setRequestHeader( "Content-type", "application/x-www-form-urlencoded" );
	http.setRequestHeader( "Content-length", params.length );
	http.setRequestHeader( "Connection", "close" );
	
	//alert( 'sending' );
	//http.onreadystatechange = function() {//Call a function when the state changes.
	//	alert( http.status );
	//	if( http.status == 200 ) {
	//		document.title = "done.";
	//		alert( http.responseText );
	//	}
	//};
	http.send( params );
}

function getMaximums( r ){
	
	var http = getXmlHttpObject();
	if( !http ){
		setValue( 'ot'+r, 'CountMax could not connect.' );
	}
	
	var fieldName = 'selection'+r;
	var letters = getValue( fieldName );
	var freqs = getFreqs( letters );
	
	var url = "wordsearch.php";
	var params = '';
	for( var i = 0; i < freqs.length; ++i ){
		if( freqs[i] > 0 ){
			if( params !== '' ){ params += '&'; }
			params += String.fromCharCode(i+65) + "=" + encodeURIComponent( freqs[i] );
		}
	}
	
	if( getValue( 'series' ) >= 1 && getValue( 'series' ) <= 50 ){
		params += '&dic=5';
	}else{
		params += '&dic=7';
	}
	
	//alert( params );
	//setValue( 'c2'+r, params );
	
	http.onreadystatechange = function() {//Call a function when the state changes.	
		try{
			if( http.status == 200 ){
				
				var words = http.responseText.split( ';' );
				var prunedWords = [];
				
				var badWords = getOTs( getValue( 'dc'+r ) );
				badWords.push( getContestantWord( r, 1 ) );
				badWords.push( getContestantWord( r, 2 ) );
				
				//alert( "BAD: " + badWords.join( ' ' ) );
				
				for( var i = 0; i < words.length; ++i ){
					var word = words[i];
					if( !contains( badWords, word ) ){
						prunedWords.push( word );
					}					
				}
				
				setValue( 'ot'+r, prunedWords.join( ' ' ) );	
				previewUpTo( r );
	
				document.getElementById('info'+r).value = 'Done.';
			}
		}catch( err ){
			//ignore
		}
	};
	http.open("GET", url+'?'+params, true);
	http.send( null );
}

function contains( l, e ){
	for( var i = 0; i < l.length; ++i ){
		if( l[i] === e ){
			return true;
		}
	}
	return false;
}

/////////////////////// BUSINESS LOGIC ///////////////////////////////

function getSeries(){ return document.getElementById('series').value; }

function setCurrentRoundEdit( v ){
	if( v != currentRoundEdit ){
		if( currentRoundEdit != -1 ){
			previewUpTo( currentRoundEdit );
		}
		currentRoundEdit = v;
	}
}

function getNumberOfRounds(){
  var r = 1; 
  while( document.getElementById('type'+r) ){
  	++r;
  }
  return r-1;  
}


function recapError( theMsg, theRnum ){
	warnings.push( { msg: theMsg, rnum: theRnum, warning: 0 } );
}

function recapWarning( theMsg, theRnum ){
	warnings.push( { msg: theMsg, rnum: theRnum, warning: 1 } );
}

function recapAll(){
  resetGlobals();
  var recap = getOverviewPreview();
  for( var r = 1; document.getElementById('type'+r); ++r ){
    var rtype = getValue( 'type'+r );
    if( rtype === 'T' ){
      recap += 'TTT: ' + getRoundSummary( r ) + '<br />';
    }else{
      recap += 'R' + getDoubleDigit(getValue('displaynum'+r)) + ': ' + getRoundSummary( r ) + '<br />';
    }
  }
  recap += '<br /> <br />And now a brief interlude before our main feature:<br /><br />';
  for( var spoilerspace = 0; spoilerspace < 20; ++spoilerspace ){
    recap += 'SPOILER SPOILER SPOILER SPOILER SPOILER SPOILER<br />';
  }
  recap += '<br />Enjoy the show.<br /><br />';

  for( r = 1; document.getElementById('type'+r); ++r ){
    recap += getRoundPreview( r ) + '<br />';
  }

  //recap += getStats();
  var series = getSeries();
  recap += '<br />Further summaries are at:<br />http://www.apterous.org/cdb/series.php?series=' + series;

  var asp = '<a target="_blank" href="recapsubmit.php?d=' +
    document.getElementById('recapdateday').value + 
    '&m=' + document.getElementById('recapdatemonth').value +
    '&y=' + document.getElementById('recapdateyear').value +
    '&s=' + series +
    '&c1=' + document.getElementById('champion').value +
    '&c2=' + document.getElementById('challenger').value +
    '&s1=' + scores[0] +
    '&s2=' + scores[1] +
    '&max=' + scores[2] + '"><strong>Important: Add to CDB database</strong></a> (opens a new window).';
  document.getElementById('autosubmit').innerHTML = asp;

  return recap;
}

function getWikiArticle(){	//You MUST call recapAll before calling this, or the state won't be set. Yes, this is bad.
		
	var series = getSeries();
	var championName = names[0];
	var challengerName = names[1];
	var winnerId = scores[0] > scores[1] ? 0 : 1;
	var lex = getValue('lexico');
	var guest = getValue('guest');
	
	wikitext = "{{episode|previous=Episode ?|next=Episode ?}}\r\n'''Episode ?''' was broadcast on " + 
		getValue('recapdateday') + ' ' + getMonthName( getValue('recapdatemonth') ) + ' ' + getValue('recapdateyear') +
		' as part of [[Series ' + series + ']].\r\n\r\n' +
		'[[' + championName + ']] played [[' + challengerName + ']], with ' +
		( scores[0]>scores[1] ? championName : challengerName ) +
		' winning ' + scores[ winnerId ] + " - " + scores[1-winnerId] +
		'. The [[Dictionary Corner]] guest was [[' + guest + ']], and the [[lexicographer]] was [[' + lex + ']].' +	
		"\r\n\r\n==Rounds==\r\n{{Rounds-start|" +
		championName + "|" + challengerName + "}}\r\n" + wiki +
		"{{Rounds-end}}\r\n\r\n{{DEFAULTSORT:?}}\r\n" + 
		"[[Category:15-round games]]\r\n" +
		"[[Category:Episodes in Series " + series + "]]\r\n" +
		"[[Category:Episodes presented by " + getPresenterName() + "]]\r\n" +
		"[[Category:Episodes with " + getArithmoName() + " as arithmetician]]\r\n" +
		"[[Category:Episodes with " + lex + " as lexicographer]]\r\n" +
		"[[Category:Episodes with " + guest + " as a guest]]";	
	
	return wikitext;
}

var stageNames = [ "P", "QF", "SF", "GF", "CoC", "CoCQF", "CoCSF", "CoCGF" ];

function getStageName(){
	var stageId = getValue( 'stage' );
	try{
		return stageNames[ stageId ];
	}catch( e ){ //ArrayIndexOutOfBoundsException 
		return "?";
	}
}

function getEpisodeTableEntry(){
	var epDate = padLeft( getValue( 'recapdateday' ), '0', 2 ) + "/" + padLeft( getValue( 'recapdatemonth' ), '0', 2 ) + "/" + getValue( 'recapdateyear' );
	
	return "{{ep | ? | " + epDate + " | " + getStageName() + " | " + names[0] + " | " + scores[0] + " - " + scores[1] + " | [[" + names[1] + "]] | [[" + getValue('guest') + "]] | [[" + getValue('lexico') + "]] }}";
}


function makeWikiArticle(){
	recapAll(); //for side-effects (i.e. globals)	

	document.getElementById('wiki').innerHTML = "<pre>" + getWikiArticle() + "</pre>";
	return false;
}

function makeRecap(){
	document.getElementById('fullrecap').innerHTML = recapAll();

	var sync = [];
	sync.text = getWikiArticle();
	sync.epentry = getEpisodeTableEntry();
	sendToServer( sync );

	return false;	
}

function getDoubleDigit( n ){
  if( n < 10 ){
    return '0' + parseInt( n, 10 );
  }else{
    return n;
  }
}
//************************************GENERAL FUNCTIONS***********************************

function padLeft( string, padder, width ){
	string += '';	
	
	while( string.length < width ){
		string = padder + string;
	}
	return string;
}

function padRight( s, padder, width ){
	s += '';	
		
	while( s.length < width ){
		s += padder;
	}
	
	return s;
}

function getOrdinal( n ){
  if( (n%100) >= 4 && (n%100) <= 20 ){
    return n + 'th';
  }

  switch( n % 10 ){
    case 1: return n + 'st';
    case 2: return n + 'nd';
    case 3: return n + 'rd';
    default: return n + 'th';
  }
}

function getMonthName( m ){
  switch( m ){
    case '1': return 'January';
    case '2': return 'February';
    case '3': return 'March';
    case '4': return 'April';
    case '5': return 'May';
    case '6': return 'June';
    case '7': return 'July';
    case '8': return 'August';
    case '9': return 'September';
    case '10': return 'October';
    case '11': return 'November';
    case '12': return 'December';
    default: return 'Unknown month \'' + m + '\'';
  }
}

function getDayOfWeek( d, m, y ){
  d = Math.floor(d);
  m = Math.floor(m);
  y = Math.floor(y);

  if( m < 3 ){
    d += y;
    y--;
  }else{
    d += y - 2;
  }
  //return '[' + d + ':' + m + ':' + y + ']';
  var dow =  Math.floor(23*m/9) + d + 4 + Math.floor(y/4) - Math.floor(y/100) + Math.floor(y/400); 

  switch( dow % 7 ){
    case 1: return 'Monday';
    case 2: return 'Tuesday';
    case 3: return 'Wednesday';
    case 4: return 'Thursday';
    case 5: return 'Friday';
    case 6: return 'Saturday';
    case 0: return 'Sunday';
    default: return 'Unknown day';
  }
}

//******************************PREVIEW FUNCTIONS******************************

function getValue( id ){
  var el = document.getElementById( id );
  if( el === null ){
    throw "No such element " + id;
  }
  return el.value;
}

function setValue( id, value ){
	document.getElementById( id ).value = value;
}

function setInfo( r, val ){
  document.getElementById( 'info'+r ).innerHTML = val;
}

function checkForErrors(){
  previewUpTo( getNumberOfRounds() );
  setMakerButtonsEnabled( true );
}

function setMakerButtonsEnabled( enabled ){
	document.getElementById('textrecapbutton').disabled = !enabled;
	document.getElementById('wikirecapbutton').disabled = !enabled;
}

function previewUpTo( maxround ){
  resetGlobals();
  previewOverview();
  for( var r = 1; r <= maxround; ++r ){
    previewRound( r );
  }
  
  var warningDesc = '';
  var warningCount = 0;
  var errorCount = 0;
  for( var i in warnings ){
    warningDesc += '<li>';
  	if( warnings[i].warning == 1 ){
	  	warningDesc += '<strong>Warning:</strong> ';
	  	++warningCount;
	}else{
	  	warningDesc += '<strong>Error:</strong> ';
	  	++errorCount;
	}
  	warningDesc += warnings[i].msg + ' <a href=\"#anchor' + warnings[i].rnum + '\">[Go to.]</a></li>\n';
  }
 
  if( warningDesc === '' ){
	warningDesc = 'You have no errors or warnings, congratulations!';
  }else{
  	warningDesc = '<p>Errors: ' + errorCount + '. You should resolve all errors before continuing.</p> <p>Warnings: ' + warningCount + '. Warnings may be safe to ignore. Use your own judgment.</p> <ul>' + warningDesc + '</ul>';
  }
  
  document.getElementById('warningdiv').innerHTML = warningDesc;
  
  //blank out all the later rounds to prevent confusion
  for( ; document.getElementById('previewr'+r); ++r ){
		document.getElementById('previewr'+r).innerHTML = '';
  }
}

function previewOverview(){
  document.getElementById('overviewpreview').innerHTML = getOverviewPreview();
}

function previewRound( roundnum ){
  document.getElementById('previewr' + roundnum).innerHTML = getRoundPreview( roundnum );
}

//******************************OVERVIEW FUNCTIONS****************************************

function getOverviewPreview(){
  //Read variables from document
  var recapday = document.getElementById('recapdateday').value;
  var recapmonth = document.getElementById('recapdatemonth').value;
  var recapyear = document.getElementById('recapdateyear').value;
  var stage = document.getElementById('stage').value;
  names = [ document.getElementById('champion').value, document.getElementById('challenger').value ];
  var wins = [ document.getElementById('c1wins').value, document.getElementById('c2wins').value ];
  var points = [ document.getElementById('c1points').value, document.getElementById('c2points').value ];
  var lexico = document.getElementById('lexico').value;
  var guest = document.getElementById('guest').value;

  //prepare the preview

  var preview = 'Countdown recap for ' +
    getDayOfWeek( recapday, recapmonth, recapyear ) + ' ' +
    recapday + ' ' + getMonthName( recapmonth ) + ' ' + recapyear + 
    '.<br /><br />';
  
  for( var c = 0; c < 2; ++c ){
    preview += 'C' + (c+1) + ': ';
    if( wins[c] !== '' && wins[c] > 0 ){
      preview += 'Champion ' + names[c] + ' (' +wins[c]+ ' win' + (wins[c]==1?'':'s');
      if( points[c] !== '' ){
         preview += ', ' +points[c]+ ' points';
      }
      preview += '.)<br />';
    }else{
      preview += 'Challenger ' + names[c] + '.<br />';
    }
  }
  
  preview += 'DC: ' + lexico + ' and ' + guest + '.<br />' + getArithmoInitials() + ": " + getArithmoName() + '.<br />OT: Other words or solutions.<br /><br />';

  return preview;
}

//************************************STATS FUNCTIONS*************************************


function getStats( ){
  var stats = '<br />************************<br /><br />WINNER STATS<br />';

  var poses = [ scores[0] > scores[1] ? 0 : 1, scores[0] > scores[1] ? 1 : 0 ];
  //poses[0] is the winner; poses[1] is the loser.

  var numberOfRounds = getValue('scoringrounds');

  for( var c = 0; c < 2; ++c ){
    if( c === 1 ){
      stats += '<br /><br />LOSER STATS<br />';
    }

    stats += 'Rounds won           : ' + winners[poses[c]] +
       '<br />Rounds drawn         : ' + draws[poses[c]] +
       '<br />Rounds lost          : ' + ( numberOfRounds - winners[poses[c]] - draws[poses[c]] ) +
       '<br />Rounds max scored    : ' + maxes[poses[c]] +
       '<br />% of max scored      : ' + ( Math.round( 1000 * scores[poses[c]] / scores[2] ) / 10 ) +
       '%<br />Raw Score            : ' + raw[poses[c]] +
       '<br />% of max (raw score) : ' + ( Math.round( 1000 * raw[poses[c]] / scores[2] ) / 10 ) + '%';
  }

  return stats;
}

//************************************ROUND FUNCTIONS*************************************
function getRoundSummary( r ){
  switch( document.getElementById('type' + r).value ){
    case 'L':
      return spacify( document.getElementById('selection'+r).value.toUpperCase() );
    case 'N':
      var selection = document.getElementById('numbers'+r).value;
      var target = document.getElementById('target'+r).value;
      var workers = selection.split( /[^0-9]+/ );  
      var preview = '';

      for( var w = 0; w < workers.length; ){
        preview += workers[w];
        ++w;
        if( w != workers.length ){
          preview += ', ';
        }
      }
      return preview + '. Target: ' +target+ '.';
    case 'C':
      return spacify( document.getElementById('con'+r).value.toUpperCase() ) + ' (conundrum)';
    case 'T':
      var ttt = getValue( 'ttt'+r );
      var clue = getValue( 'clue'+r );
      if( clue !== '' ){
        ttt += ' - "' + clue + '"';
      }
      return ttt;
  }
}

function getRoundPreview( roundnum ){
  var preview = '';
  var rtype = getValue('type' + roundnum);
  switch( rtype ){
    case 'L': preview += getLettersRoundPreview( roundnum ); break;
    case 'N': preview += getNumbersRoundPreview( roundnum ); break;
    case 'C': preview += getConundrumRoundPreview( roundnum ); break;
    case 'T': preview += getTeatimeTeaserPreview( roundnum ); break;
    default: preview = 'ERROR.';
  }
  //alert(preview);
  if( rtype !== 'T' ){
    if( roundnum == 17 ){
	preview += "\n[b]Final Score: ";
    }else{
	preview += 'Score: ';
    }
    preview += scores[0] + "&ndash;" + scores[1] + " (max " + scores[2] + ')';
    if( roundnum == 17 ){
	preview += '[/b]';
    }
    preview += '<br />';
  }
  return preview;
}

//************************************GUI FUNCTIONS****************************************

function updateControls(){
  updateOverview();  
  for( var r = 1; document.getElementById('type'+r); ++r ){
    switch( document.getElementById('type'+r).value ){
      case 'L': updateLettersRound(r); break;
      case 'C': updateConundrum(r); break;
      case 'N': updateNumbersRound(r); break;
    }
  }
}

function resetControls(){
  return confirm('Are you sure you want to reset all the data from this recap?'); 
}

function updateOverview(){
  var stage = document.getElementById('stage').value;

  //update input boxes

    //In the prelims (stage 0), the challenger will be a new player so has no win/point tally.
  document.getElementById('c2wins').disabled = ( stage === 0 );
  document.getElementById('c2points').disabled = ( stage === 0 );
}

function updateLettersRound( r ){
	setMakerButtonsEnabled( false );
}

function updateNumbersRound( r ){
	setMakerButtonsEnabled( false );

  //load from doc
  var target = getValue('target'+r);
  var workers = getWorkers( r );
  var decs = [ document.getElementById('c1d'+r).value, document.getElementById('c2d'+r).value, document.getElementById('c3d'+r).value, document.getElementById('c4d'+r).value ];
  var mistakes = [ document.getElementById('c1mistake'+r).checked, document.getElementById('c2mistake'+r).checked, false, false ];

	for( var i = 0; i < 2; ++i ){
		if( !decs[i].match( /^\d{2,3}$/ ) ){
			decs[i]=0;
		}
	}

  //update gui
  var maxyet = 0;

  for( var c = 0; c < 2; ++c ){
    var points = getNumberPoints( target, c, decs, mistakes );
    if( points > maxyet ){
      maxyet = points;
    }
    //document.getElementById('c'+(c+1)+'m'+r).disabled = ( points === 0 );
    document.getElementById('c'+(c+1)+'mistake'+r).disabled = false; //disabling these can cause lock-out problems
    //document.getElementById('c'+(c+1)+'mistake'+r).disabled = ( points === 0 ); 
  }

  //if either contestant gets 10 points then CV doesn't get a say
  document.getElementById('c3d'+r).disabled = ( maxyet === 10 );
  document.getElementById('c3m'+r).disabled = ( maxyet === 10 );


  if( maxyet !== 10 && getValue('c3d'+r) !== '' ){
    //neither contestant got it and CV declared something.
    var cvpoints = getPointsForDistance( Math.abs( target - document.getElementById('c3d'+r).value ) );

    //OT only gets a say if CV couldn't get it either
    var allowOTs = ( cvpoints !== 10 );
    
    document.getElementById('c4d'+r).disabled = !allowOTs;
    document.getElementById('c4m'+r).disabled = !allowOTs;
    
    if( allowOTs && workers.length == 6 ){
    	var solverURL = 'http://www.crosswordtools.com/numbers-game/?targetvalue=' + target;
    	for( var i = 0; i < workers.length; ++i ){
    		solverURL += '&n' + (i+1) + '=' + workers[i];
    	}
	    document.getElementById('numinfo'+r).innerHTML = '<p><a target="_blank" href="' + solverURL + '">Get automatic solution</a> (opens in a new window.)</p>';
	}
  }else{
    //if CV doesn't get a say, we definitely don't
    document.getElementById('c4d'+r).disabled = true;
    document.getElementById('c4m'+r).disabled = true;
  }
}

function updateConundrum( r ){
	setMakerButtonsEnabled( false );
	
  //load values from doc
  var buzzes = [ document.getElementById('buzz1r'+r).value, document.getElementById('buzz2r'+r).value ];
  var buzztimes = [ document.getElementById('buzztime1r'+r).value, document.getElementById('buzztime2r'+r).value ];
  var attempts = [ document.getElementById('attempt1r'+r).value.toUpperCase(), document.getElementById('attempt2r'+r).value.toUpperCase() ];
  
  for( var b = 0; b < 2; ++b ){
    document.getElementById('buzztime' + (b+1) + 'r'+r).disabled = ( buzzes[b] === 0 );
    document.getElementById('attempt' + (b+1) + 'r'+r).disabled = ( buzzes[b] === 0 || buzzes[b] == 1 || buzzes[b] == 3 );
  }

  document.getElementById('buzz2r'+r).disabled = ( buzzes[0] === 0 || buzzes[0] == 1 || buzzes[0] == 3 );
}

function selectionChanged( r ){
	var autobutton = document.getElementById('info'+r);
	autobutton.disabled = ( getValue( 'selection'+r ).length != 9 );
}

function autosolve( r ){
	var autobutton = document.getElementById('info'+r);
	
	if( getValue( 'selection'+r ).length == 9 ){
		if( getValue( 'ot'+r ).length != 0 && !confirm( 'This will clear the other words you have currently entered. Are you sure you want to do this?' ) ){ return; }
		autobutton.value = 'Solving - please wait...';
		getMaximums( r );
	}else{
		autobutton.value = 'Selection must have 9 letters.';
	}
}

//***********************************LETTERS ROUND FUNCTIONS******************************

function isWordValid( w ){
  //this should still return true if w features non-alpha chars
  return ( w.toUpperCase() == w );
}

function getScoreForWord( w ){
  var alphas = 0;
  for( var i = 0; i < w.length; ++i ){
    var index = w.charCodeAt( i ) - 65; //65 is A in ascii    
    if( index >= 0 && index < 26 ){
      alphas++;
    }
  }

  return isWordValid( w ) ? ( alphas == 9 ? 18 : alphas ) : 0;
}

function spacify( s ){
  var spaced = '';
  for( var p = 0; p < s.length; ++p ){
    spaced += s.charAt( p ) + ' ';
  }
  return spaced;
}

function getFreqs( word ){
  var freqs = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];

  for( var i = 0; i < word.length; ++i ){
    var index = word.charCodeAt( i ) - 65; //65 is A in ascii
    if( index >= 0 && index < 26 ){
      freqs[ index ]++;
    } //ignore non-alpha characters (otherwise we get problems with punctuation)
  }

  return freqs;
}

function canBeMadeFrom( word, selection ){
  var wordFreqs = getFreqs( word );
  var selFreqs = getFreqs( selection );

  if( wordFreqs.length === 0 || selFreqs.length === 0 ){
    return false;
  }

  for( var l = 0; l < wordFreqs.length; ++l ){
    if( wordFreqs[l] > selFreqs[l] ){
      return false;
    }
  }

  return true;
}

var cwordRegExp = new RegExp( "^([^ ]*)", "" );
var cCommentRegExp = new RegExp( "^[^ ]* (.*)", "" );

function getContestantWord( r, c ){
	var raw = getValue( 'c' + c + '' + r );
	return raw.match( cwordRegExp )[ 0 ];
}

function getContestantComment( r, c ){
	var raw = getValue( 'c' + c + '' + r );
	var comment = raw.match( cCommentRegExp );
	
	if( comment === null || comment.length == 0 ){
		return '';
	}else{
		return comment[ 1 ];
	}
}

function getOTs( s ){
  var otwords = s.split( ' ' );
  var filtered = [];
  
  for( var i in otwords ){
  	var word = otwords[i];
    if( word.length > 4 && word.toUpperCase() == word ){
    	filtered.push( word );
    }
  }
  
  return filtered;
}

function getLettersRoundPreview( r ){
  //read vars from doc
  var selection = document.getElementById('selection'+r).value.toUpperCase();
  var words = [ document.getElementById('c1'+r).value, document.getElementById('c2'+r).value ];
  var ot = [ document.getElementById('dc'+r).value, document.getElementById('ot'+r).value ];
  var maxThisRound = 0;
  var scoreThisRound = [ 0, 0 ];

  var cwords = [ getContestantWord( r, 1 ), getContestantWord( r, 2 ) ];
  var comments = [ getContestantComment( r, 1 ), getContestantComment( r, 2 ) ];
  
  //alert( comments[0] );

  //prepare preview
  var preview = 'Round ' + getValue('displaynum'+r) + ': ' + spacify(selection) + '<br /><br />';

  if( selection.length != 9 ){
    recapError( 'Selection does not have 9 letters! Remember you don\'t need to enter spaces.', r );
  }

   //pass through both words first, extracting the word from any commentary
  /*for( var c = 0; c < 2; ++c ){
    var firstspace = words[c].search( ' ' );
    if( firstspace == -1 ){
      cwords[c] = words[c];
      comments[c] = '';
    }else{
      cwords[c] = words[c].substring( 0, firstspace );
      comments[c] = words[c].substring( firstspace + 1, words[c].length );
    }
  }*/
  
  wiki += "{{R-letters  |" + padRight(getValue('displaynum'+r),' ',2) +	"|" + selection;

  // now search, armed with both words, which is necessary for scoring
  for( c = 0; c < 2; ++c ){
    var cword = cwords[c];
    var scoreForThisWord = 0;

    preview += 'C' + (c+1) + ': ';
    preview += cword;
 
    if( isWordValid( cword ) ){
      if( cword.length === 0 ){
        preview += ' - ';
        wiki += '| &amp;mdash; ';
      }else{
        scoreForThisWord = getScoreForWord( cword );
        preview += ' (' + scoreForThisWord  + ') ';
        if( !canBeMadeFrom( cword, selection ) ){
        	recapError( 'C' + (c+1) + "\'s word contains letters not present in the selection.", r );
        }
  
		wiki += '|' + padRight(cword,' ',9);
      }
    }else{
	  wiki += '|' + cword + ' {{x}}';
      preview += ' ';
    }
    
    preview += comments[c] + '<br />';

    if( scoreForThisWord >= getScoreForWord( cwords[1-c] ) ){
      scores[c] += scoreForThisWord;
      scoreThisRound[c] = scoreForThisWord;
    }

    raw[c] += scoreForThisWord;

    if( scoreForThisWord > maxThisRound ){
      maxThisRound = scoreForThisWord; //max so far
    }
  }

  var wikiwords = '';

  for( var oti = 0; oti < 2; ++oti ){
    if( ot[oti] !== '' ){
      if( oti === 0 ){
        preview += 'DC: ';
      }else{
        preview += 'OT: ';
      }

      var otwords = ot[ oti ].split( ' ' );
      for( var word in otwords ){
      	  var w = otwords[word];
          if( w.length > 4 && w.toUpperCase() == w ){
		      var otWordScore = getScoreForWord( w );
		      preview += w + ' (' + otWordScore + ') ';
		      
		      if( otWordScore > maxThisRound ){
		        maxThisRound = otWordScore;
		        wikiwords = '';
		      }
		      
		      if( wikiwords !== '' ){ wikiwords += ', '; }
		      wikiwords += w;
		      if( oti == 1 ){ wikiwords += '*'; }          
		      
		      if( !canBeMadeFrom( w, selection ) ){
		    	recapError( 'DC or OT word contains letters not present in the selection.', r );
		      }
          }else{
            preview += w + ' ';
          }
      }
      
      preview += '<br />';
    }
  }

  for( c = 0; c < 2; ++c ){
    if( scoreThisRound[c] == maxThisRound ){
      maxes[c]++;
    }
    if( scoreThisRound[c] > scoreThisRound[1-c] ){
      winners[c]++;
    }else if( scoreThisRound[c] === scoreThisRound[1-c] ){
      draws[c]++;
    }
  }

  scores[ 2 ] += maxThisRound;
  
	wiki +=
		"|" + padRight( wikiwords, ' ', 20) +
		"|" + padLeft(scores[0],' ',3) +
		"|" + padRight(scores[1],' ',3) +
		"|" + padLeft(scores[2],' ',3) +
		"}}\r\n";
  
  return preview;
}


//*********************************NUMBERS ROUND FUNCTIONS********************************

function getIntFromString( n ){	//if n is an integer, returns n; otherwise returns the empty string
	return n === '' ? 0 : n;
}

function isValidWorker( w ){
	return w == parseInt( w ) && ( ( w >= 1 && w <= 10 ) || w == 25 || w == 50 || w == 75 || w == 100 );
}

function getWorkers( r ){
	var selection = document.getElementById('numbers'+r).value;
	var workers = selection.split( /[^0-9]+/ ); 
	while( workers.length > 0 && workers[ workers.length - 1 ] === '' ){
		workers.pop();
	}
	for( var i in workers ){
		if( !isValidWorker( workers[i] ) ){
			recapError( 'Numbers selection contains unexpected number ' + workers[i] + '.', r );
		}
	}
	return workers;
}

function getNumbersRoundPreview( r ){
  //load values from doc
  var selection = document.getElementById('numbers'+r).value;
  var target = document.getElementById('target'+r).value;
  var decs = [ 	document.getElementById('c1d'+r).value, 
							  document.getElementById('c2d'+r).value,
							  document.getElementById('c3d'+r).value,
							  document.getElementById('c4d'+r).value ];
  var mistakes = [ document.getElementById('c1mistake'+r).checked, document.getElementById('c2mistake'+r).checked, false, false ];
  var methods = [ document.getElementById('c1m'+r).value, document.getElementById('c2m'+r).value, document.getElementById('c3m'+r).value, document.getElementById('c4m'+r).value ];

	//if the declaration is not an integer, treat it as 0
	for( var i = 0; i < 4; ++i ){
		if( !decs[i].match( /^\d{2,3}$/ ) ){
			decs[i]=0;
		}
	}

  var maxThisRound = 0;
  var workers = getWorkers( r ); 

  var preview = 'Round ' + getValue('displaynum'+r) + ': ';

  if( target == '' || selection == '' ){
    return preview + '<br />';  
  }

  //prepare preview
  preview += workers.join( ", " ) + '. Target: ' + target + '.<br /><br />';

  if( workers.length != 6 ){
    	recapError( 'Selection should have 6 numbers (yours has ' + workers.length + '.)', r );
  }
  
  wiki += "{{R-numbers  |" + padRight(getValue('displaynum'+r),' ',2) + "| " + workers.join('|') + "| " + target;

  for( var c = 0; c < 2; ++c ){
		preview += 'C' + (c+1) + ': ';
		if( decs[c] === 0 ){
			preview += '-';
			wiki += "\r\n|&amp;mdash;";			
		}else{
			preview += decs[c] + '. ';
			wiki += "\r\n|" + decs[c];
		}
		
    var ourPoints = getNumberPoints( target, c, decs, mistakes );
    if( ourPoints !== 0 ){
			wiki += "|sol" + (c+1) + "=" + methods[c];
      preview += methods[ c ] + ' (' + ourPoints + ')';
      if( ourPoints > maxThisRound ){
        maxThisRound = ourPoints;
      }
      scores[c] += ourPoints;
    }else if( mistakes[c] ){
      preview += 'Mistake in working.';
      wiki += " {{x}}";
    }
    preview += '<br />';
  }

  for( var ot = 2; ot < 4; ++ot ){
    var lowerInitials = getArithmoInitials().toLowerCase();
        
    if( decs[ot] !== 0 ){
      if( ot == 2 ){
        preview += getArithmoInitials() + ': ' + decs[2] + '.';
        wiki += "\r\n|" + lowerInitials + "=" + decs[2];				
      }else{
				preview += 'OT: ' + decs[3] + '.';
				wiki += "\r\n|other=" + decs[3];
      }

      if( methods[ot] != '' ){
        preview += ' ' + methods[ot];
        
        if( ot == 2 ){
					wiki += "|sol" + lowerInitials + "=" + methods[2];
        }else{
					wiki += "|solother=" + methods[3];
        }
      }

      var otPoints = getPointsForDistance( Math.abs( target - decs[ot] ) );
      if( otPoints > maxThisRound ){
        maxThisRound = otPoints;
      }
      preview += ' (' + otPoints + ')<br />';
    }
  }

	scores[2] += maxThisRound;
	
	wiki += "\r\n|" + scores[0] + "|" + scores[1] + "|" + scores[2] + "}}\r\n";
  
  return preview;
}

function getArithmoInitials(){
  switch( getValue( 'arithmo' ) ){
  case '0': return 'CV';
  case '1': return 'RR';
  default: return '??';
  }
}

function getArithmoName(){
  switch( getValue( 'arithmo' ) ){
  case '0': return 'Carol Vorderman';
  case '1': return 'Rachel Riley';
  default: return '??';
  }
}

function getPresenterName(){
  switch( getValue( 'presenter' ) ){
  case '0': return 'Richard Whiteley';
  case '1': return 'Des Lynam';
  case '2': return 'Des O\'Connor';
  case '3': return 'Jeff Stelling';
  default: return '??';
  }
}

function getPointsForDistance( d ){
    if( d === 0 ){
      return 10;
    }else if( d <= 5 ){
      return 7;
    }else if( d <= 10 ){
      return 5;
    }
    return 0;
}

function getNumberPoints( target, who, decs, mistakes ){
  if( mistakes[who] ){
    return 0; //we made a mistake and score nothing
  }

  var ourdist = Math.abs(target-decs[who]);
  if( mistakes[1-who] || ourdist <= Math.abs(target-decs[1-who]) ){
    //they made a mistake, or our solution was at least as close
    return getPointsForDistance( ourdist ); 
    //if more than 10 away then this returns 0 anyway
  }
  return 0;
}

//**************************************CONUNDRUM FUNCTIONS********************************

function getConundrumRoundPreview( r ){
  //load values from doc
  var conundrum = document.getElementById('con'+r).value.toUpperCase();
  var answer = document.getElementById('answer'+r).value.toUpperCase();
  var buzzes = [ document.getElementById('buzz1r'+r).value, document.getElementById('buzz2r'+r).value ];
  var buzztimes = [ document.getElementById('buzztime1r'+r).value, document.getElementById('buzztime2r'+r).value ];
  var attempts = [ document.getElementById('attempt1r'+r).value.toUpperCase(), document.getElementById('attempt2r'+r).value.toUpperCase() ];

  //prepare preview
  var preview = 'Round ' +getValue('displaynum'+r)+ ': ' + spacify( conundrum ) + '<br /><br />';
	wiki += "{{R-conundrum|" + getValue('displaynum'+r) + "|" + conundrum + "|";

  if( conundrum.length !== 9 || answer.length !== 9 ){
  	recapError( 'Conundrum or answer does not have 9 characters. Remember you don\'t need to enter spaces.', r );
  }
  if( !canBeMadeFrom( conundrum, answer ) || !canBeMadeFrom( answer, conundrum ) ){
    recapError( 'Conundrum and answer do not contain the same letters.', r );
  }

  if( buzzes[0] == 0 ){
    preview += 'No one buzzes. The answer was ' + answer + '.<br />';
    wiki += "sol=" + answer + "|";
  }else{
    var solved = false;
    var lastbuzzer;
    for( var b = 0; b < 2 && !solved; ++b ){
      if( buzzes[b] == 0 ){
        preview += 'C' + (2-lastbuzzer) + ' does not buzz.<br />';
      }else{
        lastbuzzer = ( buzzes[b] == 1 || buzzes[b] == 2 ) ? 0 : 1;
        solved = ( buzzes[b] == 1 || buzzes[b] == 3 );

        preview += 'C' +(lastbuzzer+1)+ ' buzzes ';
        if( buzztimes[b] != '' ){
          preview += 'on ' +buzztimes[b]+ ' second';
          if( buzztimes[b] != 1 ){
            preview += 's';
          }
        }
        preview += ' to say ';
        
        wiki += "c" + (lastbuzzer+1) + "time=" + buzztimes[b] + "|c" + (lastbuzzer+1) + "sol=";
        if( solved ){
          preview += answer + ' which is correct.<br />';
          scores[ lastbuzzer ] += 10;
          wiki += answer + "|";
        }else{
          preview += attempts[b] + ' which is incorrect.<br />';
          wiki += attempts[b].toLowerCase() + " {{x}}|";
        }
      }
    }
    if( !solved ){
      preview += 'The answer was ' + answer + '.<br />';
      wiki += "sol=" + answer + "|";
    }
  }

  scores[2] += 10;
  wiki += scores[0] + "|" + scores[1] + "|" + scores[2] + "}}\r\n";

  return preview;
}

//******************************TEATIME TEASER FUNCTIONS**********************************

function getTeatimeTeaserPreview( r ){
  var ttt = getValue( 'ttt'+r );
  var answer = getValue('answer'+r);
  var clue = getValue('clue'+r);

  var preview = 'Teatime teaser: ' + ttt + ' -> ' + answer + '<br />';

  if( !canBeMadeFrom( ttt, answer ) || !canBeMadeFrom( answer, ttt ) ){
    recapError( 'Teatime teaser shuffle and answer do not contain the same letters.', r );
  }
  
  if( ttt !== '' || answer !== '' ){
		wiki += "{{R-TTT         |" + ttt + "|" + clue + "|" + answer + "}}\r\n";
	}

  return preview;
}
