(function() {

	var S = new App.make("Sprockits")
		, Libs = ["XHR", "DOMEvents"]
		, Applications = []
		, doc = window.document
		, head = doc.getElementsByTagName("head")[0]
		, body = doc.body
		, baseURL;

/*  */
	S.makeAction("config", function(){
		baseURL = (this.event[0] || "") + "Sprockits/";
		this.set("baseURL", baseURL);
		this.step();
	});

	S.set("_lib", Libs);

	S.makeAction("_lib", function(){
		var that = this
			, node = that[0]
			, libURL = baseURL + "_lib/"
			, lib = node._lib
			, length = lib.length
			, curLib = 0
			, xhr = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP")
			, scripts = ""
			, callback;

		that.make(that.event.euid, function(){
			var script = document.getElementById(that.event.euid);
			script.parentNode.removeChild(script);
			that.set("_lib", "loaded");
			for(var x = 0; x < length; x++){ that.require(lib[x]) }
			that.step();
			this.remove()
		});

		xhr.open("GET", libURL + lib[curLib] + ".js",true);
		callback = function(){
			if(this.readyState==4 && this.status==200){
				scripts += this.responseText + ";";
				curLib += 1;
				if(curLib < length){
					var newXhr = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
					newXhr.open("GET", libURL + lib[curLib] + ".js",true);
					newXhr.onreadystatechange = function(){ callback.call(newXhr) }
					newXhr.send()
				}else{
					var newScript = document.createElement("SCRIPT");
					newScript.setAttribute("id",that.event.euid);
					newScript.text = scripts + "App.get('Sprockits').get('" + that.event.euid + "').trigger();";

					document.body.appendChild(newScript)
				}
			}
		}
		xhr.onreadystatechange = function(){ callback.call(xhr) };
		xhr.send()

	});

	S.makeAction("required", function(){ if(Applications.length > 0) for(var x = 0; x < Applications.length; x++){ S.get("new").trigger(Applications[x]) } });

	S.setType("application", ["config", "_lib", "required"]);
/*  */


/*  */
	S.makeAction("init", function(){
		var app = this.event[0], that = this, baseURL = that[that.length-1].baseURL;

		app.set("baseURL", baseURL);

		that.step()

	});

	S.makeAction("getBlueprint", function(){
		var app = this.event[0], that = this;

		S.get("XHR").trigger("GET", baseURL + app.path[0] + "/blueprint.json", function(){
			var blueprint;
			try { blueprint = JSON.parse(this.responseText) } catch(err) { return false }
			app.set(blueprint);
			that.step();
		});
	});

	S.makeAction("getLogic", function(){
		var node = this.event[0], path = node.path, that = this;

		if(node[0].logic !== "defer"){
			that.step();
			return false;
		}

		that.make(that.event.euid, function(){
			that.step();
			this.remove();
		});

		S.get("XHR").trigger("GET", baseURL + path.join("/") + "/logic.js", function(){
			var script = document.createElement("script");
			script.text = "App.select(" + JSON.stringify(path) + ").set('logic',function(){" + this.responseText + "});App.select(" + JSON.stringify(that.get(that.event.euid).path) + ").trigger();";
			body.appendChild(script);
		})
	});

	S.makeAction("addActions", function(){
		var app = this.event[0];

		app.makeAction("getBlueprint", function(){
			var that = this, path = that.path;

			S.get("XHR").trigger("GET", baseURL + path.join("/") + "/blueprint.json", function(){
				var blueprint;
				try { blueprint = JSON.parse(this.responseText) } catch(err) { return false }
				if(!blueprint.type || blueprint.type === "defer") blueprint.type = "command";
				that.set(blueprint);
				that.step()
			})
		});

		app.makeAction("getTemplate", function(){
			var that = this, path = that.path, tmplEl = doc.createElement("script");

			tmplEl.setAttribute("type", "tex/html");

			if(that[0].template === "defer") S.get("XHR").trigger("GET", baseURL + path.join("/") + "/template.html", function(){
				tmplEl.text = this.responseText;

				that[0].template = tmplEl;
				head.appendChild(tmplEl);

				that.step()
			});
			else if(typeof that[0].template === "string"){
				tmplEl.text = that[0].template;

				that[0].template = tmplEl;
				head.appendChild(tmplEl);

				that.step()
			} else that.step();
		});

		app.makeAction("getStyle", function(){
			var that = this, path = that.path, style;

			if(that[0].style === "defer"){
				style = doc.createElement("LINK");
				style.setAttribute("href", baseURL + path.join("/") + "/style.css");
				style.setAttribute("rel", "stylesheet");
				style.setAttribute("type", "text/css");
				that[0].style = style;
				head.appendChild(style)
			}

			that.step()
		});

		app.makeAction("getLogic", function(){
			var that = this, path = that.path;

			if(that[0].logic !== "defer"){
				that.step();
				return true
			}

			that.make(that.event.euid, function(){
				that.step();
				this.remove()
			});

			S.get("XHR").trigger("GET", baseURL + path.join("/") + "/logic.js", function(){
				var script = document.createElement("script");
				script.text = "App.select(" + JSON.stringify(path) + ").set('logic',function(){" + this.responseText + "});App.select(" + JSON.stringify(that.get(that.event.euid).path) + ").trigger();";
				body.appendChild(script)
			})
		});

		app.makeAction("block", function(){
			var that = this
				, node = that[0]
				, path = that.path
				, block = node.block
				, target, tmpEl, template;

			if(typeof block === "object" && typeof block.target === "string"){
				target = ((target = block.target) && target.charAt(0) === "#") ? doc.getElementById(target.split("#")[1]) : doc.getElementsByTagName(target)[0];
				template = node.template;

				if(target){
					tmpEl = doc.createElement("span");
					tmpEl.innerHTML = template.text;

					for(var x = 0; x < tmpEl.childNodes.length; x++){
						target.appendChild(tmpEl.childNodes[x]);
					}
					tmpEl = null;
				}

			}

			that.step();
		});

		app.makeAction("loop", function(){
			var that = this;
			that.trigger();
			this.step()
		});

		this.step()
	});

	S.makeAction("addTypes", function(){
		var app = this.event[0];
		app.makeType("defer", ["getBlueprint", "loop"]);
		app.makeType("frozen", []);
		app.setType("command", ["getStyle", "getTemplate", "getLogic", "block", "logic"]);
		this.step()
	});

	S.makeAction("extend", function(){
		var app = this.event[0], pathName = (window.location.href).split("/");

		pathName.pop();
		pathName = pathName.join("/") + "/";

		S.get("addListener").trigger("click", body, function(e){
			var e = e || window.event, t = e.srcElement || e.target, path, node;

			while(t.nodeName !== "A" && t.nodeName !== "BODY" && t.parentNode){ t = t.parentNode; }

			if(t && t.nodeName === "A") {
				path = t.getAttribute("href").split(pathName).pop();
				node = app.select(path);
				if(!node) return true;
				e.preventDefault ? e.preventDefault() : e.returnValue = false;
				e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true;
				node.trigger(e,t)
			}
		});

		this.step()
	});

	S.makeAction("execute", function(){
		var app = this.event[0];
		app.trigger();
		this.step()
	});

	S.makeType("Sprockits_App", ["init", "getBlueprint", "getLogic", "addActions", "addTypes", "extend", "execute"]);
/* */

	S.make("new", "Sprockits_App");

	S.make("require", function(app){
		if(S[0]._lib === "loaded") S.get("new").trigger(app); else Applications.push(app);
	})

})()

