/* Summer Festival Guide Planner
by Alex Moon, November 2009 */

/* constants */
var stageWidth = 150 + 2;
var headerHeight = 54;
var marginTopHeight = 17;
var adMargin = 20;
var adHeight = 100 + (2*adMargin);
var nl = "\n";

var beginhour;
var endhour;
var beginminute;
var endminute;

var day;			/* currently selected day */
var dayLength;			/* the height of the columns */
var dayThreshold;		/* the time at which one day ends and the next begins */
var festival;			/* huge object full of data */
var myGigs = new Array();	/* myGigs[day][n] = act */
var notes = new Array();	/* notes[day][n] = note */
var overlaps = new Array();	/* overlaps[day][n] = overlap */

var divPlanner;			/* planner div */
var divTabs;			/* tabs div */
var divStages; 			/* stage columns */
var divTimes;			/* times div */
var divMyGigs;			/* my gigs column */
var divOverlap;			/* overlap column */
var divNotes;			/* notes column */
var divNoteBox;			/* notebox div */
var divEmail;			/* emailbox div */

var divBanner;
var divBLAd;
var divBRAd;

var http;			/* AJAX object */

window.onload = function() {
	divPlanner=document.getElementById('planner');
	divTabs=document.getElementById('tabsleft');
	divStages=document.getElementById('stagesinner');
	divTimes=document.getElementById('timesinner');
	divMyGigs=document.getElementById('mygigsinner');
	divOverlap=document.getElementById('overlapinner');
	divNotes=document.getElementById('notesinner');
	divNoteBox=document.getElementById('notebox');
	divEmail=document.getElementById('emailbox');
	divBanner=document.getElementById('banner');
	divBLAd=document.getElementById('blad');
	divBRAd=document.getElementById('brad');
	beginhour = document.getElementById('nb_hourbegin');
	endhour = document.getElementById('nb_hourend');
	beginminute = document.getElementById('nb_minutebegin');
	endminute = document.getElementById('nb_minuteend');

	if (window.XMLHttpRequest) {
		http = new XMLHttpRequest();
	} else {
		http = new ActiveXObject("Microsoft.XMLHTTP");
	}

	http.open("GET", "festival.php"+window.location.search, true);
	http.onreadystatechange = function(){
		if (http.readyState == 4) {
			festival = eval('(' + http.responseText + ')');
			if(festival['festival']==undefined) {
				divPlanner.innerHTML = "<p class='bignote'>That festival does not exist. If you bookmarked this festival, it may have been deleted.</p><p class='bignote'><a href='../'>Home</a></p>\n";
			} else if(festival['numdays']==0) {
				document.getElementById("festival").innerHTML = festival['festival'].toUpperCase();
				divPlanner.innerHTML = "<p class='bignote'>There is no information for this festival as yet. Please try again later.</p><p class='bignote'><a href='../'>Home</a></p>\n";
			} else {
				document.getElementById("festival").innerHTML = festival['festival'].toUpperCase();
				for(i=1;festival[i]!=undefined;i++) { /* for each day */
					myGigs[i] = new Array();
					notes[i] = new Array();
					overlaps[i] = new Array();
				}
				dayThreshold = festival['daythreshold'];
				dayLength = timeCompare(festival['daystart'],festival['dayend']);
				if(dayLength<=0) { dayLength += 1440; }
				document.getElementById("overlapinner").style.height = dayLength + 'px';
				divPlanner.style.height = (dayLength + headerHeight + marginTopHeight + adHeight) + 'px';
				if(festival[1]['numstages']>4) { divBLAd.style.marginTop = '4px'; } else { divBLAd.style.marginTop = '20px'; }
				if(IE) { document.getElementById('times').style.width = "20px"; }
				else { divBRAd.style.marginTop = (dayLength + headerHeight + marginTopHeight + adMargin) + 'px'; }
				divBanner.childNodes[0].href = festival['bannerlink'];
				divBLAd.childNodes[0].href = festival['bladlink'];
				divBRAd.childNodes[0].href = festival['bradlink'];
				changeDay(1);
			}
		}
	}
	http.send(null);
}

function drawPlanner() {
	drawTabs(); /* though technically the tabs aren't in the planner */
	if(IE){drawStagesIE();}else{drawStages();}
	drawTimes();
	drawMyGigs();
	drawOverlap();
	drawNotes();
}

function drawTabs() {
	result = '';
	for(i=1;festival[i]!=undefined;i++) {
		if(i==day) {
			result += '<div class="tabactive">'+dayOfWeek(festival[i]['date'])+' ('+shortAusDate(festival[i]['date'])+")</div>\n";
		} else {
			result += '<div class="tabinactive" ';
			result += 'onmouseover="this.style.background='+"'#9a492e'"+'; this.style.color='+"'#fff'"+'" ';
			result += 'onmouseout="this.style.background='+"'#fff'"+'; this.style.color='+"'#000'";
			result += '" onclick="changeDay('+i+')">'+dayOfWeek(festival[i]['date'])+' ('+shortAusDate(festival[i]['date'])+")</div>\n";
		}
	}
	divTabs.innerHTML = result;
}

