
function copyPrototype(descendant, parent) {
    var sConstructor = parent.toString();
    var aMatch = sConstructor.match( /\s*function (.*)\(/ );
    if ( aMatch != null ) { descendant.prototype[aMatch[1]] = parent; }
    for (var m in parent.prototype) {
        descendant.prototype[m] = parent.prototype[m];
    }
};

Function.prototype.bind = function(obj) {
  var method = this,
   temp = function() {
    return method.apply(obj, arguments);
   };
 
  return temp;
}

Function.prototype.bindWithAdditionalArgs = function(obj,moreArgs) {
	  var method = this,
	   temp = function() {
		var j,i=0;
		var newArgs = new Array();
		while (i<arguments.length) {
			newArgs[i] = arguments[i];
			i++;
		}
		for (j=0;j<moreArgs.length;j++) newArgs[i++] = moreArgs[j];
//		console.log(newArgs);
	    return method.apply(obj, newArgs);
	   };
	 
	  return temp;
	}

var trackRowFormatter = function(elTr, oRecord) { 
    if (oRecord.getData('listened')) { 
    	//console.log("marking listened ",elTr);
    	YAHOO.util.Dom.addClass(elTr, 'listened-track'); 
    }
    if (!oRecord.getData('nominatable')) {
    	//console.log("marking nominatable ",elTr);
    	YAHOO.util.Dom.addClass(elTr, 'unnominatable-track'); 
    	//YAHOO.util.Dom.addClass(elTr, 'unselectable-row'); 
    }
    if (oRecord.getData('nomcount') > 0) {
    	YAHOO.util.Dom.addClass(elTr, 'nominated-row'); 
    }
    return true; 
};  
/*
initialTrackData = {
	meta: { totalRecords:4 },
	results: [
		{pk:1, tracknum:1, title:"Track 1", album: "Some album", artist:"Artist name", nomcount:0, listened:false, nominatable:true}, 
		{pk:2, tracknum:2, title:"Track 2", album: "Some album", artist:"Artist name", nomcount:0, listened:false, nominatable:true}, 
		{pk:3, tracknum:3, title:"Track 3", album: "Some album", artist:"Artist name", nomcount:0, listened:false, nominatable:true}, 
		{pk:4, tracknum:4, title:"Track 4", album: "Some album", artist:"Artist name", nomcount:0, listened:false, nominatable:true}
	],
	tId: 0
};
*/
create_list = function(elmID,sourceURL,initialSort,initialSortDir,itemsPerPage,columnDefs,responseSchema,startIndex,dynamic) {
    // Custom parser
	if (dynamic == undefined) dynamic = true;
    var stringToDate = function(sData) {
        var array = sData.split("-");
        return new Date(array[1] + " " + array[0] + ", " + array[2]);
    };
    
    // DataSource instance
    var myDataSource = new YAHOO.util.DataSource(sourceURL);
    myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
    myDataSource.responseSchema = responseSchema;

    myDataSource.old_makeConnection = myDataSource.makeConnection;
    myDataSource.originalURL = sourceURL;
    myDataSource.initialRequest = true;
    myDataSource.makeConnection = function( oRequest , oCallback , oCaller ) {
    	if (this.initialRequest) {
    		this.initialRequest = false;
    		YAHOO.util.DataSourceBase.issueCallback(oCallback,[oRequest,initialTrackData],undefined,oCaller);
    	    return 0;
    	} else
    		return this.old_makeConnection(oRequest,oCallback,oCaller);
    }

    if (!startIndex)
    	startIndex = 0;
    
    requestStr = "sort="+initialSort+"&dir=asc&startIndex="+startIndex;
    if (itemsPerPage > 0) 
    	requestStr = requestStr + "&results="+itemsPerPage;
    else
    	requestStr = requestStr + "&results=10000";

    initialSortDirToken = YAHOO.widget.DataTable.CLASS_ASC;
    if (initialSortDir != 'asc') initialSortDirToken = YAHOO.widget.DataTable.CLASS_DESC;
    
    // DataTable configuration
    var myConfigs = {
        initialRequest: requestStr, // Initial request for first page of data
        dynamicData: dynamic, // Enables dynamic server-driven data
        sortedBy : {key:initialSort, dir:initialSortDirToken}, // Sets UI initial sort arrow
    };

    if (dynamic) {
       myConfigs['formatRow'] = trackRowFormatter;
    }

    initialPageNum = 1
    if (itemsPerPage > 0) {
    	initialPageNum = Math.round(startIndex / itemsPerPage)+1;
    	myConfigs.paginator = new YAHOO.widget.Paginator({ 
    		rowsPerPage:itemsPerPage, 
    		initialPage:initialPageNum,
    		totalRecords:initialTrackData['meta']['totalRecords'] }); // Enables pagination 
    }
    
    // DataTable instance
    var myDataTable = new YAHOO.widget.DataTable(elmID, columnDefs, myDataSource, myConfigs);
    // Update totalRecords on the fly with value from server
    myDataTable.handleDataReturnPayload = function(oRequest, oResponse, oPayload) {
        oPayload.totalRecords = oResponse.meta.totalRecords;
        return oPayload;
    }

    var o = new Object();
    o.ds = myDataSource;
    o.dt = myDataTable;
    o.paginator = myConfigs.paginator;
    return o;
/*
    return {
        ds: myDataSource,
        dt: myDataTable
    };      
*/
};

track_row_selected = function(elm) {
	this.overlay.hide();
	this.overlay.setBody("");

//	console.log('/tracks/'+elm.record.getId()+'/inline/');
//	console.log(dumpObj(elm.record,'','',9));

	if (elm.el != this.currentElm) {
		this.overlay.cfg.setProperty("context", [elm.el, "tl", "bl"]);
        var tmphght1 = document.defaultView.getComputedStyle(elm.el, "").getPropertyValue("width");
        tmphght1 = tmphght1.split('px')
        tmphght1 = Number(tmphght1[0]);
        tmphght = Math.floor(tmphght1);
        tmphght = tmphght-9;
        if (tmphght < 600) tmphght = 600;
        this.overlay.cfg.setProperty("width",tmphght+"px");
        this.overlay.cfg.setProperty('zIndex',1);
        this.overlay.setBody("Loading...");
	    this.overlay.render(document.body);
        this.overlay.show();
		
        url = '/tracks/'+elm.record.getData().pk+'/inline/?width='+tmphght;
        if (this.forJudge) url = url + "&forJudge=true";
        	
		AjaxRequest.get(
				  {
				    'url':url
					,'foo':this.overlay
				    ,'onSuccess':function(req){ 
						  req.parameters.foo.setBody(req.responseText);
						  req.parameters.foo.render(document.body);
						  //req.parameters.foo.show();
					      //alert('Success! '); 
					}
				    ,'onError':function(req){ 
				    	//console.log('Error!\nStatusText='+req.statusText+'\nContents='+req.responseText);
					    }
					  }
				);
		this.currentElm = elm.el;
	} else {
		this.currentElm = null;
	}
		
}


function ItemList(idPrefix,list) {
	this.dt = list.dt;
	this.ds = list.ds;
	this.paginator = list.paginator;
	this.name = idPrefix;
	
	this.overlay = new YAHOO.widget.Overlay("list_overlay", { visible:false } );
	this.overlay.setBody("Hello!");
    this.overlay.render(document.body);

    this.currentElm = null;

    this.dt.subscribe("rowClickEvent", this.row_click.bind(this)); 
    
    var boundClose = this.closeOverlay.bind(this);
    this.dt.subscribe("paginatorChange", boundClose);
    this.dt.subscribe("columnResizeEvent", boundClose);
    this.dt.subscribe("renderEvent", boundClose);
}

ItemList.prototype.row_click = function(a,b,c) {
	if (a.target.className.indexOf('unselectable-row') != -1) return;
	this.dt.onEventSelectRow(a,b,c);
}

ItemList.prototype.stopSpinners = function() {
	var e;
	e = document.getElementById('left_spinner');
	if (!e) e = document.getElementById('left_spinner_'+this.name);
	if (e) e.style.visibility = 'hidden';
	e = document.getElementById('right_spinner');
	if (!e) e = document.getElementById('right_spinner_'+this.name);
	if (e) e.style.visibility = 'hidden';
}

ItemList.prototype.startSpinners = function() {
	var e;
	e = document.getElementById('left_spinner');
	if (!e) e = document.getElementById('left_spinner_'+this.name);
	if (e) e.style.visibility = 'visible';
	e = document.getElementById('right_spinner');
	if (!e) e = document.getElementById('right_spinner_'+this.name);
	if (e) e.style.visibility = 'visible';
}

ItemList.prototype.closeOverlay = function() {
	//console.log('foo');
	this.overlay.hide();
	this.overlay.setBody("");
    this.currentElm = null;
    this.dt.unselectAllRows();
}

ItemList.prototype.reload_succeeded = function(a,b,c,d) {
	/*
	totalRecords = b.meta.totalRecords;
	if ((c.pagination.recordOffset + c.pagination.rowsPerPage) > totalRecords) {
		newPageNum = Math.floor(c.pagination.totalRecords / c.pagination.rowsPerPage) + 1;
		c.pagination.page = newPageNum;
		c.pagination.recordOffset = (newPageNum-1)*c.pagination.rowsPerPage;
	}
	*/
	this.dt.deleteRows(0,100000);
	this.dt._oRecordSet.deleteRecords(0, 100000);
	this.dt.onDataReturnSetRows(a,b,c);	
	this.dt.render();
	this.stopSpinners();
}

ItemList.prototype.reload = function() {
	this.startSpinners();

	this.ds.flushCache();
    var oState = this.dt.getState();
    var request = this.dt.get("generateRequest")(oState, this);
    
    // Get the new data from the server
    var callback = {
        success : this.reload_succeeded, //this.dt.onDataReturnSetRows,
        failure : this.reload_succeeded,
        argument : oState, // Pass along the new state to the callback
        scope : this
    };
    this.dt._oDataSource.sendRequest(request, callback);
}

var trackColumnDefs = [
	 {key:"title", label:"Title", sortable:true,resizeable:true},
	 {key:"album", label:"Album", sortable:true,resizeable:true},
	 {key:"artist", label:"Artist", sortable:true,resizeable:true},
	 {key:"nomcount", label:"Nominations", sortable:false,resizeable:false}
];

changeRank = function(e,table,record,col,delta) {
	var rs = table.dt.getRecordSet();
	var numRecords = rs.getLength();
	var newRank;
	var index = record.getData("rank");
	if (index == '?') index = record._nCount;

	newRankings = new Array(numRecords);

    url = '/judge/submitRankings/'+table.listType+'/?for_award='+table.for_award;
	for (var i=0;i<numRecords;i++) {
		rec = table.dt.getRecord(i);
		newRank = i;
		if (i == index) {
			newRank+=delta;
		} else if (i == (index+delta)) {
			newRank-=delta;
		}
		newRankings[i] = newRank;
		url += '&'+table.listType+rec.getData('pk')+'='+newRank;
	}

	table.startSpinners();
	AjaxRequest.get(
			  {
			    'url':url
				,'table':table
				,'newRankings':newRankings
			    ,'onSuccess':function(req){
					var table = req.parameters.table;
					table.stopSpinners();
					var rs = table.dt.getRecordSet();
					var numRecords = rs.getLength();
					for (var i=0;i<numRecords;i++) {
						rec = table.dt.getRecord(i);
						table.dt.updateCell(rec,col,req.parameters.newRankings[i]);
					}
					table.dt.sortColumn(col,YAHOO.widget.DataTable.CLASS_ASC);
			  	}
			    ,'onError':function(req){ 
					var table = req.parameters.table;
					table.stopSpinners();
			    	alert('There was a problem sending your new rankings to the server.'); 
			    	//console.log(req);
			    }
			  }
			);

	e.stopPropagation();
}

rankUpDownFormatter = function(elCell, oRecord, oColumn, oData) { 
	if (this.dt == undefined) return;
	contents = ""
	rank = oRecord.getData('rank');
	var upLink = document.createElement("a");
	var ranking = document.createElement("span");
	var displayRank = rank;
	if (rank != '?') displayRank = rank+1;
	var order = this.dt.getRecordSet().getRecordIndex(oRecord);
	ranking.innerHTML = "<span style='font-weight:bold;'>"+displayRank+"</span>";
	var downLink = document.createElement("a");
	if (order == 0) upLink.style.visibility = "hidden";
	if (order == this.dt.getRecordSet().getLength()-1) downLink.style.visibility = "hidden";
	upLink.innerHTML = '<img style="padding-left:2px;padding-right:5px;" src="/media/images/expando-up.gif">';
	downLink.innerHTML = '<img style="padding-left:5px;padding-right:2px;" src="/media/images/expando-down.gif">';
	elCell.innerHTML = '';
	elCell.appendChild(upLink);
	elCell.appendChild(ranking);
	elCell.appendChild(downLink);
	upLink.onclick = changeRank.bindWithAdditionalArgs(upLink,[this,oRecord,oColumn,-1]);
	downLink.onclick = changeRank.bindWithAdditionalArgs(downLink,[this,oRecord,oColumn,1]);
}; 
YAHOO.widget.DataTable.Formatter.rankUpDownFormatter = rankUpDownFormatter;

var trackOfAlbumColumnDefs = [
   	 {key:"tracknum", label:"#", sortable:false,resizeable:false},
   	 {key:"title", label:"Title", sortable:false,resizeable:false},
];

var trackResponseSchema = {
	resultsList: "records",
	fields: [
	         {key:"pk", parser:"number"},
	         {key:"tracknum"},
	         {key:"title"},
	         {key:"album"},
	         {key:"artist"},
	         {key:"nomcount"},
	         {key:"listened"},
	         {key:"nominatable"},
	         {key:"player"},
	         {key:"rank"},
	],
	metaFields: {
		totalRecords: "totalRecords" // Access to value in the server response
	}
};

var albumNomColumnDefs = [
   	 {key:"title", label:"Title", sortable:true,resizeable:true},
   	 {key:"artist", label:"Artist", sortable:true,resizeable:true},
//   	 {key:"nomcount", label:"Nominations", sortable:true,resizeable:true}
];

var albumNomResponseSchema = {
	resultsList: "records",
	fields: [
	    {key:"pk", parser:"number"},
	    {key:"title"},
	    {key:"artist"},
        {key:"nomcount"},
	    {key:"listened"},
        {key:"nominatable"},
	],
	metaFields: {
		totalRecords: "totalRecords" // Access to value in the server response
    }
};

var albumColumnDefs = [
    {key:"title", label:"Title", sortable:true,resizeable:true},
    {key:"artist", label:"Artist", sortable:true,resizeable:true},
];

var albumResponseSchema = {
	resultsList: "records",
	fields: [
	    {key:"pk", parser:"number"},
	    {key:"title"},
	    {key:"artist"},
	    {key:"nomcount"},
	    {key:"listened"},
        {key:"nominatable"},
        {key:"rank"},
	],
	metaFields: {
	    totalRecords: "totalRecords" // Access to value in the server response
	}
};

function TrackNominationList(elmID,itemsPerPage,startIndex,initialSort,initialSortDir,additionalQueries) {
	query = "/tracks/trackdata/?status=A&listName="+elmID+"&";
	if (additionalQueries) query = query + additionalQueries+"&";
	var list = create_list(elmID,query,initialSort,initialSortDir,itemsPerPage,trackColumnDefs,trackResponseSchema,startIndex);
	this.ItemList(elmID,list);
    this.row_selected = track_row_selected;
    this.dt.subscribe("rowSelectEvent", this.row_selected.bind(this));
}
copyPrototype(TrackNominationList,ItemList);

function TrackOfAlbumList(elmID,albumID,forJudging) {
	if (forJudging == undefined) forJudging = false;
	var list = create_list(elmID,"/tracks/trackdata/?album="+albumID+"&listName="+elmID+"&listened=all&nominated=all&","tracknum","asc",0,trackOfAlbumColumnDefs,trackResponseSchema,0,!forJudging);
	this.ItemList(elmID,list);
    this.row_selected = track_row_selected;
    this.forJudge = forJudging;
    this.dt.subscribe("rowSelectEvent", this.row_selected.bind(this));
}
copyPrototype(TrackOfAlbumList,ItemList);

function TrackJudgingList(elmID,itemsPerPage,startIndex,initialSort,initialSortDir,additionalQueries,forAward) {
	query = "/tracks/trackdata/?listName="+elmID+"&";
	if (additionalQueries) query = query + additionalQueries+"&";
	var judgeTrackColumnDefs = [
	                         	 {key:"title", label:"Title", sortable:false,resizeable:true},
	                         	 {key:"album", label:"Album", sortable:false,resizeable:true},
	                         	 {key:"artist", label:"Artist", sortable:false,resizeable:true},
	                         	 //{key:"player", label:"Listen to it!", sortable:false,resizeable:false},
	                         	 {key:"rank", label:"Rank it!", sortable:false,resizeable:false,
	                         		 formatter:YAHOO.widget.DataTable.Formatter.rankUpDownFormatter.bind(this)},
	                         ];
	var list = create_list(elmID,query,"rank","asc",0,judgeTrackColumnDefs,trackResponseSchema,startIndex,false);
	this.ItemList(elmID,list);
    this.row_selected = track_row_selected;
    this.for_award = forAward;
    this.listType = 'track';
    this.forJudge = true;
    this.dt.subscribe("rowSelectEvent", this.row_selected.bind(this));
    this.dt.render();
}
copyPrototype(TrackJudgingList,ItemList);

function AlbumJudgingList(elmID,itemsPerPage,startIndex,initialSort,initialSortDir,additionalQueries,forAward) {
	query = "/tracks/trackdata/?listName="+elmID+"&";
	if (additionalQueries) query = query + additionalQueries+"&";
	var judgeAlbumColumnDefs = [
	                         	 {key:"title", label:"Title", sortable:false,resizeable:true},
	                         	 {key:"artist", label:"Artist", sortable:false,resizeable:true},
	                         	 {key:"rank", label:"Rank it!", sortable:false,resizeable:false,
	                         		 formatter:YAHOO.widget.DataTable.Formatter.rankUpDownFormatter.bind(this)},
	                         ];
	var list = create_list(elmID,query,"rank","asc",0,judgeAlbumColumnDefs,albumResponseSchema,startIndex,false);
	this.ItemList(elmID,list);

	this.albumSelected = function(elm) {
		window.location.href = '/judge/album/'+elm.record.getData("pk")+'/';
	}
	
    this.dt.subscribe("rowSelectEvent", this.albumSelected.bind(this));

    this.listType = 'album';
	this.for_award = forAward;
    this.forJudge = true;
    this.dt.render();
}
copyPrototype(AlbumJudgingList,ItemList);

function AlbumNominationList(elmID,itemsPerPage,startIndex,initialSort,initialSortDir,additionalQueries) {
	query = "/albums/albumdata/?status=A&listName="+elmID+"&";
	if (additionalQueries) query = query + additionalQueries+"&"
	var list = create_list(elmID,query,initialSort,initialSortDir,itemsPerPage,albumNomColumnDefs,albumNomResponseSchema,startIndex);
	this.ItemList(elmID,list);
	
	this.albumSelected = function(elm) {
		window.location.href = '/nominator/album/'+elm.record.getData("pk")+'/';
		//elm = document.getElementById(elmID);
		//elm.align = "left";
		//elm.style = "text-align:left;";
	}
	
    this.dt.subscribe("rowSelectEvent", this.albumSelected.bind(this));
}

function AlbumList(elmID,itemsPerPage,startIndex) {
	var list = create_list(elmID,"/albums/albumdata/?",initialSort,initialSortDir,itemsPerPage,albumColumnDefs,albumResponseSchema,startIndex);
	this.ItemList(elmID,list);
	
	this.albumSelected = function(elm) {
		window.location.href = '/albums/'+elm.record.getData("pk")+'/';
		//elm = document.getElementById(elmID);
		//elm.align = "left";
		//elm.style = "text-align:left;";
	}
	
    this.dt.subscribe("rowSelectEvent", this.albumSelected.bind(this));
}

copyPrototype(AlbumList,ItemList);
copyPrototype(AlbumNominationList,ItemList);
