/*jslint laxbreak:true */
/*jslint laxcomma:true */
/*jslint loopfunc:true */
/*jslint strict:true */
/*jslint browser:true */
/*jslint devel:true */
define([
	"underscore"
	, "jquery"
	, "backbone"
	, "bootstrap"

	, "text!../../templates/view-list.html"

	, "jquery-ui"
	, "jquery-event-drag"
	, "jquery-clone-styles"

	, "datatables"
	, "dt-scroller"
	, "dt-tabletools"
	, "dt-colreorder"
]
, function (
_
, $
, Backbone
, Bootstrap

, tmplListView
) {
	"use strict";

	var List	= Backbone.View.extend({
		options:			{
			type:	"playlist"
		}

	, dataTable:			null

	, tableSchemaDefaults:	{

	}

	, tableSchema:			[
		{	// Now playing column
			mData:				null
			, sTitle:			""
			, sDefaultContent:	""
			, bSortable:		false
			, bSearchable:		false
			, sWidth:			"15px"
			, fnCreatedCell:	function(nTd, sData, oData, iRow, iCol) {
				var span	= document.createElement("span");
				nTd.appendChild(span);
			}
		}
		, {
			mData:				"dmap_itemname"
			, sTitle:			"Title"
			, sDefaultContent:	"Unknown"
		}
		, {
			mData:				"daap_songartist"
			, sTitle:			"Artist"
			, sDefaultContent:	"Unknown"
			, aDataSort:		[2, 6, 3, 5, 4]
		}
		, {
			mData:				"daap_songalbum"
			, sTitle:			"Album"
			, sDefaultContent:	"Unknown"
			, aDataSort:		[3, 6, 5, 4]
		}
		, {
			mData:				"daap_songtracknumber"
			, sTitle:			"Track"
			, sClass:			"center"
			, sDefaultContent:	""
			/*, sType:			"numeric"*/
			, sWidth:			"75px"
			, mRender:			function(data, type, full) {
				if (data === "") {
					return "";
				} else if (full.daap_songtrackcount) {
					return data + " of " + full.daap_songtrackcount;
				} else {
					return data;
				}
			}
		}
		, {
			mData:				"daap_songdiscnumber"
			, sTitle:			"Disc"
			, sClass:			"center"
			, sDefaultContent:	"Unknown"
			/*, sType:			"numeric"*/
			, sWidth:			"50px"
			, mRender:			function(data, type, full) {
				if (data === "") {
					return "";
				} else if (full.daap_songdisccount) {
					return data + " of " + full.daap_songdisccount;
				} else {
					return data;
				}
			}
		}
		, {
			mData:				"daap_songyear"
			, sTitle:			"Year"
			, sClass:			"center"
			, sDefaultContent:	""
			, sType:			"numeric"
			, sWidth:			"50px"
		}
		, {
			mData:				"daap_songgenre"
			, sTitle:			"Genre"
			, sClass:			"center"
			, sDefaultContent:	""
			, bVisible:			false
		}
		, {
			mData:				"daap_songtime"
			, sTitle:			"Time"
			, sClass:			"center"
			, sDefaultContent:	""
			/*, sType:			"numeric"*/
			, sWidth:			"75px"
			, bVisible:			true
			, mRender:			function(data, type, full) {
				if (data !== "") {
					return songMSTimeFormat(data);
				} else {
					return data;
				}
			}
		}
		, {
			mData:				"daap_songuserrating"
			, sTitle:			"Rating"
			, sClass:			"center"
			, sType:			"numeric"
			, sDefaultContent:	""
			, bVisible:			false
		}
		, {
			mData:				"dmap_itemid"
			, sTitle:			"ID"
			, sClass:			"center"
			, sDefaultContent:	""
			, bVisible:			false
		}
	]

	, detailsFields:	[
		{
			title:		"Title"
			, field:	"dmap_itemname"
		}
		, {
			title:		"Artist"
			, field:	"daap_songartist"
		}
		, {
			title:		"Album"
			, field:	"daap_songalbum"
		}
		, {
			title:		"Composer"
			, field:	"daap_songcomposer"
		}
		, {
			title:		"Genre"
			, field:	"daap_songgenre"
		}
		, {
			title:		"Track Number"
			, field:	"daap_songtracknumber"
			, render:	function(data, full) {
				var value	= data;

				if (data === "") {
					value	= "Unknown";
				}

				if (typeof full.daap_songtrackcount !== "undefined") {
					value	+= " of " + full.daap_songtrackcount;
				}

				return value;
			}
		}
		, {
			title:		"Disc Number"
			, field:	"daap_songdiscnumber"
			, render:	function(data, full) {
				var value	= data;

				if (typeof full.daap_songdisccount !== "undefined") {
					value	+= " of " + full.daap_songdisccount;
				}

				return value;
			}
		}
		, {
			title:		"Year"
			, field:	"daap_songyear"
		}
		, {
			title:		"Rating"
			, field:	"daap_songuserrating"
		}
		, {
			title:		"Compilation"
			, field:	"daap_songcompilation"
			, defaults:	"No"
			, render:	function (data, full) {
				return (data == 1 ? "Yes" : "No");
			}
		}
		, {
			title:		"Duration"
			, field:	"daap_songtime"
			, render:	function (data, full) {
				return songMSTimeFormat(data);
			}
		}
		, {
			title:		"BPM"
			, field:	"daap_songbeatsperminute"
		}
		, {
			title:		"Bit Rate"
			, field:	"daap_songbitrate"
			, render:	function (data, full) {
				if (data > 0) {
					data += "kbps";
				}

				return data;
			}
		}
		, {
			title:		"Sample Rate"
			, field:	"daap_songsamplerate"
			, render:	function (data, full) {
				if (data !== "") {
					if (data > 1000) {
						data = (data / 1000) + "k";
					}

					data += "Hz";
				}

				return data;
			}
		}
		, {
			title:		"Date added"
			, field:	"daap_songdateadded"
		}
	]

	, tableSort:	[]

		, initialize:	function (options) {
			_.bindAll(this
				, "resize"
				, "render"
				, "show"
				, "hide"
			);

			var that	= this
			;

			if (options && options.el) {
				$(options.el).html(tmplListView);
			} else {
				options					= options || {};
				options.el				= document.createElement("div");

				options.el.id			= "__view-playlist";
				options.el.className	= "playlist-view-container";

				$(options.el).html(tmplListView);

				this.el					= options.el;
				this.$el				= $(this.el);
			}

			List.__super__.initialize.apply(this, arguments);

			if (that.options.type === "playlist" && that.options.collection) {
				that.options.collection.fetch();
				that.options.collection.on("add", function __fnPlaylistAddRow(model) {
					if (that.dataTable) {
						that.dataTable.fnAddData(model.toJSON(), that.$el.is(":visible"));
					}
				});
			}

			return this;
		}

		// FIXME: Sometimes the parent element's size is 0 and resizing fails.
		, resize:		function () {
			var that			= this
			,	parentEl		= that.options.parentEl || that.$el.parent()
			,	parentWidth		= parentEl.innerWidth()
			,	parentHeight	= parentEl.innerHeight()
			;
console.log(parentWidth, that.$el.innerWidth(), parentHeight, that.$el, parentEl);
			that.$el.find(".dataTables_scrollBody").height(that.$el.innerHeight() - 20);
			that.$el.width(parentWidth);
			that.$el.find(".dataTables_wrapper").width(parentWidth);
			that.$el.find(".dataTables_scrollBody").width(parentWidth);
			that.$el.find(".dataTables_scroll").width(parentWidth);
			that.$el.find(".dataTables_scrollHeadInner").width(parentWidth);
			that.$el.find(".dataTables_scrollHeadInner table").width(parentWidth);
			that.$el.parent().find("span[resizer='north']").width(parentWidth);
		}

		, render:		function () {
			var that			= this
			,	initialHeight	= that.$el.innerHeight() - 20
			,	dataTableOpts	= {
				sScrollY:			initialHeight + "px"
				, sDom:				"RTrtS"
				, oColReorder:		{
					iFixedColumns:	1
				}
				, bInfo:			false
				, bLengthChange:	false
				, bAutoWidth:		false
				, bFilter:			true
				, bDeferRender:		true
				, bStateSave:		false//true
				, bScrollCollapse:	true
				, bJQueryUI:		true
				, sHeightMatch:		"auto"
				, sEmptyTable:		""
				//, bProcessing:		true
				//, bServerSide:		true

				, aaData:			that.collection.toJSON()

				, aoColumns:		that.tableSchema

				, oTableTools:		{
					sRowSelect:			"single"
					, sSelectedClass:	"selected"
					, aButtons:			[]
				}

				, fnCreatedRow: function(nRow, aData, iDataIndex) {
					if (that.options.type !== "playlist") {
						$(nRow).draggable({
							scope:				"list-item"
							, stack:			"droppable"
							, cursor:			"copy"
							, revert:			"invalid"
							, containment:		"window"
							, revertDuration:	200
							, scroll:			false

							, start: function(event, ui) {
								$(this).fadeTo("fast", 0.5);
							}

							, stop: function(event, ui) {
								$(this).fadeTo(0, 1);
							}

							, helper:	function (event) {
								var dragEl	= $('<div class="drag-table-item"><table></table></div>')
										.find("table")
										.append(
											$(this)
											.closest("tr")
											.clone()
											//.css($(this).getStyleObject())
											.addClass("selected")
										)
										.parent()
								;

								//console.debug("Extracting draggable", this, dragEl);
								return dragEl.prependTo('body').css('zIndex',10000).show();
								//return dragEl
								//		.appendTo("body")
								//		.css("zIndex", "5000")
								//		.show();
							}
						})
						.data("hostname",	that.options.client.hostname)
						.data("dbId",		that.options.client.dbId)
						.data("item",		aData.id)
						;
					}
					// create a view for the row
					//var rowModel = that.collection.get(aData.id);
					//view.rows.push(new DtRowView({id: aData.id, el: nRow, model: rowModel}));
				}

				, fnServerData: function(sSource, aoData, fnCallback, settings) {
					console.log(sSource, aoData, fnCallback, settings);
				}
/*
					// function used to populate the DataTable with the current
					// content of the collection
					var populateTable = function()
					{
					// clear out old row views
					var rows = [];

					// these 'meta' attributes are set by the collection's parse method
					var totalSize = that.collection.meta('totalSize');
					var filteredSize = that.collection.meta('filteredSize');

					return fnCallback({iTotalRecords: totalSize,
						iTotalDisplayRecords: filteredSize,
						aaData: that.collection.toJSON()});
					};

					aoData.shift(); // ignore sEcho
					var params = $.param(aoData);

					if (params != that.constraint)
					{
						// trigger param:change event with new parameters. Pass in
						// populateTable function so fnCallback can be called after
						// the data has been refreshed. Note that we cannot just call
						// <a href="/ref#fnDraw">fnDraw</a> on the collection reset event since closure state
						// in the fnCallback passed to this method would be lost.
						that.trigger("param:change", params, populateTable);
					}
					else
					{
						// no filter change, just populate the table
						populateTable();
					}
				}
 */
			}
			;

			// Default sorting order
			if (that.options.type !== "playlist") {
				dataTableOpts.aaSorting		= [[2, "asc"], [6, "asc"], [3, "asc"], [5, "asc"], [4, "asc"]];
			} else {
				var schemaLastItem			= (that.tableSchema.length - 1);
				dataTableOpts.aaSorting		= [[schemaLastItem, "asc"]];
				that.tableSchema[schemaLastItem].mData	= "order";

				for (var i = 0; i < schemaLastItem; i++) {
					that.tableSchema[i].bSortable	= false;
				}

				dataTableOpts.aoColumns		= that.tableSchema;
			}

			this.dataTable	= this.$el.find("table:first").dataTable(dataTableOpts);

		}

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

			if (!that.dataTable) {
				that.render();
			}

			that.$el.show();

			that.dataTable.fnDraw();

			that.resize();
		}

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

			this.$el.hide();
		}
	});

	return List;
});