function drawStages() {
	numstages = festival[day]['numstages'];
	innerwidth = numstages * stageWidth;
	divStages.style.width = innerwidth + 'px';
	if(numstages < 4){divStages.style.cssFloat = 'right';divStages.style.styleFloat = 'right';/* this second one for the benefit of IE8*/}

	result = '';						/* result string */
	for(i=1;festival[day][i]!=undefined;i++) {		/* for each stage */
		result += '<div class="stage">'+nl;
		result += '<div class="stageheader'+(i%3)+'"><p>'+festival[day][i]['stage']+'</p></div>'+nl;
		result += '<div class="stageinner" style="height: '+dayLength+'px">'+nl;
		curtime = festival['dayend'];
		for(j=1;festival[day][i][j]!=undefined;j++) {	/* for each act */
			/* first draw the empty slot if necessary */
			if(festival[day][i][j]['end']!=curtime) {
				h = timeCompare(festival[day][i][j]['end'],curtime);
				result += '<div class="break" style="height: '+h+'px"> </div>'+nl;
			}
			h = timeCompare(festival[day][i][j]['begin'],festival[day][i][j]['end']) - 1;
			if(festival[day][i][j]['planned']==true) {
				result += '<div class="dact'+(i%3)+'" style="height:'+h+'px" onclick="removeFromMyGigs('+festival[day][i][j]['id']+')">'+nl;
				result += '<div class="insideleft"><strong>'+festival[day][i][j]['act']+'</strong><br />';
				result += printTime(festival[day][i][j]['begin'])+'-'+printTime(festival[day][i][j]['end'])+nl;
				result += '</div><div class="insideright">Click to Remove</div>'+nl+'</div>'+nl;
			} else {
				result += '<div class="act'+(i%3)+'" style="height:'+h+'px" onclick="addToMyGigs('+festival[day][i][j]['id']+')">'+nl;
				result += '<div class="insideleft"><strong>'+festival[day][i][j]['act']+'</strong><br />';
				result += printTime(festival[day][i][j]['begin'])+'-'+printTime(festival[day][i][j]['end'])+nl;
				result += '</div><div class="insideright">Click to Add</div>'+nl+'</div>'+nl;
			}
			curtime = festival[day][i][j]['begin'];
		}
		result += "</div>\n</div>\n";
	}
	divStages.innerHTML = result;
}

function drawStagesIE() {
	document.getElementById('stagescroll').style.height = (dayLength + headerHeight + marginTopHeight + 20) + 'px';
	numstages = festival[day]['numstages'];
	innerwidth = numstages * stageWidth + 2;
	divStages.style.width = innerwidth + 'px';
	if(numstages < 4){divStages.style.styleFloat = 'right';}

	result = '';						/* result string */
	result += '<table><tr>';
	for(i=1;festival[day][i]!=undefined;i++) {		/* for each stage */
		result += '<td>'+nl;
		result += '<div class="stageheader'+(i%3)+'"><p>'+festival[day][i]['stage']+'</p></div>'+nl;
		result += '<div class="stageinner" style="height: '+dayLength+'px">'+nl;
		curtime = festival['dayend'];
		for(j=1;festival[day][i][j]!=undefined;j++) {	/* for each act */
			/* first draw the empty slot if necessary */
			if(festival[day][i][j]['end']!=curtime) {
				h = timeCompare(festival[day][i][j]['end'],curtime);
				result += '<div class="break" style="height: '+h+'px"> </div>'+nl;
			}
			h = timeCompare(festival[day][i][j]['begin'],festival[day][i][j]['end']) - 1;
			if(festival[day][i][j]['planned']==true) {
				result += '<div class="dact'+(i%3)+'" style="height:'+h+'px; position: static;"';
				result += 'onclick="removeFromMyGigs('+festival[day][i][j]['id']+')">'+nl;
				result += '<div class="insideleft"><strong>'+festival[day][i][j]['act']+'</strong><br />';
				result += printTime(festival[day][i][j]['begin'])+'-'+printTime(festival[day][i][j]['end'])+nl;
				result += '<span style="margin-left: 15px">Click to Remove</span></div>'+nl+'</div>'+nl;
			} else {
				result += '<div class="act'+(i%3)+'" style="height:'+h+'px; position: static;"';
				result += 'onclick="addToMyGigs('+festival[day][i][j]['id']+')">'+nl;
				result += '<div class="insideleft"><strong>'+festival[day][i][j]['act']+'</strong><br />';
				result += printTime(festival[day][i][j]['begin'])+'-'+printTime(festival[day][i][j]['end'])+nl;
				result += '(Click to Add)</div>'+nl+'</div>'+nl;
			}
			curtime = festival[day][i][j]['begin'];
		}
		result += "</div><!--stageinner-->\n</td>\n";
	}
	result += "</tr></table>\n";
	divStages.innerHTML = result;
}

