var App = {
	start: function() {
		App.InputFrame.create();
		App.SideBar.create();
		App.CompareCostsPane.create();
		App.BreakEvenPane.create();
		App.BrochuresPane.create();
		
		App.InputFrame.submit();
	}
};

var FuncUtils = {
	isNumeric: function(value) {
		return !isNaN(value);
	},
	
	isInt: function(num) {
		return num % 1 == 0 ? true : false;
	},
	
	/*
	formatCurrency: function(value) {
		value = value.toString().replace(/\$|\,/g, "");
		value = value.toFloat();
		
		var sign = value == (value = Math.abs(value));
		
		value = Math.floor(value * 100 + 0.50000000001);
		
		var cents = value % 100;
		
		value = Math.floor(value / 100).toString();
		
		for (var i = 0; i < Math.floor((value.length - (1 + i)) / 3); i++) {
			var pos = value.length - (4 * i + 3);
			value = value.substring(0, pos) + "," + value.substring(pos);
		}
		
		return (sign ? "$" : "-$") + value + (cents < 10 ? ".0" : ".") + cents;
	}
	*/
	
	formatCurrency: function(num) {
		num = num.toFloat();
		
		var sign = num == (num = Math.abs(num));
		
		num = Math.floor(num * 100 + 0.50000000001);
		
		var cents = num % 100;
		
		num = Math.floor(num / 100).toString();
		
		for (var i = 0; i < Math.floor((num.length - (1 + i)) / 3); i++) {
			var pos = num.length - (4 * i + 3);
			num = num.substring(0, pos) + "," + num.substring(pos);
		}
		
		return (sign ? "$" : "-$") + num + (cents < 10 ? ".0" : ".") + cents;
	},
	
	suppressCurrencyFormat: function(value) {
		return value.toString().replace(/\$|\,/g, "");
	}
};

