/***************************************************************************
EDITED PLEASE!?!?

	Copyright (C) 2004 Chris G. Kampmeier
	email: chris@kampers.net
	
	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.
 ***************************************************************************/


// utility variable used by some objects that must override the actions of their container objects
var noAction = false;


var m_basedir = '/';



function fillFields() {
// variable argument order: toFields, [fromFields,] defaultFromValue

	for (var i = 1; i < document.recording_details.length; i++) {
		if (document.recording_details.elements[arguments[0] + i]) {

			if (arguments.length == 3) { // user has passed a To array name, a From array name, and a default fill value
				if (document.recording_details.elements[arguments[1] + i]) { // if the From array name is valud
					document.recording_details.elements[arguments[0] + i].value = document.recording_details.elements[arguments[1] + i].value
				}
				else {			// otherwise use the default fill value
					document.recording_details.elements[arguments[0] + i].value = arguments[2];
				}
			}
			else if (arguments.length == 2) { // user has passed a To array name and a fill value
				document.recording_details.elements[arguments[0] + i].value = arguments[1];
			}
		}
	}
		
}

function fixCapitalizations(toFields) {
	for (var i = 1; i < document.recording_details.length; i++) {
		if (document.recording_details.elements[toFields + i]) {
			document.recording_details.elements[toFields + i].value = GuessCase(document.recording_details.elements[toFields + i].value);
		}
	}
}

function fillCheckboxes(toFields, value) {
	for (var i = 1; i < document.recording_details.length; i++) {
		if (document.recording_details.elements[toFields + i]) {
			document.recording_details.elements[toFields + i].checked = value;
		}
	}
}

function fillIntegersAsc(toFields) {
	for (var i = 1; i < document.recording_details.length; i++) {
		if (document.recording_details.elements[toFields + i]) {
			document.recording_details.elements[toFields + i].value = i;
		}
	}
}

function clearIfValue(fieldName, value) {
	if (fieldName.value == value) {
		fieldName.value = '';
	}
}
	
function checkLocation() {
	if (document.recording_details.location.value == 'None') {		// location is none
		document.recording_details.wall.value = 'None';
		document.recording_details.wall.disabled = true;
		document.recording_details.number.value = ''
		document.recording_details.number.disabled = true;
	}
	else {
		document.recording_details.wall.disabled = false;
		document.recording_details.number.disabled = false;
	}
}

function moveFocus(toField, fromObj, maxLength) {
	if (fromObj.value.length == maxLength) {
		document.recording_details.elements[toField].focus();
	}
}

function pasteField(toField) {
	toField.value = '';
	toField.focus();
	document.execCommand("Paste");
}

function validateInsert(theForm) {
	var why = "";
	why += checkArtist(theForm.artist);
	why += checkTitle(theForm.title);
	why += checkLabel(theForm.label);
	why += checkNumber(theForm.number);

	why += checkYear(theForm.date_release_year);
	why += checkMonth(theForm.date_release_month);
	why += checkDay(theForm.date_release_day);

	var tracksExist = false;
	for (var i = 1; i < theForm.length; i++) {
		if (theForm.elements["track_time_" + i]) {
			why += checkLength(theForm.elements["track_time_" + i]);
			tracksExist = true;
		}
	}
	
	if (!(tracksExist)) {
		why += "You did not submit any tracks.\n";
	}

	if (why != "") {
		alert("There are errors in your entry:\n\n" + why);
		return false;
	}
	return true;
}


function validatePlaylistTrack(theForm) {
	var why = "";
	why += checkArtist(theForm.artist);
	why += checkAlbum(theForm.recording_title);
	why += checkTitle(theForm.title);
	why += checkLength(theForm.time);
	why += checkLabel(theForm.label);
	why += checkTrackNumber(theForm.track);
	why += checkComposer(theForm.composer);
	if (theForm.manner_performance.value == 'Vocal') {
		why += checkAuthor(theForm.author);
	}

	
	if (why != "") {
		alert("There are errors in your entry:\n\n" + why);
		return false;
	}
	
	var capsCount = checkCaps(theForm.artist);
	capsCount += checkCaps(theForm.recording_title);
	capsCount += checkCaps(theForm.title);
	capsCount += checkCaps(theForm.label);
	capsCount += checkCaps(theForm.composer);
	if (theForm.manner_performance.value == 'Vocal') {
		capsCount += checkCaps(theForm.author);
	}
	
	if ((theForm.manner_performance.value == 'Vocal' && capsCount >= 4) || capsCount >= 3) {
// DING DONG THE WITCH IS DEAD		alert('Please correct capitalization errors in your track. This information appears on kscr.org, so it should be formatted correctly.');
		return true;
	}

	return true;
}

