(function (window, undefined){
	"use strict";
	pjQ.$.ajaxSetup({
		xhrFields: {
			withCredentials: true
		}
	});
	var document = window.document,
		validate = (pjQ.$.fn.validate !== undefined),
		routes = [
		          	{pattern: /^#!\/loadSearch$/, eventName: "loadSearch"},
		          	{pattern: /^#!\/loadBooth$/, eventName: "loadBooth"},
		          	{pattern: /^#!\/loadExtras$/, eventName: "loadExtras"},
		          	{pattern: /^#!\/loadCheckout$/, eventName: "loadCheckout"},
		          	{pattern: /^#!\/loadPreview$/, eventName: "loadPreview"},
		         ];
	
	function log() {
		if (window.console && window.console.log) {
			for (var x in arguments) {
				if (arguments.hasOwnProperty(x)) {
					window.console.log(arguments[x]);
				}
			}
		}
	}
	
	function assert() {
		if (window && window.console && window.console.assert) {
			window.console.assert.apply(window.console, arguments);
		}
	}
	
	function hashBang(value) {
		if (value !== undefined && value.match(/^#!\//) !== null) {
			if (window.location.hash == value) {
				return false;
			}
			window.location.hash = value;
			return true;
		}
		
		return false;
	}
	
	function onHashChange() {
		var i, iCnt, m;
		for (i = 0, iCnt = routes.length; i < iCnt; i++) {
			m = window.location.hash.match(routes[i].pattern);
			if (m !== null) {
				pjQ.$(window).trigger(routes[i].eventName, m.slice(1));
				break;
			}
		}
		if (m === null) {
			pjQ.$(window).trigger("loadSearch");
		}
	}
	pjQ.$(window).on("hashchange", function (e) {
    	onHashChange.call(null);
    });
	
	function NightClub(opts) {
		if (!(this instanceof NightClub)) {
			return new NightClub(opts);
		}
				
		this.reset.call(this);
		this.init.call(this, opts);
		
		return this;
	}
	
	NightClub.inObject = function (val, obj) {
		var key;
		for (key in obj) {
			if (obj.hasOwnProperty(key)) {
				if (obj[key] == val) {
					return true;
				}
			}
		}
		return false;
	};
	
	NightClub.size = function(obj) {
		var key,
			size = 0;
		for (key in obj) {
			if (obj.hasOwnProperty(key)) {
				size += 1;
			}
		}
		return size;
	};
	
	NightClub.prototype = {
		reset: function () {
			this.$container = null;			
			this.container = null;
			this.date = null;
			this.booth_id = null;
			this.opts = {};
			
			return this;
		},
		
		disableButtons: function () {
			this.$container.find(".btn").each(function (i, el) {
				pjQ.$(el).attr("disabled", "disabled");
			});
		},
		enableButtons: function () {
			this.$container.find(".btn").removeAttr("disabled");
		},
		
		init: function (opts) {
			var self = this;
			this.opts = opts;
			this.container = document.getElementById("pjNcbContainer_" + self.opts.index);
						
			self.$container = pjQ.$(self.container);
			
			this.$container.on("click.nc", ".pjNcbSelectBooth", function (e) {
				if (e && e.preventDefault) {
					e.preventDefault();
				}
				var booth_id = pjQ.$(this).attr('data-id');
				
				self.disableButtons();
				pjQ.$.get([self.opts.folder, "index.php?controller=pjFront&action=pjActionSetBooth", "&session_id=", self.opts.session_id, "&id=", booth_id].join("")).done(function (data) {
					if(data.status == 'OK')
					{
						if (!hashBang("#!/loadBooth")) 
						{
							self.loadBooth.call(self);
						}
					}else{
						self.enableButtons();
					}
				}).fail(function () {
					self.enableButtons();
				});
				return false;
			}).on("click.nc", ".pjNcbMenuItem", function (e) {
				if (e && e.preventDefault) {
					e.preventDefault();
				}
				if(!pjQ.$(this).parent().hasClass('disabled'))
				{
					var item = pjQ.$(this).attr('data-item');
					if (!hashBang("#!/" + item)) 
					{
						pjQ.$(window).trigger(item);
					}
				}
				return false;
			}).on("change.nc", "#pjNcbCnt_" + self.opts.index, function (e) {
				var cnt = pjQ.$(this).val(),
					price = pjQ.$(this).attr('data-price');
				self.disableButtons();
				pjQ.$.get([self.opts.folder, "index.php?controller=pjFront&action=pjActionSetCount", "&session_id=", self.opts.session_id, "&cnt=", cnt, "&price=", price].join("")).done(function (data) {
					if(data.status == 'OK')
					{
						pjQ.$('#pjNcbPrice_' + self.opts.index).html(data.text);
					}
					self.enableButtons();
				}).fail(function () {
					self.enableButtons();
				});
				return false;
			}).on("click.nc", ".pjNcb-drink-title", function (e) {
				if (e && e.preventDefault) {
					e.preventDefault();
				}
				pjQ. $(this).next().toggleClass('active');
				return false;
			}).on("click.nc", ".pjNcbCategory", function (e) {
				if (e && e.preventDefault) {
					e.preventDefault();
				}
				var category_id = pjQ.$(this).attr('data-id');
				pjQ.$('.pjNcbCategory').parent().removeClass('active');
				pjQ.$(this).parent().addClass('active');
				self.disableButtons();
				pjQ.$.get([self.opts.folder, "index.php?controller=pjFront&action=pjActionGetExtras", "&session_id=", self.opts.session_id, "&category_id=", category_id].join("")).done(function (data) {
					pjQ.$('#pjNcbExtrasContainer_' + self.opts.index).html(data);
					self.enableButtons();
				}).fail(function () {
					self.enableButtons();
				});
				return false;
			}).on("click.nc", ".pjNcbSpinner", function (e) {
				if (e && e.preventDefault) {
					e.preventDefault();
				}
				var spinnerUpClass = 'pjNcb-spinner-up';
		        var spinnerDownClass = 'pjNcb-spinner-down';
		        var spinnerResult = '.pjNcb-spinner-result';
		        
		        var $clickedSpinnerBtn = pjQ.$(this);
	            var $spinnerField = $clickedSpinnerBtn.siblings(spinnerResult);
	            var $spinnerValue = $spinnerField.val();
	           
	            var category_id = $clickedSpinnerBtn.attr('data-cid');
	            var extra_id = $clickedSpinnerBtn.attr('data-id');
	            
	            if ($clickedSpinnerBtn.hasClass(spinnerUpClass)) 
	            {
	                $spinnerValue = $spinnerValue +++ 1;
	            } else if ($clickedSpinnerBtn.hasClass(spinnerDownClass)) {
	                $spinnerValue = $spinnerValue --- 1;
	            };

	            if ($spinnerValue <= 0) 
	            {
	                $spinnerValue = 0;
	            };
	            
	            self.disableButtons();
	            pjQ.$.get([self.opts.folder, "index.php?controller=pjFront&action=pjActionSetExtras", "&session_id=", self.opts.session_id, "&category_id=", category_id, "&extra_id=", extra_id, '&cnt=', $spinnerValue].join("")).done(function (data) {
	            	if(data.status == 'OK')
	            	{
			            if(pjQ.$('#pjNcbCheckoutForm_' + self.opts.index).length > 0)
			            {
			            	if (!hashBang("#!/loadCheckout")) 
							{
								self.loadCheckout.call(self);
							}
			            }else{
			            	$spinnerField.val($spinnerValue);
			            }
	            	}
					self.enableButtons();
				}).fail(function () {
					self.enableButtons();
				});
	            
				return false;
			}).on("change.nc", "select[name='payment_method']", function () {
				self.$container.find(".pjNcbCcWrap").hide();
				self.$container.find(".pjNcbBankWrap").hide();
				switch (pjQ.$("option:selected", this).val()) {
				case 'creditcard':
					self.$container.find(".pjNcbCcWrap").show();
					break;
				case 'bank':
					self.$container.find(".pjNcbBankWrap").show();
					break;
				}
			}).on("click.nc", ".pjNcbBtnStartOver", function (e) {
				if (e && e.preventDefault) {
					e.preventDefault();
				}
				if (!hashBang("#!/loadSearch")) 
				{
					self.loadSearch.call(self);
				}
				return false;
			});
			
			pjQ.$(window).on("loadSearch", this.$container, function (e) {
				self.loadSearch.call(self);
			}).on("loadBooth", this.$container, function (e) {
				self.loadBooth.call(self);
			}).on("loadExtras", this.$container, function (e) {
				self.loadExtras.call(self);
			}).on("loadCheckout", this.$container, function (e) {
				self.loadCheckout.call(self);
			}).on("loadPreview", this.$container, function (e) {
				self.loadPreview.call(self);
			});
			
			if (window.location.hash.length === 0) {
				this.loadSearch.call(this);
			} else {
				onHashChange.call(null);
			}
		},
		
		loadSearch: function () {
			var self = this,
				index = this.opts.index,
				params = { 
							"locale": this.opts.locale,
							"index": this.opts.index,
							"date": this.date
						 };
			pjQ.$.get([this.opts.folder, "index.php?controller=pjFront&action=pjActionSearch", "&session_id=", self.opts.session_id].join(""), params).done(function (data) {
				self.$container.html(data);
				self.bindSearch();
			}).fail(function () {
				
			});
		},
		bindSearch: function(){
			var self = this,
				index = this.opts.index;
		
			if (pjQ.$('.pjNcbDate').length) 
			{
				moment.locale('en', {
					week: { dow: self.opts.week_start },
					months : pjQ.$('#pjNcbCalendarLocale').data('months').split("_"),
			        weekdaysMin : pjQ.$('#pjNcbCalendarLocale').data('days').split("_")
				});
				var currentDate = new Date();
				pjQ.$('.pjNcbDate').datetimepicker({
					format: self.opts.momentDateFormat.toUpperCase(),
					locale: moment.locale('en'),
					allowInputToggle: true,
					minDate: new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate())
				});
				
				pjQ.$('.pjNcbDate').on('dp.change', function(e) {
					self.date = pjQ.$('#pjNcbDate_' +index).val();
					if (!hashBang("#!/loadSearch")) 
					{
						self.loadSearch.call(self);
					}
				});
			}
		},
		loadBooth: function () {
			var self = this,
				index = this.opts.index,
				params = { 
							"locale": this.opts.locale,
							"index": this.opts.index
						 };

			pjQ.$.get([this.opts.folder, "index.php?controller=pjFront&action=pjActionBooth", "&session_id=", self.opts.session_id].join(""), params).done(function (data) {
				if (data.code != undefined && data.status == 'ERR') {
					if (!hashBang("#!/loadSearch")) 
					{
						self.loadSearch.call(self);
					}
				}else{
					self.$container.html(data);
				}
			}).fail(function () {
				
			});
		},
		loadExtras: function () {
			var self = this,
				index = this.opts.index,
				params = { 
							"locale": this.opts.locale,
							"index": this.opts.index
						 };

			pjQ.$.get([this.opts.folder, "index.php?controller=pjFront&action=pjActionExtras", "&session_id=", self.opts.session_id].join(""), params).done(function (data) {
				if (data.code != undefined && data.status == 'ERR') {
					if(data.code == '100')
					{
						if (!hashBang("#!/loadSearch")) 
						{
							self.loadSearch.call(self);
						}
					}else{
						if (!hashBang("#!/loadCheckout")) 
						{
							self.loadCheckout.call(self);
						}
					}
				}else{
					self.$container.html(data);
				}
			}).fail(function () {
				
			});
		},
		loadCheckout: function () {
			var self = this,
				index = this.opts.index,
				params = { 
							"locale": this.opts.locale,
							"index": this.opts.index
						 };

			pjQ.$.get([this.opts.folder, "index.php?controller=pjFront&action=pjActionCheckout", "&session_id=", self.opts.session_id].join(""), params).done(function (data) {
				if (data.code != undefined && data.status == 'ERR') {
					if (!hashBang("#!/loadSearch")) 
					{
						self.loadSearch.call(self);
					}
				}else{
					self.$container.html(data);
					self.bindCheckout.call(self);
				}
			}).fail(function () {
				
			});
		},
		bindCheckout: function(){
			var self = this,
				index = this.opts.index;
		
			pjQ.$('.modal-dialog').css("z-index", "9999"); 
			
			if (validate) 
			{
				var $form = pjQ.$('#pjNcbCheckoutForm_'+ self.opts.index);
				$form.validate({
					rules: {
						"captcha": {
							remote: self.opts.folder + "index.php?controller=pjFront&action=pjActionCheckCaptcha"
						}
					},
					onkeyup: false,
					errorElement: 'li',
					errorPlacement: function (error, element) {
						if(element.attr('name') == 'terms')
						{
							error.appendTo(element.siblings().find('ul'));
						}else{
							error.appendTo(element.next().find('ul'));
						}
					},
		            highlight: function(ele, errorClass, validClass) {
		            	var element = pjQ.$(ele);
		            	if(element.attr('name') == 'captcha')
						{
							element.parent().parent().parent().addClass('has-error');
						}else{
							element.parent().addClass('has-error');
						}
		            },
		            unhighlight: function(ele, errorClass, validClass) {
		            	var element = pjQ.$(ele);
		            	if(element.attr('name') == 'captcha')
						{
							element.parent().parent().parent().removeClass('has-error').addClass('has-success');
						}else{
							element.parent().removeClass('has-error').addClass('has-success');
						}
		            },
					submitHandler: function (form) {
						self.disableButtons.call(self);
						var $form = pjQ.$(form);
						pjQ.$.post([self.opts.folder, "index.php?controller=pjFront&action=pjActionCheckout"].join(""), $form.serialize()).done(function (data) {
							if (data.status == "OK") {
								if (!hashBang("#!/loadPreview")) 
								{
									self.loadPreview.call(self);
								}
							}
						}).fail(function () {
							self.enableButtons.call(self);
						});
						return false;
					}
				});
			}
		},
		loadPreview: function () {
			var self = this,
				index = this.opts.index,
				params = { 
							"locale": this.opts.locale,
							"index": this.opts.index
						 };

			pjQ.$.get([this.opts.folder, "index.php?controller=pjFront&action=pjActionPreview", "&session_id=", self.opts.session_id].join(""), params).done(function (data) {
				if (data.code != undefined && data.status == 'ERR') {
					if (!hashBang("#!/loadSearch")) 
					{
						self.loadSearch.call(self);
					}
				}else{
					self.$container.html(data);
					self.bindPreview.call(self);
				}
			}).fail(function () {
				
			});
		},
		bindPreview: function(){
			var self = this,
				index = this.opts.index;
		
			if (validate) 
			{
				var $form = pjQ.$('#pjNcbPreviewForm_'+ self.opts.index);
				$form.validate({
					onkeyup: false,
					errorElement: 'li',
					errorPlacement: function (error, element) {
						if(element.attr('name') == 'terms')
						{
							error.appendTo(element.siblings().find('ul'));
						}else{
							error.appendTo(element.next().find('ul'));
						}
					},
		            highlight: function(ele, errorClass, validClass) {
		            	var element = pjQ.$(ele);
		            	if(element.attr('name') == 'captcha')
						{
							element.parent().parent().parent().addClass('has-error');
						}else{
							element.parent().addClass('has-error');
						}
		            },
		            unhighlight: function(ele, errorClass, validClass) {
		            	var element = pjQ.$(ele);
		            	if(element.attr('name') == 'captcha')
						{
							element.parent().parent().parent().removeClass('has-error').addClass('has-success');
						}else{
							element.parent().removeClass('has-error').addClass('has-success');
						}
		            },
					submitHandler: function (form) {
						self.disableButtons.call(self);
						var $form = pjQ.$(form);
						pjQ.$.post([self.opts.folder, "index.php?controller=pjFront&action=pjActionSaveReservation"].join(""), $form.serialize()).done(function (data) {
							if (data.code == "200") {
								self.getPaymentForm.call(self, data);
							} else if (data.code == "119") {
								self.enableButtons.call(self);
							}
						}).fail(function () {
							self.enableButtons.call(self);
						});
						return false;
						return false;
					}
				});
			}
		},
		getPaymentForm: function(obj){
			var self = this,
				index = this.opts.index;
			var	params = { 
					"locale": this.opts.locale,
					"index": this.opts.index,
					"reservation_id": obj.reservation_id, 
					"payment_method": obj.payment,
				 };
			pjQ.$.get([this.opts.folder, "index.php?controller=pjFront&action=pjActionGetPaymentForm"].join(""), params).done(function (data) {
				self.$container.html(data);
				switch (obj.payment) {
					case 'paypal':
						self.$container.find("form[name='ncbPaypal']").trigger('submit');
						break;
					case 'authorize':
						self.$container.find("form[name='ncbAuthorize']").trigger('submit');
						break;
					case 'creditcard':
					case 'bank':
					case 'cash':
						break;
				}
			}).fail(function () {
				log("Deferred is rejected");
			});
		}
	};
	
	window.NightClub = NightClub;	
})(window);