function drawTimes() {
	earliest = parseInt(festival['daystart'].split(":")[0]);
	latest = parseInt(festival['dayend'].split(":")[0]);
	result = '';
	first = true;
	for(i=latest;true;i--) {
		if(!first && i==earliest){break;}
		ap = 'AM';
		if(i<=0) { i += 24; }
		if(i>12) { h = i-12; if(i!=24){ap='PM';} } else { h=i; if(i==12){ap='PM';} }
		result += '<div class="time">'+h+'<br /><small>'+ap+'</small></div>'+nl;
		if(first){first=false;}
	}
	ap = 'AM';
	if(i<=0) { i += 24; }
	if(i>12) { h = i-12; ap='PM'; } else { h=i; if(i==12){ap='PM';} }
	result += '<div class="time">'+h+'<br /><small>'+ap+'</div>'+nl;
	divTimes.innerHTML = result;
}

function drawMyGigs(){
	/* little note underneath "My Gigs!" saying what day, exactly, we're talking about here */
	document.getElementById("theday").innerHTML = dayOfWeek(festival[day]['date']) + " (" + shortAusDate(festival[day]['date']) + ")";

	/* the fun begins */
	curtime = festival['dayend'];
	result = '';
	for(i=0;myGigs[day][i]!=undefined;i++) {
		/* first, draw the empty slot if need be */
		if(!overlaps[day][i-1] && timeEarlier(myGigs[day][i]['end'],curtime)) {
			h = timeCompare(myGigs[day][i]['end'],curtime);
			result+=('<div class="break" style="height: '+h+'px;"></div>'+"\n");
		}

		/* we begin by setting a maximum height for the act, which we will subtract according to overlaps */
		h = timeCompare(myGigs[day][i]['begin'],myGigs[day][i]['end'])-1;
		curtime = myGigs[day][i]['begin'];
		
		/* now check for overlaps */
		/* first we check for type 2 prior */
		if(overlaps[day][i] && overlaps[day][i]['type']==2) {
			h = timeCompare(myGigs[day][i+1]['end'],myGigs[day][i]['end'])-1;
			curtime = myGigs[day][i+1]['end'];
		}

		/* now we check for type 1 overlaps */
		if(overlaps[day][i-1] && overlaps[day][i-1]['type']==1) { /* type 1 posterior */
			h -= Math.ceil(timeCompare(overlaps[day][i-1]['begin'],overlaps[day][i-1]['end'])/2);
		}
		if(overlaps[day][i] && overlaps[day][i]['type']==1) { /* type 1 prior */
			deltaT = Math.floor(timeCompare(overlaps[day][i]['begin'],overlaps[day][i]['end'])/2);
			h -= deltaT;
		}

		/*  we draw the current act */
		result += '<div class="act'+(myGigs[day][i]['stagenum']%3) + '" style="height: '+h+'px" ';
		result += 'onclick="removeFromMyGigs('+myGigs[day][i]['id']+')"><div class="insideleft"><strong>';
		result += myGigs[day][i]['act'] + '</strong><br />';
		result += printTime(myGigs[day][i]['begin'])+'-'+printTime(myGigs[day][i]['end'])+'</div>';
		result += '<div class="insideright">Click to Remove</div></div>'+nl;

		/* finally we check for type 2 posteriors - the one case where we take overlaps[day][i-2] into account */
		if(overlaps[day][i-1] && overlaps[day][i-1]['type']==2 && (myGigs[day][i+1]==undefined || timeEarlierOrEqual(myGigs[day][i+1]['end'],myGigs[day][i-1]['begin']))) {
			h = timeCompare(myGigs[day][i-1]['begin'],myGigs[day][i]['begin']) - 1;
			result += '<div class="act'+(myGigs[day][i-1]['stagenum']%3) + '" style="height: '+h+'px" ';
			result += 'onclick="removeFromMyGigs('+myGigs[day][i-1]['id']+')"><div class="insideleft"><strong>';
			result += myGigs[day][i-1]['act'] + '</strong><br />';
			result += printTime(myGigs[day][i-1]['begin'])+'-'+printTime(myGigs[day][i-1]['end'])+'</div>';
			result += '<div class="insideright">Click to Remove</div></div>'+nl;
			curtime = myGigs[day][i-1]['begin'];
		}
		if(overlaps[day][i-2] && overlaps[day][i-2]['type']==2) {
			if(timeEarlier(myGigs[day][i-2]['begin'],myGigs[day][i]['begin'])) {
				h = timeCompare(myGigs[day][i-2]['begin'],myGigs[day][i]['begin']) - 1;
				result += '<div class="act'+(myGigs[day][i-1]['stagenum']%3) + '" style="height: '+h+'px" ';
				result += 'onclick="removeFromMyGigs('+myGigs[day][i-1]['id']+')"><div class="insideleft"><strong>';
				result += myGigs[day][i-1]['act'] + '</strong><br />';
				result += printTime(myGigs[day][i-1]['begin'])+'-'+printTime(myGigs[day][i-1]['end'])+'</div>';
				result += '<div class="insideright">Click to Remove</div></div>'+nl;
				curtime = myGigs[day][i-2]['begin'];
			}
		}
	}

	divMyGigs.innerHTML = result;
}