App.InputFrame = {
	data: {},
	
	_element: null,
	_focusedElement: null,
	_defaultData: {
		solutionInvestment: 25000,
		resourcePerHour: 30,
		postageOverhead: 1,
		outNumInvoices: 4000,
		inNumInvoices: 1000,
		outTimePerInvoice: 5,
		inTimePerInvoice: 5,
		outEInvoicesPercentage: 75,
		inEInvoicesPercentage: 75
	},
	
	create: function() {
		this._element = $("input-frame");
		
		$extend(this.data, this._defaultData);
		
		$ES("#inputForm p.field input", this._element).each(function(input) {
			input.onkeydown = function(evt) {
				var evt = new Event(evt);
				
				if (evt.key == "enter") {
					this.submit();
					
					evt.stop();
				}
			}.bind(this);
		}, this);
		
		$E("#inputForm p.actions a.submit", this._element).addEvent("click", this.submit.bind(this));
		$E("#inputForm p.actions a.clear", this._element).addEvent("click", this._resetInputs.bind(this));
		
		this._solutionInvestmentText = $("solutionInvestmentText");
		
		this._solutionInvestmentText.addEvents({
			"focus": function() {
				this._focusedElement = this._solutionInvestmentText;
				
				this._solutionInvestmentText.setProperty(
					"value",
					FuncUtils.suppressCurrencyFormat(this._solutionInvestmentText.getProperty("value")).toInt()
				);
			}.bind(this),
			
			"blur": function() {
				this._focusedElement = null;
				
				var value = this._solutionInvestmentText.getProperty("value");
				this._solutionInvestmentText.setProperty("value", FuncUtils.formatCurrency(
					FuncUtils.isNumeric(value) ? value.toInt().limit(500, 100000) : this._defaultData.solutionInvestment
				));
			}.bind(this)
		});
		
		this._postageOverheadText = $("postageOverheadText");
		
		this._postageOverheadText.addEvents({
			"focus": function() {
				this._focusedElement = this._postageOverheadText;
				
				this._postageOverheadText.setProperty(
					"value",
					FuncUtils.suppressCurrencyFormat(this._postageOverheadText.getProperty("value")).toFloat()
				);
			}.bind(this),
			
			"blur": function() {
				this._focusedElement = null;
				
				var value = this._postageOverheadText.getProperty("value");
				this._postageOverheadText.setProperty("value", FuncUtils.formatCurrency(
					FuncUtils.isNumeric(value) ? value.toFloat().round(2).limit(0.5, 100) : this._defaultData.postageOverhead
				));
				
			}.bind(this)
		});
		
		this._setupInputs();
	},
	
	submit: function() {
		this._validateInputs();
		
		App.CompareCostsPane.render();
		App.BreakEvenPane.render();
	},
	
	_setupInputs: function() {
		this._solutionInvestmentText.setProperty("value", (this._focusedElement == this._solutionInvestmentText || (window.ie ? document.activeElement == this._solutionInvestmentText : false)) ?
		                                                   this.data.solutionInvestment : FuncUtils.formatCurrency(this.data.solutionInvestment));
		$("resourcePerHourText").setProperty("value", this.data.resourcePerHour);
		this._postageOverheadText.setProperty("value", (this._focusedElement == this._postageOverheadText || (window.ie ? document.activeElement == this._postageOverheadText : false)) ?
		                                                this.data.postageOverhead : FuncUtils.formatCurrency(this.data.postageOverhead));
		$("outNumInvoicesText").setProperty("value", this.data.outNumInvoices);
		$("inNumInvoicesText").setProperty("value", this.data.inNumInvoices);
		$("outTimePerInvoiceText").setProperty("value", this.data.outTimePerInvoice);
		$("inTimePerInvoiceText").setProperty("value", this.data.inTimePerInvoice);
		$("outEInvoicesPercentageText").setProperty("value", this.data.outEInvoicesPercentage);
		$("inEInvoicesPercentageText").setProperty("value", this.data.inEInvoicesPercentage);
		
		return this;
	},
	
	_resetInputs: function() {
		this._solutionInvestmentText.setProperty("value", FuncUtils.formatCurrency(this._defaultData.solutionInvestment));
		$("resourcePerHourText").setProperty("value", this._defaultData.resourcePerHour);
		this._postageOverheadText.setProperty("value", FuncUtils.formatCurrency(this._defaultData.postageOverhead));
		$("outNumInvoicesText").setProperty("value", this._defaultData.outNumInvoices);
		$("inNumInvoicesText").setProperty("value", this._defaultData.inNumInvoices);
		$("outTimePerInvoiceText").setProperty("value", this._defaultData.outTimePerInvoice);
		$("inTimePerInvoiceText").setProperty("value", this._defaultData.inTimePerInvoice);
		$("outEInvoicesPercentageText").setProperty("value", this._defaultData.outEInvoicesPercentage);
		$("inEInvoicesPercentageText").setProperty("value", this._defaultData.inEInvoicesPercentage);
		
		return this;
	},
	
	_validateInputs: function() {
		this.data.solutionInvestment = FuncUtils.suppressCurrencyFormat(this._solutionInvestmentText.getProperty("value"));
		this.data.solutionInvestment = FuncUtils.isNumeric(this.data.solutionInvestment) ?
		                               this.data.solutionInvestment.toInt().limit(500, 100000) :
		                               this._defaultData.solutionInvestment;
		
		this.data.resourcePerHour = $("resourcePerHourText").getProperty("value");
		this.data.resourcePerHour = FuncUtils.isNumeric(this.data.resourcePerHour) ?
		                            this.data.resourcePerHour.toFloat().round(2).limit(0.01, 200) :
		                            this._defaultData.resourcePerHour;
		
		this.data.postageOverhead = FuncUtils.suppressCurrencyFormat(this._postageOverheadText.getProperty("value"));
		this.data.postageOverhead = FuncUtils.isNumeric(this.data.postageOverhead) ?
		                            this.data.postageOverhead.toFloat().round(2).limit(0.5, 100) :
		                            this._defaultData.postageOverhead;
		
		this.data.outNumInvoices = $("outNumInvoicesText").getProperty("value");
		this.data.outNumInvoices = FuncUtils.isNumeric(this.data.outNumInvoices) ?
		                           this.data.outNumInvoices.toInt().limit(500, 250000) :
		                           this._defaultData.outNumInvoices;
		
		this.data.inNumInvoices = $("inNumInvoicesText").getProperty("value");
		this.data.inNumInvoices = FuncUtils.isNumeric(this.data.inNumInvoices) ?
		                          this.data.inNumInvoices.toInt().limit(500, 250000) :
		                          this._defaultData.inNumInvoices;
		
		this.data.outTimePerInvoice = $("outTimePerInvoiceText").getProperty("value");
		this.data.outTimePerInvoice = FuncUtils.isNumeric(this.data.outTimePerInvoice) ?
		                              this.data.outTimePerInvoice.toInt().limit(1, 10080) :
		                              this._defaultData.outTimePerInvoice;
		
		this.data.inTimePerInvoice = $("inTimePerInvoiceText").getProperty("value");
		this.data.inTimePerInvoice = FuncUtils.isNumeric(this.data.inTimePerInvoice) ?
		                             this.data.inTimePerInvoice.toInt().limit(1, 10080) :
		                             this._defaultData.inTimePerInvoice;
		
		this.data.outEInvoicesPercentage = $("outEInvoicesPercentageText").getProperty("value");
		this.data.outEInvoicesPercentage = FuncUtils.isNumeric(this.data.outEInvoicesPercentage) ?
		                                   this.data.outEInvoicesPercentage.toInt().limit(1, 100) :
		                                   this._defaultData.outEInvoicesPercentage;
		
		this.data.inEInvoicesPercentage = $("inEInvoicesPercentageText").getProperty("value");
		this.data.inEInvoicesPercentage = FuncUtils.isNumeric(this.data.inEInvoicesPercentage) ?
		                                  this.data.inEInvoicesPercentage.toInt().limit(1, 100) :
		                                  this._defaultData.inEInvoicesPercentage;
		
		this._setupInputs();
		
		return this;
	}
};

