﻿/*
*/
function Order(order$) {
	this._container$ = order$;
	this._items = [];
}
Order.prototype = {
	_appendItem$: function(item$) { this._container$.append(item$); },
	add: function(menuItem$) {
		var item = new OrderItem(menuItem$, this);
		this._items.push(item);
	},
	remove: function(menuItem$, remove) {
		var found = false;
		for (var i = 0; i < this._items.length; i++) {
			if (found) {
				this._items[i-1] = this._items[i];
				// may need to call position() on each item to reposition it visually
			}
			else if (this._items[i].isMI(menuItem$)) {
				found = true;
				if (remove) { this._items[i].remove(false); }
			}
		}
		if (found) { this._items.pop(); }
	},
	removeAll: function() {
		while (this._items.length > 0) {
			var item = this._items.pop();
			item.remove(false);
		}
	},
	validate: function() {
		var e = '';
		var c = this._items.length;
		if (c > 0) {
			for (var i = 0; i < c; i++) {
				var ie = this._items[i].validate();
				if (ie != '') e += '\n' + ie;
			}
		}
		else {
			e = 'Please select some items from the menu for your order';
		}
		return e;
	},
	toString: function() {
		var s = '';
		for (var i = 0; i < this._items.length; i++) {
			s += '~n' + this._items[i].toString();
		}
		return s;	
	},
	getLength: function() {
		return this._items.length;
	}
}

function OrderItem(menuItem$, order) {
	var s = this;
	s._order = order;
	
	s._menuItem$ = menuItem$;
	var desc = menuItem$.children('.description');
	s.name = desc[0].firstChild.data
	//s._price$ = menuItem$.children('.price');
	
	s._container$ = $('<div class="orderitem"></div>');
	//s._order.order$().append(s._container$);
	order._appendItem$(s._container$);

	var name = $('<div class="orderDescription">' + s.name + '</div>');
	s._container$.append(name);

	var remove = $('<span class="remove" title="Remove item from list">X</span>');
	s._container$.append(remove);
	remove.click(function(e) {s.remove(true);});
		
	if (desc.hasClass('bread')) {
		s._multi = new Multioptions(s.bread, s._container$);
		s._multiName = 'bread';
	}
	else if (desc.hasClass('juice')) {
		s._multi = new Multioptions(s.juice, s._container$);
		s._multiName = 'size';
	}
	else {
		s._quantity = new Quantity(name, 9, 1);
	}

}
OrderItem.prototype = {
	bread: ['on White Bloomer', 'on Toasted White Bloomer', 'on Brown Bloomer', 'on Toasted Brown Bloomer', 'on Panini', 'on Ciabatta'],
	juice: ['250ml Glass', '500ml Jug'],
	isMI: function(menuItem$) { return this._menuItem$.length == menuItem$.length && this._menuItem$[0] == menuItem$[0]; },
	//position: function() { if (this._multi) this._multi.position(); },
	remove: function(remove) { 
		this._container$.remove(); 
		this._menuItem$.removeClass('ordered'); 
		if (remove) { this._order.remove(this._menuItem$, false); }
	},
	quantity: function() {
		return this._multi ? this._multi.total() : this._quantity.getQuantity();
	},
	validate: function() {
		if (this._multi) {
			if (this._multi.total() == 0) {
				return 'Please select which ' + this._multiName + ' you want for the ' + this.name;
			}
		}
		return '';
	},
	toString: function() {
		if (this._multi) {
			return this.name + this._multi.toString();
		}
		else {
			return this.name + ' x ' + this.quantity();
		}
	}
}