function drawOverlap() {
	/* an interesting function here, because we need to join overlapping overlaps */
	curtime = festival['dayend'];
	result = '';
	for(i=0;overlaps[day][i]!=undefined;i++) {
		if(overlaps[day][i]) { /* we have an overlap to draw */
			/* so, first we draw the empty slot as needed */
			if(timeEarlier(overlaps[day][i]['end'],curtime)) {
				h = timeCompare(overlaps[day][i]['end'],curtime);
				result += '<div class="break" style="height: '+h+'px"></div>'+nl;
				curtime = overlaps[day][i]['end'];
			}

			/* then, we begin joining overlaps */
			end = overlaps[day][i]['end'];
			curtime = overlaps[day][i]['begin'];
			while(overlaps[day][i+1] && timeEarlierOrEqual(overlaps[day][i]['begin'],overlaps[day][i+1]['end'])) { /* we have an overlapping overlap */
				curtime = overlaps[day][i+1]['begin'];
				i++;
			}

			/* now we have our joined overlaps we draw them */
			h = timeCompare(curtime,end)-1;
			result += '<div class="overlap" style="height: '+h+'px">'+(h+1)+'</div>'+nl;
		}
	}
	divOverlap.innerHTML = result;
}

function drawNotes() {
	curtime = festival['dayend'];
	result = '';
	var imgstring;
	for(i=0;notes[day][i]!=undefined;i++) {
		/* first draw the empty slot if necessary */
		if(timeEarlier(notes[day][i]['end'],curtime)) {
			h = timeCompare(notes[day][i]['end'],curtime);
			result += '<div class="break" style="height: '+h+'px"> </div>'+nl;
		}
		h = timeCompare(notes[day][i]['begin'],notes[day][i]['end']) - 1;
		result += '<div class="note'+notes[day][i]['type']+'" style="height:'+h+'px">'+nl;
		result += '<div class="noteicons"><img src="edit.gif" alt="edit" onclick="editNoteBox('+i+')" /><img src="delete.gif" alt="delete" onclick="deleteNote('+i+')" /></div>'+nl;
		result += '<p>'+notes[day][i]['content']+' <small>(';
		result += printTime(notes[day][i]['begin'])+'-'+printTime(notes[day][i]['end'])+nl;
		result += ')</small></p></div>'+nl;
		curtime = notes[day][i]['begin'];
	}
	divNotes.innerHTML = result;
}

function changeDay(n) {
	day = n;
	fillNoteBoxSelects();
	drawPlanner();
}

