/*----------------------------------------------------------------------------
Lev Kanter
2011

----------------------------------------------------------------------------*/

if (!LEV_KANTER) {
	var LEV_KANTER = {
		version: 1.1
	};
}

// ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
// ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

(function(app, $) {

	var debug = true;
	
	function typeCheckString(v) {
		var t = app.typeOf(v);
		if (t !== "string")
			throw new TypeError("expected string, was passed " + t);
	};
	
	function typeCheckNum(v) {
		var t = app.typeOf(v);
		if (t !== "number")
			throw new TypeError("expected number, was passed " + t);
	};
	
	app.instances = {
		browser: {}
	};

	if (debug && 
		typeof console !== "undefined" &&
		typeof console.debug !== "undefined") {
			app.log = function(message, level) {
				console[level || "info"](message);
			};
			app.dump = function(obj) {
				console.log(obj);
			}
		}
	else {
		app.log = app.dump = function() {};
	}

	app.typeOf = function(v) {
			var s = typeof v;
			if (s === "object") {
				if (v) {
					if (typeof v.length === "number" &&
							!v.propertyIsEnumerable("length") &&
							typeof v.splice === "function")
								s = "array";
				} else
					s = "null";
			}
			return s;
	};

	app.random = function() {
		if (arguments.length === 0)
			return Math.random();
		else if (arguments.length === 1)
			return Math.random()*arguments[0];
		else {
			return (function(min, max) {
				return Math.random()*(max - min) + min;
			}(arguments[0], arguments[1]));
		}
	};

	app.round = function(n, places) {
		var pow = Math.pow(10, places);
		return Math.round(n*pow) / pow;
	};

	app.trim = function(str) {
		typeCheckString(str);
		return $.trim(str);
	};

	app.truncate = function(str, len) {
		typeCheckString(str);
		typeCheckNum(len);
		return str.length > len ?
			str.substring(0, len) : str;
	};

	app.isEmpty = function(str) {
		typeCheckString(str);
		return $.trim(str) ? true : false;
	};

	app.extend = function(sub, base) {
		var F = function() {};
		F.prototype = base.prototype;
		sub.prototype = new F();
		sub.prototype.constructor = sub;
		sub.base = base.prototype;
		if (base.prototype.constructor == Object.prototype.constructor)
			base.prototype.constructor = base;
	};

	app.clone = function(obj) {
		var F = function() {};
		F.prototype = obj;
		return new F();
	};

	app.augment = function(dest, src) {
		var i;
		if (arguments[2]) {
			for (i = 2; i < arguments.length; i += 1) {
				dest.prototype[arguments[i]] = src.prototype[arguments[i]];
			}
		} else {
			for (i in src.prototype) {
				if (!dest.prototype[i]) {
					dest.prototype[i] = src.prototype[i];
				}
			}
		}
	};

	app.timer = {
		future: function(f, t, cb) {
			return {
				id: setTimeout(f, t),
				callback: typeof(cb) === "function" ?
					cb : null
			};
		},
		tick: function(f, t, cb) {
			return {
				id: setInterval(f, t),
				callback: typeof(cb) === "function" ?
					cb : null
			};
		},
		end: function(op) {
			clearTimeout(op.id);
			if (typeof(op.callback) === "function")
				op.callback();
		}
	};

	app.modal = function(options) {
		var $modal, $bg, o, isOpen;
		
		app.log("[modal]");
		
		o = $.extend({
			onOpen: function(instance) {},
			onClose: function(instance) {},
			template: {
				base: "<div class='modal'></div>",
				bg: "<div class='page-cover'></div>"
			},
			context: "body"
		}, options);
		
		$modal = $(o.template.base); 
		$bg = $(o.template.bg);
		
		$bg.click(function(e) {
			$modal.close();
		});
		
		$modal.open = function(content) {
			$bg.show();
			$modal.append(content).show();
			
			isOpen = true;
			if (typeof o.onOpen === "function")
				o.onOpen($modal);
		};
		
		$modal.close = function() {
			$modal.hide().empty();
			$bg.hide();
			
			isOpen = false;
			if (typeof o.onClose === "function")
				o.onClose($modal);
		};
		
		$bg.hide().appendTo(o.context);
		$modal.hide().appendTo(o.context);
		return $modal;
	};
	
	$.prototype.switchMenu = function(options) {
		var $select = this;
		
		$select.change(function(e) {
			var v = $select.find("option:selected").val();
			if (v !== "") {
				window.location.assign(v);
			}
		});
		
		return $select;
	};

	$.prototype.carousel = function(options) {
		var $c, scrollable, o;
		
		app.log("[carousel]");
	
		o = $.extend({
			scrollableOptions: {
				circular: true,
				speed: 300
			},
			useNavigator: true,
			unitSelector: "p",
			template: {
				crud: "<div><div class='items'></div></div>",
				controls:
					"<div class='controls'><div>\
						<a class='btn prev'><span><span>Previous</span></span></a>\
						<div class='navi'></div>\
						<a class='btn next'><span><span>Next</span></span></a>\
					</div></div>"
			}
		}, options);
	
		$c = this;
		$c.find(o.unitSelector).wrapAll(o.template.crud);
		$c.append(o.template.controls);
		scrollable = $c.find("div:first").scrollable(o.scrollableOptions);
		if (o.useNavigator) 
			scrollable.navigator();
		
		$c.click(function(e) {
			$c.handle().focus();
		});
	
		$c.handle = function() {
			return scrollable.data("scrollable");
		};
	
		return $c;
	};

	app.browserSupportsHTML5Video = function() {
		if (typeof app.instances.browser.supportsHTML5Video === "undefined") {
			app.instances.browser.supportsHTML5Video = 
					Boolean(document.createElement("video").canPlayType);
		}
		return app.instances.browser.supportsHTML5Video;
	};

	app.video = function($v, options) {
		var video, o;
		
		app.log("app[video]");
		
		if (!app.browserSupportsHTML5Video()) {
			app.log("html5 video not supported", "warn");
		}
		
		o = $.extend({
			useNativeControls: true,
			defaultVolume: 0.85
		});
	
		video = $v[0];
	
		if (typeof video.hasAttribute === "function" &&
				video.hasAttribute("preload")) {
					video.autobuffer = true;
		}
	
		$v.parent().addClass("video-holder");
		$v.append('<span class="notification feature-fallback">\
				Your browser does not support \
				<a href="http://en.wikipedia.org/wiki/HTML5_video">HTML5 video</a>.\
			</span>');
	
		$v.play = function() {
			video.play();
		};
	
		$v.pause = function() {
			video.pause();
		};
	
		$v.canPlay = function() {
			$v.find("source").each(function() {
				if (video.canPlayType(this.type) === "probably" ||
						video.canPlayType(this.type) === "maybe")
							return true;
			});
			return false;
		};
	
		return $v;
	};

	app.topBeam = function(selector, options) {
		var $beam, o, setOpacity;
		
		app.log("app[topBeam]");
		
		o = $.extend({
			fadeOpacity: 0.8,
			offsetThreshold: 5
		}, options);
	
		setOpacity = function() {
			$beam.css({
				"opacity": $(document).scrollTop() > o.offsetThreshold ?
						o.fadeOpacity : 1
			});
		};
	
		$beam = $(selector);
	
		$(document).scroll(function(e) {
			setOpacity();
		});
	
		$beam.mouseover(function(e) {
			$beam.css({
				"opacity": 1
			});
		}).mouseleave(function(e) {
			setOpacity();
		});
		
		$beam.find(".dropdown").each(function() {
			var holder = $(this);
			holder.mouseleave(function(e) {
				holder.removeClass("active").find("ul:first").hide();
			});
		});
		$beam.find(".dropdown > a").each(function() {
			var trigger, holder;
			
			trigger = $(this);
			holder = trigger.parent();
			
			trigger.click(function(e) {
				e.preventDefault();
				holder.toggleClass("active");
				holder.find("ul:first").toggle();
			});
		});
		
		setOpacity();
		return $beam;
	};

	app.searchForm = function(selector, options) {
		var $form, $field, $btn, blurColor, o, setBlurredButtonBG;
		
		app.log("app[searchForm]");
	
		o = $.extend({
			focusColor: "#faffbd",
			submitTriggerSelector: ".btn-wrapper"
		}, options);
	
		setBlurredButtonBG = function() {
			$btn.css({
				"background-color": blurColor
			});
		};
	
		$form = $(selector);
		$field = $form.find("input[type='text']");
		$btn = $form.find(o.submitTriggerSelector);
		blurColor = $field.blur().css("background-color");
	
		$btn.click(function(e) {
			$form.submit();
		});
	
		$field.focus(function(e) {
			$btn.css({
				"background-color": o.focusColor
			});
		}).blur(function(e) {
			setBlurredButtonBG();
		});
		
		setBlurredButtonBG();
		return $form;
	};
		
}(LEV_KANTER, jQuery));

/*------------------------------------------------*/
/*/////////////                      \\\\\\\\\\\\\*/
/*////////////                        \\\\\\\\\\\\*/
/*///////////        Lev Kanter        \\\\\\\\\\\*/
/*//////////                            \\\\\\\\\\*/
/*\\\\\\\\\\                            //////////*/
/*\\\\\\\\\\\   http://levkanter.com   ///////////*/
/*\\\\\\\\\\\\                        ////////////*/
/*\\\\\\\\\\\\\                      /////////////*/
/*------------------------------------------------*/