function Quantity(parent$, max, min) {
	var s = this;
	s._max = max ? max : Number.MAX_VALUE;
	s._min = min ? min : 0;
	s._parent$ = parent$;
	
	s._container$ = $('<span class="quantitySelector"></span>');
	if (parent$) parent$.append(s._container$);
	
	var down = $('<span class="down" title="Quantity down">&#171;</span>');
	down.click(function(e) { s.decrQuantity(); });
	s._container$.append(down);
	
	s._current$ = $('<span class="quantity">1</span>');
	s._container$.append(s._current$);
	
	var up = $('<span class="up" title="Quantity up">&#187;</span>');
	up.click(function(e) { s.incrQuantity(); });
	s._container$.append(up);
}
Quantity.prototype = {
	getMax: function() { return this._max; },
	setMax: function(n) { this._max = n; this.setQuantity(this.getQuantity()); },
	getMin: function() { return this._min; },
	setMin: function(n) { this._min = n; this.setQuantity(this.getQuantity()); },
	getQuantity: function() { return this._current$[0].firstChild.data / 1; },
	setQuantity: function(i) { 
		var newQuantity = Math.min(Math.max(i, this._min), this._max);
		if (newQuantity != this.getQuantity()) {
			this._current$[0].firstChild.data = newQuantity;
			this._container$.trigger('onquantity', newQuantity);
		}
	},
	incrQuantity: function() { this.setQuantity(this.getQuantity()+1); },
	decrQuantity: function() { this.setQuantity(this.getQuantity()-1); },
	onquantity: function(f) { this._container$.bind('onquantity', f); }
}

function Multioptions(opts, parent$) {
	var s = this;
	s._opts = [];
	s._parent$ = parent$;
	s._container$ = $('<div class="options show"></div>');
	s._container$.hover(
		function(e) { s.show(); }, 
		function(e) { if (s.total() > 0) s.hide(); }
	);
	if (parent$) parent$.append(s._container$);

	for (var i = 0; i < opts.length; i++) {
		s._opts.push(new Multioption(opts[i], s._container$, false))
	}
}
Multioptions.prototype = {
	show: function() {
		var s = this;
		if (!s._timerID) {
			s._timerID = window.setTimeout(function() {
				s._container$.addClass('show');
				s._timerID = null;
			}, 300);
		}
	},
	hide: function() {
		if (this._timerID) {window.clearTimeout(this._timerID); this._timerID = null;}
		this._container$.removeClass('show');
	},
	total: function() {
		var q = 0;
		for (var i = 0; i < this._opts.length; i++) {
			q += this._opts[i].quantity();
		}
		return q;
	},
	toString: function() {
		var s = ''
		for (var i = 0; i < this._opts.length; i++) {
			var q = this._opts[i].quantity()
			if (q > 0) {
				s += '~n~t' + this._opts[i].name + ' x ' + this._opts[i].quantity();
			}
		}
		return s;
	}
}

function Multioption(opt, parent$, sel) {
	var s = this;
	s.name = opt;
	s._parent$ = parent$;
	s._container$ = $('<div class="option ' + (sel ? 'selected' : '') + '"></div>');
	if (parent$) parent$.append(s._container$);
	var o = $('<span class="optionDescription">' + opt + '</span>')
	o.click(function(e) {
		if (s.quantity() == s._quantity.getMin()) {
			s._quantity.incrQuantity();
		}
		else if (s.quantity() == s._quantity.getMin() + 1) {
			s._quantity.decrQuantity();
		}
	});
	s._container$.append(o);
	s._quantity = new Quantity(s._container$, 9, 0);
	s._quantity.setQuantity(sel ? 1 : 0);
	s._quantity.onquantity(function(e, n) {
		s._container$.removeClass('selected');
		if (n > 0) {
			s._container$.addClass('selected');
		}
	});
}
Multioption.prototype = {
	quantity: function() {
		return this._quantity.getQuantity();
	}
}