App.SideBar = {
	_element: null,
	_compareCostsItem: null,
	_breakEvenItem: null,
	_brochuresItem: null,
	_selectedItem: null,
	
	create: function() {
		this._element = $("side-bar");
		
		this._compareCostsItem = $("compare-costs-item");
		this._breakEvenItem = $("break-even-item");
		this._brochuresItem = $("brochures-item");
		
		this._selectedItem = this._compareCostsItem;
		
		$ES("li", this._element).addEvents({
			"mouseenter": function() {
				if (!this.hasClass("selected"))
					this.addClass("hover");
			},
			"mouseleave": function() {
				if (!this.hasClass("selected"))
					this.removeClass("hover");
			}
		});
		
		this._compareCostsItem.addEvent("click", this._showCompareCostsPane.bind(this));
		this._breakEvenItem.addEvent("click", this._showBreakEvenPane.bind(this));
		this._brochuresItem.addEvent("click", this._showBrochuresPane.bind(this));
	},
	
	_showCompareCostsPane: function() {
		if (this._selectedItem != this._compareCostsItem) {
			this._selectedItem.removeClass("selected");
			this._compareCostsItem.removeClass("hover").addClass("selected");
			
			this._selectedItem = this._compareCostsItem;
			
			App.CompareCostsPane.show();
			App.BreakEvenPane.hide();
			App.BrochuresPane.hide();
		}
		
		return this;
	},
	
	_showBreakEvenPane: function() {
		if (this._selectedItem != this._breakEvenItem) {
			this._selectedItem.removeClass("selected");
			this._breakEvenItem.removeClass("hover").addClass("selected");
			
			this._selectedItem = this._breakEvenItem;
			
			App.CompareCostsPane.hide();
			App.BreakEvenPane.show();
			App.BrochuresPane.hide();
		}
		
		return this;
	},
	
	_showBrochuresPane: function() {
		if (this._selectedItem != this._brochuresItem) {
			this._selectedItem.removeClass("selected");
			this._brochuresItem.removeClass("hover").addClass("selected");
			
			this._selectedItem = this._brochuresItem;
			
			App.CompareCostsPane.hide();
			App.BreakEvenPane.hide();
			App.BrochuresPane.show();
		}
		
		return this;
	}
};