function checkCaps(entry) {
	if (!(entry.value.match(/[A-Z]/))) {
		return 1;	
	} else if (!(entry.value.match(/[a-z]/))) {
		return 1;
	} else return 0;	
}


function checkArtist(entry) {
	if (entry.value == "") {
		return "Please complete the Artist field.\n";
	}
	else return "";
}

function checkTitle(entry) {
	if (entry.value == "") {
		return "Please complete the Title field.\n";
	}
	else return "";
}

function checkAlbum(entry) {
	if (entry.value == "") {
		return "Please complete the Album field.\n";
	}
	else return "";
}

function checkLabel(entry) {
	if (entry.value == "") {
		return "Please complete the Label field.\n";
	}
	else return "";
}

function checkAuthor(entry) {
	if (entry.value == "") {
		return "Please complete the Author field.\n";
	}
	else return "";
}

function checkComposer(entry) {
	if (entry.value == "") {
		return "Please complete the Composer field.\n";
	}
	else return "";
}

function checkNumber(entry) {
	if (entry.value == "" && entry.disabled == false) {
		return "Please complete the Number field.\n";
	}
	else return "";
}

function checkYear(entry) {
	if (entry.value == "" || isNaN(parseInt(entry.value))) {
		return "Please complete the Release Date: Year field.\n";
	}
	else return "";
}

function checkTrackNumber(entry) {
	if (entry.value == "" || isNaN(parseInt(entry.value))) {
		return "Please complete the Track Number field.\n";
	}
	else return "";
}


function checkMonth(entry) {
	if (entry.value == "" || isNaN(parseInt(entry.value))) {
		return "Please complete the Release Date: Month field.\n";
	}
	else return "";
}

function checkDay(entry) {
	if (entry.value == "" || isNaN(parseInt(entry.value))) {
		return "Please complete the Release Date: Day field.\n";
	}
	else return "";
}

function checkLength(entry) {
	var lengthFilter = /[0-9]+[:.][0-9]{2}/;
	if (!(lengthFilter.test(entry.value))) {
		return "Please check for errors in a length field: " + entry.value + "\n";
	}
	else return "";
}









// Capitalization and other error correcting functions
// from http://musicbrainz.org/