function Options(opts, parent$) {
	var s = this;
	s._opts = opts;
	s._parent$ = parent$;
	
	s._container$ = $('<span></span>'); // perhaps make show/hide hover work at this level!!
	s._container$.hover(function(e) { s.show(); }, function(e) { s.hide(); });
	if (parent$) parent$.append(s._container$);
	
	var down = $('<span class="down" title="previous bread">&#171;</span>');
	down.click(function(e) { s.down(); });
	s._container$.append(down);
	
	s._current = s._opts[0];
	var longest = '';
	for (var i = 0; i < opts.length; i++) {
		if (s._opts[i].length > longest.length) longest = s._opts[i];
	}
	longest = longest.replace(' ', '_');
	s._sizer$ = $('<span class="optionHolder" style="display:inherit;">' + longest + '</span>');
	s._container$.append(s._sizer$);

	s._optList$ =  $('<span class="menuOptions"></span>');
	s._sizer$.append(s._optList$);
	s._position();
	for (var i = 0; i < opts.length; i++) {
		var cls = i == 0 ? 'selected' : '';
		var opt = $('<div class="menuOption ' + cls + '">' + opts[i] + '</div>')
		opt.click(function(e) {s.setText($(this)[0].firstChild.data); s.hide();} );
		s._optList$.append(opt);
	}
	
	var up = $('<span class="up" title="next bread">&#187;</span>');
	up.click(function(e) { s.up(); });
	s._container$.append(up);
}
Options.prototype = {
	_getCurrentText: function() { return this._current; },
	_setCurrentText: function(text) { this._current = text; },
	getID: function(text) { 
		if (!text) text = this._getCurrentText();
		for (var i = 0; i < this._opts.length; i++) {
			if (text == this._opts[i]) return i;
		}
		return -1;
	},
	setID: function(id) {
		this._setCurrentText(this.getText(id));
		var c = this._optList$.children();
		c.removeClass('selected');
		$(c[id]).addClass('selected');
	},
	getText: function(id) { 
		if (id == undefined) return this._getCurrentText();
		else return this._opts[id]; // need bounds checking on id
	},
	setText: function(text) {
		this.setID(this.getID(text));
	},
	up: function() { 
		var oid = this.getID();
		if (oid < this._opts.length - 1) {
			this.setID(oid + 1);
		}
	},
	down: function() { 
		var oid = this.getID();
		if (oid > 0) {
			this.setID(oid - 1);
		}
	},
	_position: function() {
		var p = this._sizer$.position();
		var w = this._sizer$.outerWidth();
		this._optList$.css(p);
		this._optList$.width(w - 2);
	},
	show: function() {
		var s = this;
		s._position();
		if (!s._timerID) {
			s._timerID = window.setTimeout(function() {
				s._optList$.addClass('show');
				s._timerID = null;
			}, 200);
		}
	},
	hide: function() {
		if (this._timerID) {window.clearTimeout(this._timerID); this._timerID = null;}
		this._optList$.removeClass('show');
	}
};


function Menu() {
	this.timer = null;
}
Menu.prototype = {
	clear: function() {
		if (this._timer) {
			window.clearTimeout(this._timer);
		}
	},
	goto: function(menulink) {
		this.clear();
		var section = '#' + menulink[0].firstChild.data;
		this._timer = window.setTimeout(
			function(e) {
				var m = $('div.menu');
				var s = $(section);
				m.scrollTo(s, 400);
			}, 300);
	}
}

function PromptText(txt$, text, val, err, valOnBlur) {
	var s = this;
	s._txt$ = txt$;
	s.text = text;
	s.val = val;
	s.err = err;
	valOnBlur = valOnBlur ? valOnBlur : false;
//	if (txt$[0].nodeName.match(/textarea/i)) {
//		s.getVal = function() {return txt$[0].firstChild.data;}
//		s.setVal = function(val) {txt$[0].firstChild.data = val;}
//	}
//	else {
//		s.getVal = function() {return txt$[0].value;}
//		s.setVal = function(val) {txt$[0].value = val;}
//	}
	if (!txt$.hasClass('prompt')) txt$.addClass('prompt'); // this is really the blur function
	txt$.focus(function(e) {
		if (txt$.hasClass('prompt')) {
			s.setVal('');
			txt$.removeClass('prompt');
		}
	});
	txt$.blur(function(e) {
		var val = s.getVal();
		if (val == '' || (valOnBlur && !s.val(val, s))) {
			s.setVal(s.text);
			txt$.addClass('prompt');
		}
	});
}
PromptText.time = function(v) {
	var pat1 = /^(\d{1,2}):(\d{2})(:(\d{2}))?(\s?(AM|am|PM|pm))?$/;
	var pat2 = /^([1-9]|(11)|(12)) *\: *[0-5][0-9] *$/;
	var res = pat1.test(v);
	var resArray = v.match(pat2);
	var d = Date.parse(v);
	return res;
}
PromptText.text = function(v, pt) {
	return v != pt.text;
}
PromptText.email = function(v, pt) {
	var pat1 = /([\w\-]+\@[\w\-]+\.[\w\-]+)/;
	return pat1.test(v);
}
PromptText.phone = function(v, pt) {
	var pat1 = /^[\d]+[\d\s]+$/;
	return pat1.test(v);
}
PromptText.none = function(v) { return true; }
PromptText.prototype = {
	validate: function() {
		if (!this.val(this.getVal(), this)) {
			return 'you need to enter a valid ' + (this.err ? this.err : 'value'); 
		}
		return '';
	},
	getVal: function() {
		return this._txt$.val();
	},
	setVal: function(val) {
		this._txt$.val(val);
	}
}

