// (C) 2009 Wesley Steiner

//include("js/bridge/contract.js"); not working yet!!!

var NOT_VULNERABLE = 1;
var VULNERABLE = 2;
var TRUMP_VALUE_OVERTRICK = new Array(20,20,30,30,30);
bridge.TEAM_NAME = new Array("WE", "THEY");

function ScoreLineData(description, amount, ordinal)
{
	function SubStr(n) { return '<font size=+2><sub>[' + ordinal + '] </sub></font>'; }
	
	function ToString(who) 
		{ 
		if (who == bridge.WE) { return  SubStr(ordinal) + ' ('+description+') ' + amount; }
		else { return amount + ' (' + description + ') ' + SubStr(ordinal); }
		}	
		
	this.description = description;
	this.amount = amount;
	this.ordinal = ordinal;
	this.ToString = ToString;
}

function OverTrickText(made, trump, doubling) 
{ 
	return '+' + made + bridge.TRUMP_TEXT[trump] + DoublingSuffix(doubling); 
}

function UnderTrickText(made, doubling) 
{
	return made.toString() + DoublingSuffix(doubling); 
}

function RubberText(n) { return n + '-rubber'; }

function UnderTrickPoints(down, doubling, vulnerability) 
{
	if (doubling == NOT_DOUBLED) return (50 * down * vulnerability);
	var t = 0;
	for (var i = 1; i <= down; i++)
	{
		if (vulnerability == VULNERABLE) { t += ((i == 1) ? 50 : 75) * doubling * 2; }
		else { t += ((i == 1) ? 50 : ((i < 4) ? 100 : 150)) * doubling; }
	}
	return t;
}

function OverTrickPoints(up, trump, doubling, vulnerability)
{
	if (doubling == NOT_DOUBLED) return up * TRUMP_VALUE_OVERTRICK[trump];
	return up * (((doubling == DOUBLED) ? 100 : 200) * vulnerability);
}

function DoublingSuffix(doubling)
{
	return (doubling == NOT_DOUBLED) ? '' : ((doubling == DOUBLED) ? '/d' : '/dd');
}
	
function BridgeScore()
{
	this.ordinal = 0;

	this.ClearTally = function()
	{
		this.above_line_data = new Array(2);
		this.above_line_data[bridge.WE] = new Array();
		this.above_line_data[bridge.THEY] = new Array();
		this.below_line_games = new Array(3);
		for (var i = 0; i < this.below_line_games.length; i++) 
			{
			this.below_line_games[i] = new Array(2);
			this.below_line_games[i][bridge.WE] = new Array();
			this.below_line_games[i][bridge.THEY] = new Array();
			}
		this.current_game = 0;
	}
		
	function Clear()
	{
		this.results = new Array();
		this.ordinal = 0;
		this.ClearTally();
	}

	this.SumLines = function(data)
	{
		var t = 0;
		for (var i in data) { t += data[i].amount; }
		return t;
	}
	
	this.AboveLineTotal = function(who) { return this.SumLines(this.above_line_data[who]); }
	
	this.GameTotal = function(who,index) 
	{
		return this.SumLines(this.below_line_games[index][who]); 
	}
		
	this.BelowLineTotal = function(who) 
	{ 
		return this.GameTotal(who, 0) + this.GameTotal(who, 1) + this.GameTotal(who, 2); 
	}
		
	this.Total = function(who) { return this.AboveLineTotal(who) + this.BelowLineTotal(who); }

	this.GamesWonBy = function(who) 
	{
		var t = 0;
		for (var i = 0; i < this.below_line_games.length; i++) if (this.GameTotal(who, i) >= 100) ++t;
		return t; 
	}

	this.Vulnerability = function(who) 
	{ 
		return (this.GamesWonBy(who) == 0) ? NOT_VULNERABLE : VULNERABLE; 
	}

	this.RubberDone = function() 
	{ 
		return (this.GamesWonBy(bridge.WE) == 2) || (this.GamesWonBy(bridge.THEY) == 2); 
	}

	this.WhoWon = function() 
	{
		return this.RubberDone() ? bridge.TEAM_NAME[(this.GamesWonBy(bridge.WE) == 2) ? bridge.WE : bridge.THEY] : "";
	}

	this.VulnerabilitySuffix = function(text, who)
	{
		var r = text;
		if (this.Vulnerability(who) == VULNERABLE) r += '/v';
		return r;
	}
	
	this.TallyResults = function()
	{
		this.ClearTally();
		for (var i = 0; i < this.results.length; ++i) 
		{
			var contract = this.results[i];
			var ordinal = i + 1;
			if (contract.made >= 0)
			{
				var above = this.above_line_data[contract.who];
				if (contract.level == 6) above.push(new ScoreLineData(this.VulnerabilitySuffix('sm-slam', contract.who), (this.Vulnerability(contract.who) == VULNERABLE) ? 750 : 500, ordinal));
				else if (contract.level == 7) above.push(new ScoreLineData(this.VulnerabilitySuffix('gr-slam', contract.who), (this.Vulnerability(contract.who) == VULNERABLE) ? 1500 : 1000, ordinal));
				if (contract.made > 0) above.push(new ScoreLineData(this.VulnerabilitySuffix(OverTrickText(contract.made, contract.trump, contract.doubling), contract.who), OverTrickPoints(contract.made, contract.trump, contract.doubling, this.Vulnerability(contract.who)), ordinal));
				var game = this.below_line_games[this.current_game][contract.who];
				game.push(new ScoreLineData(contract.Text() + DoublingSuffix(contract.doubling), contract.Value(), ordinal));
				if (this.GameTotal(contract.who, this.current_game) >= 100) 
				{ 
					++this.current_game; 
					if (this.RubberDone()) above.push(new ScoreLineData(RubberText(this.current_game), (this.current_game > 2) ? 500 : 700, ordinal));
				}
				if (contract.doubling != NOT_DOUBLED) above.push(new ScoreLineData(((contract.doubling == DOUBLED) ? 'd' : 'dd'), (contract.doubling == REDOUBLED) ? 100 : 50, ordinal));
			}
			else 
			{
				var above = this.above_line_data[Opponent(contract.who)];
				above.push(new ScoreLineData(this.VulnerabilitySuffix(UnderTrickText(contract.made, contract.doubling), contract.who), UnderTrickPoints(Math.abs(contract.made), contract.doubling, this.Vulnerability(contract.who)), ordinal));
			}
		}
	}
		
	this.Push = function(contract, made)
		{ 
		contract.made = made;
		this.results.push(contract);
		++this.ordinal;
		this.TallyResults();
		}

	this.Pop = function()
	{
		this.results.pop();
		--this.ordinal;
		this.TallyResults();
	}
	
	this.Clear = Clear;
	this.Clear();
}