/* addToMyGigs takes an act id and adds it to the current day plan */
function addToMyGigs(id) {
	/* first we find the act by its id */
	var act = false;
	for(i=1;festival[day][i]!=undefined;i++) { /* for each stage */
		for(j=1;festival[day][i][j]!=undefined;j++) { /* for each act */
			if(festival[day][i][j]['id']==id) {
				act = festival[day][i][j];
				act['stagenum'] = i;
				break;
			}
		}
		if(act){break;}
	}
	if(!act){alert("Congratulations, you have broken the application: invalid act ID.");return;}

	/* then we add the act to the day plan - this consists of a few steps: */
	/* first we have to find the index for the act - the act is between two other acts by end time */
	/* if the end time is equal to another act in the plan, then which of those two comes first is determined by begin time */
	if(myGigs[day][0]) { /* if there are no gigs in the plan then we can skip all the following */
		for(k=0;myGigs[day][k]!=undefined;k++) { /* for each act in the plan so far */
			/* test for instances in which i will be the new act's index */
			if(timeEarlier(myGigs[day][k]['end'],act['end'])) {
				break; /* top higher up the day plan */
			} else if (act['end'] == myGigs[day][k]['end'] && (timeEarlier(myGigs[day][k]['begin'],act['begin']))) {
				break; /* top equal but bottom higher up the day plan */
			}
		}
		/* we now have an index (k) for the new act, so we work out overlaps */
		/* first thing we do is check if the act overlaps with more than two others - if it does we want to prevent storing it */
		var overlapcount = 0;
		for(o=0;myGigs[day][o]!=undefined;o++) {
			if(timeEarlier(act['begin'],myGigs[day][o]['end']) && timeEarlier(myGigs[day][o]['begin'],act['end'])) {
				overlapcount ++;
				if(overlaps[day][o] && overlaps[day][o-1]) { overlapcount = 3; }
			}
			if(overlapcount >= 3) { alert("Too much speed will lead to a bad day..."); return; }
		}

		/* first, overlap with earlier act (i.e. later index = k) */
		/* (bear in mind we iterate through all arrays backwards in time) */
		if(myGigs[day][k]!=undefined) { /* if there is no earlier act, then we avoid this malarchy */
			if(timeEarlierOrEqual(myGigs[day][k]['end'],act['end'])
			&& timeEarlier(act['begin'],myGigs[day][k]['end'])
			&& timeEarlierOrEqual(myGigs[day][k]['begin'],act['begin'])) { /* type 1 overlap */
				overlapPrior = {'begin':act['begin'],'end':myGigs[day][k]['end'], 'type':1};
			} else if(timeEarlier(act['begin'],myGigs[day][k]['begin'])
			&& timeEarlier(myGigs[day][k]['end'],act['end'])) { /* type 2 overlap */
				overlapPrior = {'begin':myGigs[day][k]['begin'],'end':myGigs[day][k]['end'], 'type':2};
			} else { /* no overlap */
				overlapPrior = false;
			}
		} else { /* no prior act, so no prior overlap */
			overlapPrior = false;
		}
		/* now, overlap with later act (i.e. earlier index = k-1) */
		if(k) { /* if there is no later gig, we can avoid this malarchy */
			if(timeEarlierOrEqual(act['end'],myGigs[day][k-1]['end'])
			&& timeEarlier(myGigs[day][k-1]['begin'],act['end'])
			&& timeEarlierOrEqual(act['begin'],myGigs[day][k-1]['begin'])) { /* type 1 overlap */
				overlapPosterior = {'begin':myGigs[day][k-1]['begin'],'end':act['end'], 'type':1};
			} else if(timeEarlier(myGigs[day][k-1]['begin'],act['begin'])
			&& timeEarlier(act['end'],myGigs[day][k-1]['end'])) { /* type 2 overlap */
				overlapPosterior = {'begin':act['begin'],'end':act['end'], 'type':2};
			} else { /* no overlap */
				overlapPosterior = false;
			}
		} else { /* k=0, meaning no posterior act, so no posterior overlap */
			overlapPosterior = false;
		}

		myGigs[day].splice(k,0,act); /* splice in the act */
		if(k){ overlaps[day][k-1] = overlapPosterior; } /* this will have to have been false in order to have got this far */
		overlaps[day].splice(k,0,overlapPrior);
		festival[day][i][j]['planned']=true;
	} else {
		myGigs[day][0] = act; /* first element in the plan */
		festival[day][i][j]['planned']=true;
	}
	/* intense! */
	drawPlanner();
}

/* removeFromMyGigs takes an act id and removes that act from the current day plan */
function removeFromMyGigs(id) {
	/* first we find the act in myGigs */
	for(i=0;myGigs[day][i]!=undefined;i++) {
		if(myGigs[day][i]['id']==id) {
			/* first we remove the act */
			myGigs[day].splice(i,1);
			/* then we splice out the prior overlap */
			overlaps[day].splice(i,1);
			/* then, we work out the posterior overlap */
			if(i>0) { /* if there is no posterior act, we avoid this malarchy */
				overlapPosterior = false;
				if(myGigs[day][i]!=undefined) { /* similarly, if there is no prior act, there is no posterior overlap */
					if(timeEarlierOrEqual(myGigs[day][i]['end'],myGigs[day][i-1]['end'])
					&& timeEarlier(myGigs[day][i-1]['begin'],myGigs[day][i]['end'])
					&& timeEarlierOrEqual(myGigs[day][i]['begin'],myGigs[day][i-1]['begin'])) { /* type 1 overlap */
						overlapPosterior = {'begin':myGigs[day][i-1]['begin'],'end':myGigs[day][i]['end'], 'type':1};
					} else if(timeEarlier(myGigs[day][i-1]['begin'],myGigs[day][i]['begin'])
					&& timeEarlier(myGigs[day][i]['end'],myGigs[day][i-1]['end'])) { /* type 2 overlap */
						overlapPosterior = {'begin':myGigs[day][i]['begin'],'end':myGigs[day][i]['end'], 'type':2};
					} else { /* no overlap */
						overlapPosterior = false;
					}
				}
				overlaps[day][i-1] = overlapPosterior;
			}
			/* finally we return our act to the stage and exit the subroutine */
			for(j=1;festival[day][j]!=undefined;j++) { /* for each stage */
				for(k=1;festival[day][j][k]!=undefined;k++) { /* for each act */
					if(festival[day][j][k]['id']==id) { /* we've found our act */
						festival[day][j][k]['planned'] = false;
						drawPlanner();
						return;
					}
				}
			}
		}
	}
	/* if we get to this point something has gone horribly wrong */
	alert("Congratulations, you broke the application: invalid act id.");
}