App.CompareCostsPane = {
	_element: null,
	_visible: true,
	
	create: function() {
		this._element = $("compare-costs-pane");
	},
	
	show: function() {
		if (!this._visible) {
			this._visible = true;
			
			this._element.setStyle("display", "");
		}
		
		return this;
	},
	
	hide: function() {
		if (this._visible) {
			this._visible = false;
			
			this._element.setStyle("display", "none");
		}
		
		return this;
	},
	
	toggleShowHide: function() {
		if (this._visible)
			this.hide();
		else
			this.show();
		
		return this;
	},
	
	isVisible: function() {
		return this._visible;
	},
	
	render: function() {
		this._renderDataTable();
		
		return this;
	},
	
	_renderDataTable: function() {
		App.InputFrame.data.outCurrentCost = ((App.InputFrame.data.outNumInvoices * 12) * App.InputFrame.data.postageOverhead * App.InputFrame.data.outTimePerInvoice * (App.InputFrame.data.resourcePerHour / 60)).round(2);
		App.InputFrame.data.inCurrentCost = ((App.InputFrame.data.inNumInvoices * 12) * App.InputFrame.data.postageOverhead * App.InputFrame.data.inTimePerInvoice * (App.InputFrame.data.resourcePerHour / 60)).round(2);
		App.InputFrame.data.outFutureCost = (App.InputFrame.data.outCurrentCost - (App.InputFrame.data.outCurrentCost * (App.InputFrame.data.outEInvoicesPercentage / 100))).round(2);
		App.InputFrame.data.inFutureCost = (App.InputFrame.data.inCurrentCost - (App.InputFrame.data.inCurrentCost * (App.InputFrame.data.inEInvoicesPercentage / 100))).round(2);
		
		App.InputFrame.data.outFutureSaving = App.InputFrame.data.outCurrentCost - App.InputFrame.data.outFutureCost;
		App.InputFrame.data.inFutureSaving = App.InputFrame.data.inCurrentCost - App.InputFrame.data.inFutureCost;
		
		$E(".dataTable .cellB2", this._element).setText(FuncUtils.formatCurrency(0));
		$E(".dataTable .cellC2", this._element).setText(FuncUtils.formatCurrency(0));
		$E(".dataTable .cellD2", this._element).setText(FuncUtils.formatCurrency(0));
		
		$E(".dataTable .cellB3", this._element).setText(FuncUtils.formatCurrency(App.InputFrame.data.outFutureSaving));
		$E(".dataTable .cellC3", this._element).setText(FuncUtils.formatCurrency(App.InputFrame.data.inFutureSaving));
		$E(".dataTable .cellD3", this._element).setText(FuncUtils.formatCurrency(App.InputFrame.data.outFutureSaving + App.InputFrame.data.inFutureSaving));
		
		$E(".dataTable .cellB4", this._element).setText(FuncUtils.formatCurrency(App.InputFrame.data.outCurrentCost));
		$E(".dataTable .cellC4", this._element).setText(FuncUtils.formatCurrency(App.InputFrame.data.inCurrentCost));
		$E(".dataTable .cellD4", this._element).setText(FuncUtils.formatCurrency(App.InputFrame.data.outCurrentCost + App.InputFrame.data.inCurrentCost));
		
		var comment = "";
		
		if (App.InputFrame.data.outEInvoicesPercentage != 100 || App.InputFrame.data.inEInvoicesPercentage != 100)
			comment = "* Your business can save an additional <b>" +
			          FuncUtils.formatCurrency((App.InputFrame.data.outCurrentCost + App.InputFrame.data.inCurrentCost) - (App.InputFrame.data.outFutureSaving + App.InputFrame.data.inFutureSaving)) +
			          "</b> converting 100% of paper invoices to<br />the TIE eInvoicing solution.";
		
		$E(".dataTable .comment", this._element).empty().setHTML(comment);
		
		return this;
	}
};