var the_score = new BridgeScore();

function ContractBuilder()
	{
	this.contract = new bridge.MadeContract(bridge.WE, 1, CLUB, NOT_DOUBLED);
	
	function OnSuit(trump)
	{
		if (this.IsValid() && (trump != this.contract.trump))
		{
			this.contract.trump = trump;
		}
		else
		{
			if (this.contract.level == 7) this.contract.level = 0;
			++this.contract.level;
			this.contract.made = 0;
			this.contract.trump = trump;
		}
	}
	
	this.ToString = function()
	{ 
		return "(" + bridge.TEAM_NAME[this.contract.who] + ") " + this.contract.ToString(); 
	}

	this.OnSuit = OnSuit;
	this.Tricks = function() { return (6 + this.contract.level + this.contract.made); }
	this.UpOne = function() { if (this.Tricks() < 13) ++(this.contract.made);}
	this.DownOne = function() { if (this.Tricks() > 0) --(this.contract.made);}
	this.IsValid = function() { return (this.contract.level > 0); }
}

var the_builder = new ContractBuilder();

function OnUndo()
{
	the_score.Pop();
	UpdateCommonPage();
}
	
function OnWe()
{
	the_builder.contract.who = bridge.WE;
	UpdateContractDisplay();
}

function OnThey()
{
	the_builder.contract.who = bridge.THEY;
	UpdateContractDisplay();
}

function OnUp()
	{
	the_builder.UpOne();
	UpdateContractDisplay();
	}

function OnDown()
	{
	the_builder.DownOne();
	UpdateContractDisplay();
	}
	
function OnDoubled() 
	{ 
	the_builder.contract.doubling = Math.max(NOT_DOUBLED, ((the_builder.contract.doubling << 1) & 0x7));
	UpdateContractDisplay();
	}
	
function AboveLineHTML(score,who)
{
	var r = '';
	var above = score.above_line_data[who];
	for (var i = Math.max(2, above.length); i > 0; i--) 
	{
		if (i <= above.length) r += above[i-1].ToString(who);
		if (i > 1) r += '<br>';
	}
	return r;
}