function addNoteBox(w) {
	if(divNoteBox.style.display=='block' && document.getElementById('nb_type').value == w) {
		divNoteBox.style.display='none';
	} else {
		document.getElementById('nb_content').value='';
		document.getElementById('nb_type').value = w;
		switch(w) {
			case 0: document.getElementById('nb_title').innerHTML = 'Meet'; break;
			case 1: document.getElementById('nb_title').innerHTML = 'Eat+Drink'; break;
			case 2: document.getElementById('nb_title').innerHTML = 'Chill'; break;
			case 3: document.getElementById('nb_title').innerHTML = 'Other'; break;
		}
		selectNoteBoxSelects(festival['daystart'],festival['daystart']);
		if(IE) { divNoteBox.className = "nb"+w; }
		else { divNoteBox.setAttribute("class", "nb"+w); }
		document.getElementById('nb_submit').onclick = addNote;
		document.getElementById('nb_submit').innerHTML = "Add Note";
		var vertScroll = 0;
		if(IE) {
			if(document.compatMode == "CSS1Compat") {
				vertScroll = document.body.parentNode.scrollTop;
			} else {
				vertScroll = document.body.scrollTop;
			}
		} else {
			if(document.body.parentElement) {
				vertScroll = document.body.parentElement.scrollTop;
			} else {
				vertScroll = window.scrollY;
			}
		}
		divNoteBox.style.top = (vertScroll + 300) +"px";
		divNoteBox.style.display = 'block';
	}
}

function addNote() {
	begin = document.getElementById("nb_hourbegin").options[document.getElementById("nb_hourbegin").selectedIndex].value +
	  ":" + document.getElementById("nb_minutebegin").options[document.getElementById("nb_minutebegin").selectedIndex].value + ":00";
	end = document.getElementById("nb_hourend").options[document.getElementById("nb_hourend").selectedIndex].value +
	  ":" + document.getElementById("nb_minuteend").options[document.getElementById("nb_minuteend").selectedIndex].value + ":00";
	content = document.getElementById("nb_content").value;
	type = document.getElementById("nb_type").value;
	note = {'begin':begin, 'end':end, 'content':content, 'type':type};
	if(timeEarlier(note['end'],note['begin'])) { alert("Your start time is later than your end time."); return; }
	if(note['begin'] == note['end']) { alert("Your start and end times are the same."); return; }
	if(notes[day][0]==undefined) {
		notes[day][0] = note;
		divNoteBox.style.display='none';
		drawNotes();
	} else {
		for(i=0;notes[day][i]!=undefined;i++) {
			if(timeEarlierOrEqual(notes[day][i]['end'],note['end'])) {
				if(timeEarlier(note['begin'],notes[day][i]['end'])) {
					alert("That note overlaps another note!");
					return;
				} else {
					notes[day].splice(i,0,note);
					divNoteBox.style.display='none';
					drawNotes();
					return;
				}
			}
		}
		notes[day][i] = note;
		divNoteBox.style.display='none';
		drawNotes();
	}
}

/* NB: editNoteBox takes an index, i.e. the "i" in notes[day][i] */
function editNoteBox(i) {
	document.getElementById('nb_content').value = notes[day][i]['content'];
	switch(notes[day][i]['type']) {
		case 0: document.getElementById('nb_title').innerHTML = 'Meet'; break;
		case 1: document.getElementById('nb_title').innerHTML = 'Eat+Drink'; break;
		case 2: document.getElementById('nb_title').innerHTML = 'Chill'; break;
		case 3: document.getElementById('nb_title').innerHTML = 'Other'; break;
	}
	selectNoteBoxSelects(notes[day][i]['begin'], notes[day][i]['end']);
	if(IE) { divNoteBox.className = "nb"+notes[day][i]['type']; }
	else { divNoteBox.setAttribute("class", "nb"+notes[day][i]['type']); }
	document.getElementById('nb_submit').onclick = function(){editNote(i);};
	document.getElementById('nb_submit').innerHTML = "Update Note";
		var vertScroll = 0;
		if(IE) {
			if(document.compatMode == "CSS1Compat") {
				vertScroll = document.body.parentNode.scrollTop;
			} else {
				vertScroll = document.body.scrollTop;
			}
		} else {
			if(document.body.parentElement) {
				vertScroll = document.body.parentElement.scrollTop;
			} else {
				vertScroll = window.scrollY;
			}
		}
		divNoteBox.style.top = (vertScroll + 300) +"px";
	divNoteBox.style.display = 'block';
}