App.BreakEvenPane = {
	_element: null,
	_visible: false,
	
	create: function() {
		this._element = $("break-even-pane");
	},
	
	show: function() {
		if (!this._visible) {
			this._visible = true;
			
			this._element.setStyle("display", "");
		}
		
		return this;
	},
	
	hide: function() {
		if (this._visible) {
			this._visible = false;
			
			this._element.setStyle("display", "none");
		}
		
		return this;
	},
	
	toggleShowHide: function() {
		if (this._visible)
			this.hide();
		else
			this.show();
		
		return this;
	},
	
	isVisible: function() {
		return this._visible;
	},
	
	render: function() {
		this._renderDataTable();
		this._renderGraph();
		
		return this;
	},
	
	_renderDataTable: function() {
		var monthlySaving = ((App.InputFrame.data.outFutureSaving + App.InputFrame.data.inFutureSaving) / 12).round(2);
		var saving = -App.InputFrame.data.solutionInvestment;
		
		var tableBodyEl = $E(".dataTable .body", this._element).empty();
		
		for (var month = 0; month <= 36; month++) {
			var rowEl = new Element("p", {
				"class": (month % 2 == 0) ? "even" : "odd"
			}).inject(tableBodyEl);
			
			new Element("span", {"class": "month"}).setText(month).inject(rowEl);
			new Element("span", {"class": "saving"}).setText(FuncUtils.formatCurrency(saving)).inject(rowEl);
			
			saving += monthlySaving;
		}
		
		return this;
	},
	
	_renderGraph: function() {
		var numBars = 8;
		
		var canvasEl = $E(".canvas", "break-even-graph");
		var axisesEl = $E(".axises", canvasEl);
		var barsEl = $E(".bars", canvasEl).empty();
		var infoEl = $E(".info", "break-even-graph");
		
		var step = ((App.InputFrame.data.outFutureSaving + App.InputFrame.data.inFutureSaving) / 12).round(2);
		var value = -App.InputFrame.data.solutionInvestment + step;
		var values = [];
		for (var i = 0; i < numBars; i++) {
			values.push(value);
			value += step;
		}
		
		var barEls = [];
		for (var i = 1; i <= numBars; i++) {
			var barEl = new Element("div", {
				"class": "bar month" + i
			}).inject(barsEl);
			
			barEl.addEvents({
				"mouseenter": function() {
					$E(".month .value", infoEl).setText(barEls.indexOf(this) + 1);
					$E(".saving .value", infoEl).setText(FuncUtils.formatCurrency(values[barEls.indexOf(this)]));
					
					infoEl.setStyle("display", "");
				},
				"mouseleave": function() {
					infoEl.setStyle("display", "none");
				}
			});
			
			barEls.push(barEl);
		}
		
		var yAxis = {
			"height": barsEl.getStyle("height").toInt()
		};
		
		var ratio;
		var origin;
		
		if (values[0] >= 0 && values.getLast() >= 0) {
			ratio = values.getLast() / yAxis.height;
			origin = 0;
		}
		else if (values[0] < 0 && values.getLast() < 0) {
			ratio = Math.abs(values[0]) / yAxis.height;
			origin = yAxis.height;
		}
		else {
			ratio = (Math.abs(values[0]) + values.getLast()) / yAxis.height;
			origin = (Math.abs(values[0]) / ratio).round();
		}
		
		values.each(function(value, index) {
			var height = (Math.abs(value) / ratio).round();
			
			barEls[index].setStyles({
				"height": height + "px",
				"bottom": (origin - (value >= 0 ? 0 : height)) + "px"
			});
			barEls[index].setOpacity(value >= 0 ? 1 : 0.6);
		});
		
		axisesEl.setStyles({
			"background-position": "left -" + origin + "px"
		});
	}
};

App.BrochuresPane = {
	_element: null,
	_visible: false,
	
	create: function() {
		this._element = $("brochures-pane");
	},
	
	show: function() {
		if (!this._visible) {
			this._visible = true;
			
			this._element.setStyle("display", "");
		}
		
		return this;
	},
	
	hide: function() {
		if (this._visible) {
			this._visible = false;
			
			this._element.setStyle("display", "none");
		}
		
		return this;
	},
	
	toggleShowHide: function() {
		if (this._visible)
			this.hide();
		else
			this.show();
		
		return this;
	},
	
	isVisible: function() {
		return this._visible;
	}
};