/*
 * Copyright (c) 2012-2015 Kaarle Ritvanen
 * See LICENSE file for license details
 */

define(
    [
	"aconf/blocking",
	"aconf/dom",
	"aconf/error",
	"aconf/navigation",
	"aconf/path",
	"aconf/statusbar",
	"aconf/transaction",
	"aconf/type",
	"aconf/widget/inline",
	"jquery",
	"underscore",
	"aconf/layout/stacked",
	"aconf/layout/tabular",
	"domReady"
    ],
    function(
	blocking,
	dom,
	formatError,
	navi,
	pth,
	statusBar,
	txnMgr,
	type,
	Inline,
	$,
	_
    ) {
	return function() {
	    $("#login").submit(function() {

		$.ajax("/login", {
		    type: "POST",
		    data: JSON.stringify({
			username: $("#username").val(),
			password: $("#password").val()
		    })
		}).done(function(data, status, xhr) {
		    
		    txnMgr = txnMgr(
			xhr.getResponseHeader("X-AConf-Auth-Token"),
			xhr.getResponseHeader("X-AConf-Save-Required") == "1"
		    );


		    var objPath;

		    function renderObject(path, data) {
			if (path) objPath = path;

			return (
			    data ? $.Deferred().resolve(data) :
				txnMgr.query(objPath)
			).done(function(data) {
			    var layout = data.meta.widget;
			    var name = pth.split(objPath).pop();
			    (layout ?
			     require("aconf/layout/" + layout) :
			     Inline).extend({
				 createEl: function() {
				     return $("#content").empty();
				 },
				 wrap: function() { return this.el; },
				 requestData: function(value, meta) {
				     return $.Deferred()
					 .resolve(data, data.meta);
				 }
			     }).new(
				 {
				     get: function(name) { return objPath; },
				     status: function(name) { return null; },
				     match: function(filter) { return true; }
				 },
				 name,
				 {},
				 0,
				 true,
				 false
			     );
			}).fail(function() {
			    var comps = pth.split(objPath);
			    comps.pop();
			    comps.unshift("/");
			    navi.setPath(pth.join.apply(undefined, comps));
			});
		    };

		    $("#content").on("reload", function(event, txnValid) {
			statusBar.validationReady(txnValid);
			renderObject();
			event.stopPropagation();
		    });


		    function render() {
			var path = navi.getPath();

			function renderMenu(
			    target, path, current, selectFirst
			) {
			    var def = $.Deferred();

			    txnMgr.query(path).done(function(data) {
				if (data.meta.type != "model") {
				    def.reject(data);
				    return;
				}

				var tnFields = [];
				var extraFields = false;

				_.each(data.meta.fields, function(field) {
				    if (!field.visible) return;

				    if (!type.isTreeNode(field))
					extraFields = true;
				    else if (data.data[field.name])
					tnFields.push(field);
				});

				if (!tnFields.length) {
				    def.reject(data);
				    return;
				}

				function addItem(
				    path, ui_name, status, current
				) {
				    var el = $("<li>").html(
					dom.objectRef(path).text(ui_name)
				    );
				    dom.setStatus(el, status);
				    if (current) el.addClass("current");
				    target.append(el);
				}

				if (extraFields) {
				    addItem(path, "General", null, !current);
				    selectFirst = false;
				}

				_.each(tnFields, function(field, i) {
				    addItem(
					data.get(field.name),
					field["ui-name"],
					data.status(field.name),
					current == field.name || (
					    !current && !i && selectFirst
					)
				    );
				    field.visible = false;
				});

				def.resolve(
				    extraFields ? data : tnFields[0].name
				);
			    });

			    return def;
			}


			if (path > "/") $("#content").text("Loading...");

			txnMgr.start().done(function() {
			    var comps = pth.split(path);
			    renderMenu(
				$("#modules").empty(), "/", comps[0], false
			    );
			    var tabs = $("#tabs").empty();

			    if (path == "/") return;

			    function renderTabs(p) {
				p = pth.join(p, comps.shift());
				renderMenu(tabs, p, comps[0], true)
				    .done(function(data) {
					var tabLevel = !comps.length;
					renderObject(
					    (
						tabLevel && _.isString(data)
					    ) ? pth.join(p, data) : path,
					    tabLevel && _.isObject(data) ?
						data : null
					);
				    })
				    .fail(function(data) {
					if (comps.length) renderTabs(p);
					else renderObject(p, data);
				    });
			    }
			    renderTabs("/");
			});
		    }

		    
		    function clearState() {
			statusBar.reset();
			render();
			blocking.disable();
		    }
		    
		    $("#commit").click(function() {
			blocking.enable();
			txnMgr.commit().done(clearState).fail(function(xhr) {
			    statusBar.setError(
				formatError("Commit failed", xhr), "txn"
			    );
			})
		    });
		    $("#revert").click(function() {
			blocking.enable();
			txnMgr.abort();
			clearState();
		    });
		    
		    $("#logout").click(function() {
			txnMgr.logout().done(function() {
			    $("body").html($("<p>").text("Logged out"));
			});
		    });
		    
		    statusBar.reset();
		    $("#content").empty();

		    $(window).bind("hashchange", function() {
			if (!blocking.isEnabled()) render();
		    });
		    navi.setPath("/");

		}).fail(function() {
		    statusBar.setError("Login failed", "login");
		});

		return false;
	    });

	    $("#username").focus();
	}
    }
);