function editNote(old) {
	begin = document.getElementById("nb_hourbegin").options[document.getElementById("nb_hourbegin").selectedIndex].value +
	  ":" + document.getElementById("nb_minutebegin").options[document.getElementById("nb_minutebegin").selectedIndex].value + ":00";
	end = document.getElementById("nb_hourend").options[document.getElementById("nb_hourend").selectedIndex].value +
	  ":" + document.getElementById("nb_minuteend").options[document.getElementById("nb_minuteend").selectedIndex].value + ":00";
	content = document.getElementById("nb_content").value;
	type = notes[day][old]['type'];
	notes[day].splice(old,1);
	note = {'begin':begin, 'end':end, 'content':content, 'type':type};
	if(note['begin'] > note['end']) { alert("Your start time is later than your end time."); return; }
	if(note['begin'] == note['end']) { alert("Your start and end times are the same."); return; }
	if(notes[day][0]==undefined) {
		notes[day][0] = note;
		divNoteBox.style.display='none';
		drawNotes();
	} else {
		for(i=0;notes[day][i]!=undefined;i++) {
			if(timeEarlierOrEqual(notes[day][i]['end'],note['end'])) {
				if(timeEarlier(note['begin'],notes[day][i]['end'])) {
					alert("That note overlaps another note!");
					break;
				} else {
					notes[day].splice(i,0,note);
					divNoteBox.style.display='none';
					drawNotes();
					return;
				}
			}
		}
		notes[day][i] = note;
		divNoteBox.style.display='none';
		drawNotes();
	}
}

function deleteNote(index) {
	notes[day].splice(index,1);
	drawNotes();
}

function fillNoteBoxSelects() {
	var time;

	/* first do hours */
	last = beginhour.options.length;
	for(i=0;i<last;i++) { beginhour.remove(0); endhour.remove(0); }
	last = parseInt(festival['dayend'].split(":")[0]);
	ap = 'am';
	for(i=parseInt(festival['daystart'].split(":")[0]);i!=last;i++) {
		if(i>12){h=i-12; ap='pm';}else{h=i;if(i==12){ap='pm';}}
		if(i==24){if(last==0){break;}else{i=0; ap='am';}}
		if(i<10){
			beginhour.options[beginhour.options.length] = new Option(h+ap, '0'+i);
			endhour.options[endhour.options.length] = new Option(h+ap, '0'+i);
		} else {
			beginhour.options[beginhour.options.length] = new Option(h+ap, i);
			endhour.options[endhour.options.length] = new Option(h+ap, i);
		}
	}

	/* then do minutes */
	last = beginminute.options.length;
	for(i=0;i<last;i++) { beginminute.remove(0); endminute.remove(0); }
	for(i=0;i<60;i+=5) {
		if(i<10){m='0'+i;}else{m=i;}
		beginminute.options[beginminute.options.length] = new Option(m, m);
		endminute.options[endminute.options.length] = new Option(m, m);
	}
}

function selectNoteBoxSelects(begin, end) {
	hourbegin = begin.split(":")[0]; minutebegin = begin.split(":")[1];
	hourend = end.split(":")[0]; minuteend = end.split(":")[1];
	for(i=0;i<beginhour.options.length;i++) {
		if(beginhour.options[i].value == hourbegin) { beginhour.options[i].selected = true; }
		else if(beginhour.options[i].selected) { beginhour.options[i].selected = false; }
	}
	for(i=0;i<endhour.options.length;i++) {
		if(endhour.options[i].value == hourend) { endhour.options[i].selected = true; }
		else if(endhour.options[i].selected) { endhour.options[i].selected = false; }
	}
	for(i=0;i<beginminute.options.length;i++) {
		if(beginminute.options[i].value == minutebegin) { beginminute.options[i].selected = true; }
		else if(beginminute.options[i].selected) { beginminute.options[i].selected = false; }
	}
	for(i=0;i<endminute.options.length;i++) {
		if(endminute.options[i].value == minuteend) { endminute.options[i].selected = true; }
		else if(endminute.options[i].selected) { endminute.options[i].selected = false; }
	}
}

function emailDayPlan() {
	var vertScroll = 0;
	if(IE) {
		if(document.compatMode == "CSS1Compat") {
			vertScroll = document.body.parentNode.scrollTop;
		} else {
			vertScroll = document.body.scrollTop;
		}
	} else {
		if(document.body.parentElement) {
			vertScroll = document.body.parentElement.scrollTop;
		} else {
			vertScroll = window.scrollY;
		}
	}
	divEmail.style.top = (vertScroll + 120) + 'px';
	divEmail.style.display = 'block';
}