function GuessSortname(name)
{
	name = TrimSquash(name);

	// Change "A B C" to "B C, A"
	var first_space = name.indexOf(" ");
	if (first_space != -1)
		name = name.substring(first_space+1, name.length)
			+ ", "
			+ name.substring(0,first_space);

	return name;
}
function GuessCase(s) { return GuessCase2(s, false) }
function GuessCase2(string, inbrackets)
{
	string = TrimSquash(string);

	if (inbrackets == false)
	{
		if (string.match(/^[\(\[]?\s*data(\s+track)?\s*[\)\]]?$/i))
			return "[data track]";

		if (string.match(/^[\(\[]?\s*silen(t|ce)(\s+track)?\s*[\)\]]?$/i))
			return "[silence]";
	}

	// foo (...
	var m = string.match(/^([^\(\[\"]*) ([\(\[\"].*)$/);

	if (m != null)
	{
		return GuessCase2(m[1], false) + " " + GuessCase2(m[2], false);
	}

	// (bar) ...
	m = string.match(/^([\(\[\"])([^\(\[\"]*)([\)\]\"])(.*)$/);

	if (m != null)
	{
		s = m[1] + GuessCase2(m[2], true) + m[3];
		if (m[4] != "") s += " " + GuessCase2(m[4], false);
		return s;
	}

	// stuff: more stuff
	m = string.match(/^([^:]*):\s*(.*)$/);

	if (m != null)
	{
		return GuessCase2(m[1], false) + ": " + GuessCase2(m[2], false);
	}

	// normalise some punctuation and spacing
	string = string.replace(/\s*:\s*/g, ": ");
	string = string.replace(/\s*,\s*/g, ", ");

 	string = string.toLowerCase();
  	var words = string.split(" ");

   	for (var i=0; i<words.length; i++)
	{
	  	words[i] = words[i].substring(0,1).toUpperCase()
			+ words[i].substring(1, words[i].length);
	}

	string = words.join(" ");
	string = LowercaseCommonWords(string);
	string = MiscTransform(string);
	string = TrimSquash(string);

	if (inbrackets)
	{
		string = string
			// common first words of bracketed parts
			. replace(/^acoustic\b/i, "acoustic")
			. replace(/^album\b/i, "album")
			. replace(/^alternate\b/i, "alternate")
			. replace(/^bonus\b/i, "bonus")
			. replace(/^clean\b/i, "clean")
			. replace(/^club\b/i, "club")
			. replace(/^dance\b/i, "dance")
			. replace(/^dirty\b/i, "dirty")
			. replace(/^dis[ck]\b/i, "disc")
			. replace(/^extended\b/i, "extended")
			. replace(/^instrumental\b/i, "instrumental")
			. replace(/^live\b/i, "live")
			. replace(/^original\b/i, "original")
			. replace(/^radio\b/i, "radio")
			. replace(/^single\b/i, "single")
			. replace(/^take\b/i, "take")
			// common last words of bracketed parts
			. replace(/\bdemo$/i, "demo")
			. replace(/\bdis[ck]$/i, "disc")
			. replace(/\bedit$/i, "edit")
			. replace(/\bskit$/i, "skit")
			. replace(/\bmix$/i, "mix")
			. replace(/\bremix$/i, "remix")
			. replace(/\brmx$/i, "remix")
			. replace(/\btake$/i, "take")
			. replace(/\bversion$/i, "version")
			;
	}

	return string;
}
function LowercaseCommonWords(string)
{
	return string
		. replace(/ a /gi, " a ")
		. replace(/ and /gi, " and ")
		. replace(/ an /gi, " an ")
		. replace(/ as /gi, " as ")
		. replace(/ at /gi, " at ")
		. replace(/ but /gi, " but ")
		. replace(/ by /gi, " by ")
		. replace(/ for /gi, " for ")
		. replace(/ in /gi, " in ")
		. replace(/ 'n' /gi, " 'n' ")
		. replace(/ n\' /gi, " n' ")
		. replace(/ nor /gi, " nor ")
		. replace(/ of /gi, " of ")
		. replace(/ o\' /gi, " o' ")
		. replace(/ on /gi, " on ")
		. replace(/ or /gi, " or ")
		. replace(/ the /gi, " the ")
		. replace(/ to /gi, " to ")
		// TODO .de: der und
		// TODO .fr: de du et la le les un une
		// TODO .es: y
		// TODO .it: con di
		// TODO .??: da do del
		// TODO op? (opus)
		;
}
function MiscTransform(string)
{
	return string
		. replace(/ (versus|vs\.|vs) /gi, " vs. ")
		. replace(/\bfeat(\.|\b|uring\b)/i, "feat.")
		. replace(/\bft(\.|\b)/i, "feat.")
		. replace(/\bdj\b/gi, "DJ")
		. replace(/\bmc\b/gi, "MC")
		. replace(/\btv\b/gi, "TV")
		. replace(/\bmtv\b/gi, "MTV")
		. replace(/\bep\b/gi, "EP")
		. replace(/\blp\b/gi, "LP")
		. replace(/\bi\b/gi, "I") // What have the Romans ever done for us?
		. replace(/\bii\b/gi, "II")
		. replace(/\biii\b/gi, "III")
		. replace(/\biiii\b/gi, "IIII")
		. replace(/\biv\b/gi, "IV")
		. replace(/\bv\b/gi, "V")
		. replace(/\bvi\b/gi, "VI")
		. replace(/\bvii\b/gi, "VII")
		. replace(/\bviii\b/gi, "VIII")
		. replace(/\bix\b/gi, "IX")
		. replace(/\bx\b/gi, "X")
		. replace(/\bbwv\b/gi, "BWV") // Bach
		// TODO major/minor
		;
}
function TrimSquash(s)
{
	return s
		. replace(/^\s\s*/, "")
		. replace(/\s\s*$/, "")
		. replace(/\s\s*/g, " ")
		;
}













var behaviourRules = {
	'.playlist_track': function(el) {
			el.onmouseover = function() {
				var dragger = cssQuery('.dragger', el);
				if (dragger.length > 0) {
					dragger[0].style.visibility = 'visible';
				}
			};
			el.onmouseout = function() {
				var dragger = cssQuery('.dragger', el);
				if (dragger.length > 0) {
					dragger[0].style.visibility = 'hidden';
				}
			};
	},
	
	'.playlist_track .play': function(el) {
		el.onclick = function() {
			var number = el.id.split('_')[1];
			$('track_'+number).style.borderColor = '#090';
			playTrack(number);
		};
		el.onmouseover = function() {
			el.style.backgroundImage = "url('images/play_o.gif')";
		};
		el.onmouseout = function() {
			el.style.backgroundImage = "url('images/play.gif')";					
		};
	},

	'.playlist_track .delete': function(el) {
		el.onclick = function() {
			var number = el.id.split('_')[1];
			$('track_'+number).style.borderColor = '#900';
			if (confirm('Are you sure you want to delete this track?')) {
				deleteTrack(number);
			} else {
				$('track_'+number).style.borderColor = '#c0c0c0';
			}
		};
		el.onmouseover = function() {
			el.style.backgroundImage = "url('images/trash_o.gif')";
		}
		el.onmouseout = function() {
			el.style.backgroundImage = "url('images/trash.gif')";					
		};
	}

};

Behaviour.register(behaviourRules);



function sortableCreate() {
	Sortable.create('playlist', {tag: 'div', constraint: 'vertical', handle: 'dragger', only: 'unplayed', onUpdate: playlistUpdate, onChange: playlistChange});	
}


function playlistLoader() {
	if ($('playlist')) {
		
		if (cssQuery('.playlist_track', $('playlist')).length == 0) {
			$('playlist_help').show();	
		}

		sortableCreate();

		// spinner and failure handler
		var myGlobalHandlers = {
			onCreate: function() {
				hideStatus();
				Element.show('playlist_spinner');
			},
			onComplete: function() {
				if (Ajax.activeRequestCount == 0) {
					Element.hide('playlist_spinner');
				}
			},
			onFailure: function() {
				ajaxFailure();
			}
		};
		Ajax.Responders.register(myGlobalHandlers);
		
		resizeTracks();	
	}
}
Event.observe(window, 'load', playlistLoader, true);



var ajaxFailure = function() {
	alert("Error:\n\nThere was a problem communicating with the database server. The action you requested may not have been completed.\n\nPlease refresh this page, then try again.");	
}



var playlistChange = function(draggedTrack) {
	var first_id = Sortable.sequence('playlist')[0];
	var first = $('track_'+first_id);
	
	// remove existing play button
	var play = cssQuery('.play', $('playlist'));
	if (play.length > 0) {
		play[0].parentNode.removeChild(play[0]);		
	}

	addPlayToFirstTrack();

	// play button and trashcan overlap on small tracks, so hide the trash temporarily if showing the play button
	if (first.className.indexOf('small') != -1 && play.length > 0) {
		Element.hide('delete_'+first_id);
	} else if ((draggedTrack.id != first.id) && (draggedTrack.className.indexOf('small') != -1)) {
		Element.show(cssQuery('.delete', draggedTrack)[0]);
	}

	Behaviour.apply($('playlist'));
};

var addPlayToFirstTrack = function() {
	if (playlistIsPlayable && Sortable.sequence('playlist').length > 0) {
		var first_id = Sortable.sequence('playlist')[0];
		var first = $('track_'+first_id);
		if (cssQuery('.play', first).length == 0) {
			var play = document.createElement('div');
			play.className = 'play';
			play.id = 'play_'+first_id;
			cssQuery('div>div.clearfix', first)[0].appendChild(play);
		}

		Behaviour.apply($('playlist'));
	}
};

var playlistUpdate = function() {
	resizeTracks();
	restoreTrashcans();
	
	var data = 'p_action=ajaxUpdateOrder&' + Sortable.serialize('playlist');
	var request = new Ajax.Request(m_basedir, {method: 'get', parameters: data, onSuccess: playlistUpdateSuccess});
};

var playlistUpdateSuccess = function(request) {
	if (request.responseText.indexOf('OK') == -1) {
		ajaxFailure();	
		return;
	}
}



var deleteTrack = function(track_id) {
	var el = $('track_'+track_id);
	var data = 'p_action=ajaxDeleteTrack&track_id='+track_id;
	var request = new Ajax.Request(m_basedir, {method: 'get', parameters: data, onSuccess: deleteTrackSuccess});	
};

var deleteTrackSuccess = function(request) {
	if (request.responseText.indexOf('OK') == -1) {
		ajaxFailure();	
		return;
	}
	
	var response = request.responseText.split("\n");
	var el = $('track_'+response[1]);
	
	Effect.Fade(el,	{ afterFinish: function() { 	el.parentNode.removeChild(el);
													addPlayToFirstTrack();
													resizeTracks();
													updateTotalLength();
												}
					} );
};




var playTrack = function(track_id) {
	var el = $('track_'+track_id);
	var data = 'p_action=ajaxPlayTrack&track_id='+track_id;
	var request = new Ajax.Request(m_basedir, {method: 'get', parameters: data, onSuccess: playTrackSuccess});	
};

var playTrackSuccess = function(request) {
	if (request.responseText.indexOf('OK') == -1) {
		ajaxFailure();	
		return;
	}
	
	var response = request.responseText.split("\n");
	var el = $('track_'+response[1]);

	var playedat = document.createElement('div');
	playedat.className = 'playedat';
	playedat.innerHTML = 'Played at ' + response[2];
	
	var dragger = cssQuery('.dragger', el)[0];
	var playBtn = cssQuery('.play', el)[0];
	var deleteBtn = cssQuery('.delete', el)[0];
	
	dragger.parentNode.removeChild(dragger);
	playBtn.parentNode.removeChild(playBtn);
	deleteBtn.parentNode.removeChild(deleteBtn);

	cssQuery('.information', el)[0].appendChild(playedat);
	
	Element.classNames(el).remove('unplayed');
	Element.classNames(el).add('played');
	
	el.style.borderColor = "#666";
	
	sortableCreate();
	addPlayToFirstTrack();
	resizeTracks();
};



var updateTotalLength = function() {
	var el = $('playlist_lengthtotal');
	var request = new Ajax.Updater(el, m_basedir, {method: 'get', parameters: 'p_action=ajaxTotalLength', onSuccess: updateTotalLengthSuccess});
};

var updateTotalLengthSuccess = function(request) {
	if (cssQuery('.playlist_track', $('playlist')).length == 0) {
		$('playlist_help').show();	
		$('playlist_lengthtotal').hide();
	}
}

var restoreTrashcans = function() {
	Element.show('delete_'+Sortable.sequence('playlist')[0]);
};

var hideStatus = function() {
	cssQuery('.status')[0].hide();
};

var resizeTracks = function() {
	// change class for unplayed tracks
	var sequence = Sortable.sequence('playlist');
	for (i = 0; i < sequence.length; i++) {
		if (i < 3) {
			Element.classNames('track_' + sequence[i]).remove('small');
		} else {
			Element.classNames('track_' + sequence[i]).add('small');
		}
	}
	
	// change class for played tracks
	var playedTracks = cssQuery('.played', $('playlist'));
	for (i = 0; i < playedTracks.length; i++) {
		if (playedTracks.length - i - 1 < 3) {
			Element.classNames(playedTracks[i]).remove('small');
		} else {
			Element.classNames(playedTracks[i]).add('small');
		}
	}

	// change height of dragger to fit newly sized content
	var draggers = document.getElementsByClassName('dragger');
	draggers.each( function(el) {
		el.style.height = cssQuery('.information', el.parentNode)[0].clientHeight + 'px';
	} );

	// remove and re-add trashcans to workaround safari 2.0.4 (419.3) display bug
	var tracks = cssQuery('.unplayed', $('playlist'));
	tracks.each( function(track) {
		var trash = cssQuery('.delete', track)[0];				  
		var trashParent = trash.parentNode;			 
		trashParent.removeChild(trash);
		var newTrash = document.createElement('div');
		newTrash.className = 'delete';
		newTrash.id = 'delete_'+track.id.split('_')[1];
		trashParent.appendChild(newTrash);
	} );
	
	Behaviour.apply($('playlist'));

};