function BelowLineHTML(score, game, who)
{
	var g = score.below_line_games[game][who];
	var r = (g.length > 0) ? "" : ('<center><font color="gray">' +'Game #' + (game + 1) + '</font></center>');
	for (var i = 0; i < g.length; i++) r += g[i].ToString(who) + "<br>"; 
	return r;
}

function TotalHTML(score, who)
{
	if (who == bridge.WE) return "(Total) " + score.Total(who);
	else return score.Total(who) + " (Total)";
}

function HandsHTML(score)
{
	var s = (score.results.length == 0) ? "(none yet)" : "";
	for (var i = 0; i < score.results.length; i++) 
	{
		s +=  "<font size=+3>[" + (i + 1) + "]</font> (" + bridge.TEAM_NAME[score.results[i].who] + ") "
		s += score.results[i].ToString() + "<br>";
	}
	if (score.RubberDone()) s += "<b>GAME OVER<br></b>";// + score.WhoWon() + " won the Rubber</b><p>Refresh the page to start a new Rubber.</p>";
	return s;
}
	
var ABOVE_LINE_ROW_INDEX = 1;
var BELOW_LINE_ROW_INDEX = 3;
var TOTALS_ROW_INDEX = 6;

function GetTable()
{
	return document.getElementById('score_pad');
}
	
function UpdateTable(score)
{
	GetTable().rows[ABOVE_LINE_ROW_INDEX].cells[bridge.WE].innerHTML = AboveLineHTML(score, bridge.WE);
	GetTable().rows[ABOVE_LINE_ROW_INDEX].cells[bridge.THEY].innerHTML = AboveLineHTML(score, bridge.THEY);
	for (var game = 0; game < 3; game++)
	{
		GetTable().rows[BELOW_LINE_ROW_INDEX + game].cells[bridge.WE].innerHTML = BelowLineHTML(score, game, bridge.WE);
		GetTable().rows[BELOW_LINE_ROW_INDEX + game].cells[bridge.THEY].innerHTML = BelowLineHTML(score, game, bridge.THEY);
	}
	GetTable().rows[TOTALS_ROW_INDEX].cells[bridge.WE].innerHTML = TotalHTML(score, bridge.WE);
	GetTable().rows[TOTALS_ROW_INDEX].cells[bridge.THEY].innerHTML = TotalHTML(score, bridge.THEY);
}
	
function UpdateContractDisplay()
{
	GetTable().rows[TOTALS_ROW_INDEX+1].cells[the_builder.contract.who].innerHTML = '<font color="red">' + the_builder.contract.ToString() + "</font>";
}

function UpdateCommonPage()
{
	document.getElementById("hands").innerHTML = HandsHTML(the_score);
	document.getElementById("who").disabled = the_score.RubberDone();
	document.getElementById("level_button").disabled = the_score.RubberDone();
	document.getElementById("trump_button").disabled = the_score.RubberDone();
	document.getElementById("doubled_button").disabled = the_score.RubberDone();
	document.getElementById("down1").disabled = the_score.RubberDone();
	document.getElementById("up1").disabled = the_score.RubberDone();
	document.getElementById("accept_button").disabled = the_score.RubberDone();
	document.getElementById("undo_last").disabled = (the_score.results.length == 0);
	UpdateTable(the_score);
}

function SetWeTheyButtonInfo(who)
{
	document.getElementById("who").value = (who == 0) ? "<" : ">";
	document.getElementById("who").title = "Select " + bridge.TEAM_NAME[who] + " for the current contract.";
}

function OnWeThey()
{
	GetTable().rows[TOTALS_ROW_INDEX+1].cells[the_builder.contract.who].innerHTML = "";
	SetWeTheyButtonInfo(the_builder.contract.who);
	the_builder.contract.who = Opponent(the_builder.contract.who);
	UpdateContractDisplay();
}

function InitializeControls(builder)
{
	SetWeTheyButtonInfo(Opponent(builder.contract.who));
}

function OnLevel()
{
	the_builder.contract.made = 0;
	++the_builder.contract.level;
	if (the_builder.contract.level == 8) the_builder.contract.level = 1;
	UpdateContractDisplay();
}
	
function OnAdd()
{
	the_score.Push(the_builder.contract.Clone(), the_builder.contract.made);
	UpdateCommonPage();
}

function InitializePage()
{
	InitializeControls(the_builder);
	UpdateContractDisplay();
	UpdateCommonPage();
}

function OnTrump()
{
	if (the_builder.contract.trump == NOTRUMP) the_builder.contract.trump = -1;
	++the_builder.contract.trump;
	UpdateContractDisplay();
}

	