function validateForm() {
	if (validateForm.isEnabled()) {
		// validate
		var e = validateForm.order.validate();
		e += (e != '' ? '\n' : '') + validateForm.orderTime.validate();
		e += (e != '' ? '\n' : '') + validateForm.yourname.validate();
		e += (e != '' ? '\n' : '') + validateForm.email.validate();
		e += (e != '' ? '\n' : '') + validateForm.phone.validate();
		if (e != '') {
			alert(e);
			return false;
		}
		var orderfield = $('.orderfield');
		//orderfield.append(validateForm.order.toString());
		orderfield.val(validateForm.order.toString());
		//orderfield.show();
		return true;
	}
	else {
		
		alert('Sorry, you cannot place an order after ' + validateForm.endTime.getHours() + ':' + validateForm.endTime.getMinutes());
		return false;
	}
}
validateForm.isEnabled = function() {
	return !$('.order').hasClass('disabled');
}
validateForm.setEnabled = function(enabled) {
	if (enabled) validateForm.enable();
	else validateForm.disable();
}
validateForm.disable = function() {
	$('.order').addClass('disabled');
}
validateForm.enable = function() {
	$('.order').removeClass('disabled');
}

$(document).ready(function() {
// this is the cut off time
	var endTime = new Date();
	endTime.setHours(11,30,0,0);
	var now = new Date();
	
	var order = new Order($('.order'));

	validateForm.endTime = endTime;
	validateForm.setEnabled(now < endTime && now.getDay() > 0);
	
	$('#removeall').click(function(e) {
		if (validateForm.isEnabled() && order.getLength() > 0 && window.confirm('Are you sure you want to remove everything from your order?'))
			order.removeAll();
	});
		
	$('.description').parent()
		.addClass('menuitem')
		.hover(
			function(e) { if (validateForm.isEnabled()) $(this).addClass('hover'); },
			function(e) { if (validateForm.isEnabled()) $(this).removeClass('hover'); }
		).click(
			function(e) { 
				if (validateForm.isEnabled()) {
					var mi = $(this);
					if (mi.hasClass('ordered')) {
						order.remove(mi, true);
					}
					else {
						order.add(mi); 
						$(this).addClass('ordered'); 
					}
				}
			}
		);
			
	var menu = new Menu();
	var menulinks = $('.menulink');
	menulinks.hover(
		function(e) {
			menu.goto($(this));
		},
		function(e) {
			menu.clear();
		}
	);
	
	validateForm.order = order;
	var sp = new PromptText($('.message'),"Your special requirements", PromptText.none, "");
	validateForm.orderTime = new PromptText($('.textcollect'),"Enter a time (after 12pm)", PromptText.text, "Collection Time");
	validateForm.email = new PromptText($('.textemail'),"", PromptText.email, "email address");
	validateForm.phone = new PromptText($('.textphone'),"", PromptText.phone, "phone number");
	validateForm.yourname = new PromptText($('.textname'),"", PromptText.text, "name");

	window.setTimeout(function() {
		validateForm.disable();
	}, endTime - now);


});