function postEmailDayPlan() {
	emailForm = document.getElementById('emailform');
	friends = new Array();
	for(i=0;i<8;i++) {
		if(document.getElementById('email'+i).value!='') {
			friends.push({
				'name':document.getElementById('name'+i).value,
				'email':document.getElementById('email'+i).value
			});
		}
	}

	emailjsonstring = writeJSON({
		'name':emailForm.namefrom.value,
		'email':emailForm.emailfrom.value,
		'friends':friends
	});

	if (window.XMLHttpRequest) {
		http = new XMLHttpRequest();
	} else {
		http = new ActiveXObject("Microsoft.XMLHTTP");
	}
	http.open("POST", "pdf.php"+window.location.search, true);

	/* POST gigs, overlaps, notes */
	postParams = "g="+writeJSON(myGigs)+"&o="+writeJSON(overlaps)+"&n="+writeJSON(notes)+"&m="+emailjsonstring;
	http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	http.setRequestHeader("Content-length", postParams.length);
	http.setRequestHeader("Connection", "close");

	http.onreadystatechange = function(){
		if (http.readyState == 4) {
			if(http.responseText=='JSON') {
				window.location.href="error.php";
			} else if(http.responseText=='true') {
				divEmail.style.display = 'none';
			} else {
				alert("Your e-mail was not sent: "+http.responseText);
			}
		}
	}
	http.send(postParams);

	return false;
}

/* the following code will send the myGigs, overlaps and notes objects to pdf.php by post */
function postDayPlan() {
	var form = document.createElement("form");
	form.setAttribute("method", "post");
	form.setAttribute("action", "pdf.php"+window.location.search);

	var g = document.createElement("input");
	g.setAttribute("type", "hidden");
	g.setAttribute("name", "g");
	g.setAttribute("value", writeJSON(myGigs));
	form.appendChild(g);

	var n = document.createElement("input");
	n.setAttribute("type", "hidden");
	n.setAttribute("name", "n");
	n.setAttribute("value", writeJSON(notes));
	form.appendChild(n);

	var o = document.createElement("input");
	o.setAttribute("type", "hidden");
	o.setAttribute("name", "o");
	o.setAttribute("value", writeJSON(overlaps));
	form.appendChild(o);

	document.body.appendChild(form);

	form.submit();
}

function writeJSON(o) {
	var result = '{';
	var fi=true;
	for(var i in o) {
		if(fi){fi=false;}else{result += ",";}
		result += '"'+i+'":';
		if(typeof o[i] == 'object') {
			result += writeJSON(o[i]);
		} else {
			if(typeof o[i] == 'string') { out = o[i].replace(/&/g,"%26").replace(/\n/g,"ZOMG_ITS_A_NEWLINE"); } else { out = o[i]; }
			result += '"'+out+'"';
		}
	}
	result += "}";
	return result;
}

/* timeCompare returns the number of minutes between two times ignoring seconds */
function timeCompare(earlier, later) {
	var result = 0;
	d1 = later.split(":");
	d2 = earlier.split(":");
	result = ((d1[0] - d2[0]) * 60) + (d1[1] - d2[1]);
	if(result<0) { result += 1440; }
	return result;
}

function timeEarlier(earlier, later) {
	if((earlier <= dayThreshold && later <= dayThreshold) || (earlier > dayThreshold && later > dayThreshold)) {
		return earlier < later;
	} else { /* on different sides of the threshold */
		return earlier > dayThreshold;
	}
}
function timeEarlierOrEqual(earlier, later) {
	if((earlier <= dayThreshold && later <= dayThreshold) || (earlier > dayThreshold && later > dayThreshold)) {
		return earlier <= later;
	} else { /* on different sides of the threshold */
		return earlier > dayThreshold;
	}
}

/* shortAusDate takes a string of format YYYY-MM-DD and converts it to DD/MM/YY */
function shortAusDate(datestring) {
	thedate = datestring.split("-");
	theyear = thedate[0].substring(2,4);
	return thedate[2] + "/" + thedate[1] + "/" + theyear;
}

/* dayOfWeek takes a string of format YYYY-MM-DD and gets the (short) day-of-week name */
function dayOfWeek(datestring) {
	thedate = datestring.split("-");
	year = thedate[0]-0; month = thedate[1]-0; alex_moon_is_a_genius = thedate[2]-0;
	thedate = new Date(year,month-1,alex_moon_is_a_genius);
	switch(thedate.getDay()) {
		case 0: return "Sun";
		case 1: return "Mon";
		case 2: return "Tue";
		case 3: return "Wed";
		case 4: return "Thu";
		case 5: return "Fri";
		case 6: return "Sat";
		default: return thedate.getDay();
	}
}

function printTime(timestring) {
	thetime = timestring.split(":");
	ap = 'am';
	if(thetime[0]>12){hour = thetime[0]-12; ap = 'pm';} else { hour = parseInt(thetime[0]); if(thetime[0]==12){ap='pm';} if(thetime[0]==0){hour=12;} }
	if(thetime[1]==0) { return hour+ap; } else { return hour +":"+ thetime[1] + ap; }
}
