/*jslint laxbreak:true */
/*jslint laxcomma:true */
/*jslint loopfunc:true */
/*jslint strict:true */
/*jslint browser:true */
/*jslint devel:true */

// Filename: app.js
define([
	"underscore"
	, "async"
	, "backbone"
	, "jquery"
	, "bootstrap"

	, "config"

	, "views/app"
	, "views/footer"
	, "views/sidebar"
	, "views/player"
	, "views/main"

	, "models/client"
//	, "models/dmap"

	, "collections/server"
	, "collections/playlist"

	, "views/client"
	, "views/list"

	, "text!../templates/app/modal-loading.html"
	, "text!../templates/app/modal-login.html"
	, "text!../templates/app/modal-about.html"
],
function(
_
, async
, Backbone
, $
, Bootstrap

, Config

, AppView
, FooterView
, SideBarView
, PlayerView
, MainView

, ClientModel
//, DMAPModel
, ServerCollection
, PlaylistCollection

, ClientView
, ListView

, tmplModalLoading
, tmplModalLogin
, tmplModalAbout
) {
	"use strict";

	var App		= Backbone.Router.extend({
		routes: {
			"about":					"_routerActionAbout"
			, "playlist":				"_routerActionPlaylist"
			, "servers/:server":		"_routerActionClient"
			, "playlist/:item":			"_routerActionPlaylistItem"
			, ":server/items/:item":	"_routerActionServerItem"
			, "*actions":				"_routerDefaultAction" // matches http://example.com/#anything-here
		}

		, historyStart:	window.history.length

		, playlist:		null

		, servers:		null

		, initialize:	function() {
			_.bindAll(this
				, "_routerActionAbout"
				, "_routerActionPlaylist"
				, "_routerActionClient"
				, "_routerActionItem"
				, "_routerActionServerItem"
				, "_routerDefaultAction"

				, "_serverInit"

				, "__showModalAbout"
			);

			var that	= this
			;

			console.log("app.js::init()");

			// Setup underscore templates with mustache styles
			_.templateSettings.interpolate = /\{\{(.+?)\}\}/g;

			this.servers	= new ServerCollection();

			this.playlist	= new PlaylistCollection();

			this.servers.on("add", function (server) {
				server.save();
			});

			async.waterfall([
				function __asyncAppFetchServerCollection(callback) {
					that.servers.fetch({
						success:	function (collection, modelsAttributes) {
							if (modelsAttributes.length === 0) {
								console.info("Adding default daap server");
								collection.add(Config.daap);
							}

							callback(null, collection);
						}

						, error: callback
					});
				}

				, function __asyncAppAttachStateEvents(servers, callback) {
					async.forEach(that.servers.models, function (server) {
						that._serverInit(server);
					});

					that.servers.on("add", function (server) {
						that._serverInit(server);
					});

					callback(null, servers);
				}
			]
			, function __asyncAppDependenciesReady(err, result) {
				that.Views			= {};

				that.Views.App		= new AppView();

				that.Views.SideBar	= new SideBarView({
					el:			that.Views.App.Layout.panes.west
					, servers:	that.servers
				});

				that.Views.Player	= new PlayerView({
					el:			that.Views.App.Layout.panes.north
				});

				that.Views.Footer	= new FooterView({
					el:			that.Views.App.Layout.panes.south
				});

				that.Views.Main		= new MainView({
					el:			that.Views.App.Layout.panes.center
				});

				that.Views.Playlist		= new ListView({
					collection:		that.playlist
					, type:			"playlist"
				});

				that.Views.Main.setView("playlist", that.Views.Playlist);

				that.View.Main.on("action:item", function __fnAppEventMainViewActionItem (event) {

				});

				that.View.Main.on("action:playorder", function __fnAppEventMainViewActionItem (event) {

				});

				that.Views.Footer.on("toggle:sidebar", function __fnAppEventTogglerSiderBar (event) {
					that.Views.App.toggleSideBar();
					that.Views.Main.resizeView();
				});

				that.Views.Footer.on("toggle:random", function __fnAppEventTogglerRandom (event) {
					// TODO:...
				});

				that.Views.Footer.on("toggle:repeat", function __fnAppEventTogglerRepeater (event) {
					// TODO:...
				});

				that.Views.Footer.on("show:about", that.__showModalAbout);

				that.Views.SideBar.on("add:playlist-item", function __fnAppEventPlaylistAddItem (event) {
					var listItem	= that.servers.get(event.hostname).client.collections.databases[event.dbId].get("dmap_listing").get(event.item).attributes
					;

					delete listItem._id;

					listItem.id	= event.hostname + ":" + event.dbId + ":" + event.item;

					listItem	= _.extend({}, listItem, {
						server:		event.hostname
						, database:	event.dbId
						, order:	new Date().toString()
					});

					that.playlist.on("add", function __fnAppSavePlaylistModel (model) {
						model.save();
					});

					that.playlist.add(listItem);
				});

				that.Views.App.$el.delegate("div.modal", "hidden", function __fnAppEventRemoveModals (event) {
					$(event.target).remove();
				});

				Backbone.history.start({
					pushState: true
					, root: Config.docRoot
				});

				// For now let's reset the state when we start up
				//that.navigate("", false);

				App.__super__.initialize.apply(that, that.routes);
			});

			return this;
		}

		, _routerDefaultAction:			function () {
			var that	= this
			;

			if (!that.servers || that.servers.length === 0) {
				Backbone.Router.prototype.navigate("about", true);
			} else {
				Backbone.Router.prototype.navigate("playlist", true);
			}
		}

		, _routerActionAbout:			function () {
			var that	= this
			;

			that.__showModalAbout();
		}

		, _routerActionPlaylist:		function () {
			var that	= this
			;

			that.Views.SideBar.select("> ul > li:first");
			that.Views.Main.showView("playlist");
		}

		, _routerActionClient:			function (hostname) {
			var that	= this
			,	server	= this.servers.get(hostname)
			,	client	= server && server.client || undefined
			;

			if (server && client) {
				that.Views.SideBar.select(server);
				// FIXME: This needs to take client states into account
				var __fnAppEventClientLoaded		= function () {
					if (!that.Views.Main.getView(server.get("hostname"))) {
						that.Views.Main.setView(server.client.attributes.hostname, new ClientView({
							/*el:			that.Views.App.Layout.panes.center
							, */server:	server
							, appendEl:	that.Views.App.Layout.panes.center
						}));
					}

					that.Views.Main.showView(server.get("hostname"));
				}
				,	__fnAppEventClientInitited	= function () {
					client.fetchDatabases(function __fnAppCbFetchDatabases() {
						client.fetchDatabase(function __fnAppCbFetchDatabase() {
							client.fetchGenres(function __fnAppCbFetchGenres() {
								client.fetchArtists(function __fnAppCbFetchArtists() {
									client.fetchAlbums(function __fnAppCbFetchAlbums() {
										__fnAppEventClientLoaded();
									});
								});
							});
						});
					});
				};

				if (client.state < 4) {
					client.on("inited", __fnAppEventClientInitited);

					if (client.state <= 0) {
						client.init();
					}
				} else if (client.state === 4) {
					__fnAppEventClientInitited();
				} else if (client.state > 4) {
					__fnAppEventClientLoaded();
				}
			}
		}

		, _routerActionPlaylistItem:	function (item) {
			var that	= this
			;

			that.Views.SideBar.select("> ul > li:first");
		}

		, _routerActionServerItem:		function (server, item) {
			var that	= this
			;

			that.Views.SideBar.select(server);
			that.Views.Main.showView(server.get("hostname"));
		}

		, _serverInit:					function(server) {
			var that	= this
			;

			that.loadingStates	= 0;
			that.loadingModal	= $(tmplModalLoading);
			that.loadingTimeout	= null;

			server.client.off("all");

			server.client.on("state", function __fnAppEventClientStateChange(client, state) {
				if (state === ClientModel.defaults._states.loading) {
					if (that.loadingStates === 0) {
						that.loadingTimeout	= setTimeout(function __fnAppTimeoutLoadingStat() {
							that.loadingModal.modal();
							that.loadingTimeout	= null;
						}, 800);
					}

					that.loadingStates++;
				} else if (state === ClientModel.defaults._states.loaded) {
					that.loadingStates--;

					if (that.loadingStates === 0) {
						clearTimeout(that.loadingTimeout);
						if (that.loadingModal.modal) {
							that.loadingModal.modal("hide");
						}
					}
				}
			});

			server.client.on("unauthorized", function __fnAppEventClientUnauthorized(client, xhr) {
				var tmplHtml		= _.template(tmplModalLogin)({ dmap_itemname: client.url() })
				,	serverModel		= that.servers.get(client.attributes.hostname)
				;

				that._modalLogin	= $(tmplHtml);

				that._modalLogin.find("form").on("submit", function __fnAppEventModalLogin(event) {
					var username		= $(event.target).find("input[type='text']").val()
					,	password		= $(event.target).find("input[type='password']").val()
					,	saveCredentials	= $(event.target).find("input[type='checkbox']").is(':checked')
					;

					client.setAuth(username, password);

					if (saveCredentials) {
						var newModel	= (_.clone({}, serverModel.attributes, {username: username, password: password}));

						serverModel.set("username", username, {silent: true});
						serverModel.set("password", password, {silent: true});

						serverModel.save(newModel, {silence: true});
					}

					that._modalLogin.modal("hide");

					setTimeout(client.init, 250);

					event.preventDefault();
				});

				that._modalLogin.delegate("input[type='checkbox']", "click", function __fnEventModalRemember(event) {
					if (event.target.checked === true) {
						if (!confirm("Using this feature will save the login and password locally in clear text, are you sure?")) {
							event.target.checked	= false;
							event.preventDefault();
						}
					}
				});

				setTimeout(function __fnEventAppUnauthorizedDisplayModal() {
					that._modalLogin.modal();
				}, 50);
			});

			server.client.init();
		}

		, __showModalAbout:		function () {
			var that			= this
			;

			that._modalAbout	= $(tmplModalAbout);

			that._modalAbout.on("hidden", function __fnEventAppModalAboutClosed(event) {
				// FIXME: Doesn't seem to work after 50 >_<
				if (window.history.length === 50) {
					window.history.length	= 0;
					that.historyStart		= 1;
				}
				console.log(window.history.length, that.historyStart);
				if (window.history.length === that.historyStart) {
					that.navigate("", false);
				} else {
					window.history.back();
				}
			});

			that._modalAbout.modal();
		}
	});

	return App;
});
