// sounds
soundManager.url = '/assets/flash/';
soundManager.flashVersion = 9;
soundManager.debugMode = false;
soundManager.defaultOptions.autoLoad = true;
soundManager.defaultOptions.volume = 30;
soundManager.defaultOptions.multiShot = true;
var sounds = [];
var sound;
soundManager.onload = function(){
	var prefix = '';
	var url;
	for(var i=1; i<37; i++){
		prefix = '';
		if(i < 10) prefix = '0';
		var id = prefix+i;
		url = '/assets/files/sounds/musicbox/Chrm'+id+'.mp3';
		sounds[i] = soundManager.createSound({
			id: 'Chrm'+id,
			url: url
		});
	};
}

// map

var map;
var playhead;
var gdir;
var played_notes;
var animatePlayhead;
var l;
var m;
var n;
var k;
var o;
var q;
var start_note;
var scale;
var notes_limit = 25;
var available_notes;

function makeScale(){
	start_note = parseInt($('#start_note').attr('value'));
	scale = $('#scale').attr('value');
	available_notes = [];
	var i=0
	while(i<notes_limit){
		available_notes.push(i+start_note);
		switch (scale){
			case "major":
				if(i != 4 && i != 11 && i != 16 && i != 23) i++;
				break;
			case "minor":
				if(i != 2 && i != 7 && i != 14 && i != 19) i++;
				break;
			case "pentatonic":
				if(i == 2 || i == 9 || i == 14 || i == 21) i++;
				i++;
				break;
			case "wholetone":
				i++;
				break;
			default:
				i = i;
		}
		i++;
	};
}

function markAndFitMap(points) {
   var bounds = new GLatLngBounds();
   for (var i=0; i< points.length; i++) {
   		var latlng = map.fromContainerPixelToLatLng(points[i]);
   		// map.addOverlay(new GMarker(latlng));
   		bounds.extend(latlng);
   }
   map.setZoom(map.getBoundsZoomLevel(bounds));
   map.setCenter(bounds.getCenter());
}

function makeRectangle(points) {
	var bounds = new GLatLngBounds();
	for (var i=0; i< points.length; i++) {
		points[i] = map.fromContainerPixelToLatLng(points[i]);
		bounds.extend(points[i]);
	}
	points.push(points[0]);
	var polygon = new GPolygon(points, "#ff0000", 1, 1, "#ffffff", 0);
	map.addOverlay(polygon);
	map.setZoom(map.getBoundsZoomLevel(bounds));
	map.setCenter(bounds.getCenter());
	return points;
}

function drawPlayhead(){
	if(typeof(playhead) != "undefined") map.removeOverlay(playhead);
	var points=[o,q];
	for (var i=0; i< points.length; i++) {
		points[i] = map.fromContainerPixelToLatLng(points[i]);
	}
	playhead = new GPolyline(points, "#000000", 2, 1);
	map.addOverlay(playhead);
}

function playNotes(){
	var oqh = Math.sqrt(Math.pow(o.x-q.x, 2) + Math.pow(o.y-q.y, 2));
	var noql = ((o.x*(q.y-n.y)) + (q.x*(n.y-o.y)) + (n.x*(o.y-q.y)))/oqh;
	for(var i=0; i<notes.length; i++){
		if(played_notes[i] < 0){
			var p = new GPoint(notes[i].x, notes[i].y);
			var poql = ((o.x*(q.y-p.y)) + (q.x*(p.y-o.y)) + (p.x*(o.y-q.y)))/oqh;
			if((poql > 0 && noql < 0) || (poql < 0 && noql > 0) || poql == 0){
				played_notes[i] = i;
				var ip = dotLineIntersection(p.x, p.y, n.x, n.y, m.x, m.y);
				var pipl = Math.sqrt(Math.pow(p.x-ip.x, 2) + Math.pow(p.y-ip.y, 2));
				var note_number = Math.floor(pipl/oqh*available_notes.length);
				if(note_number < 0) note_number = 0;
				if(note_number > available_notes.length-1) note_number = available_notes.length-1;
				sounds[available_notes[note_number]].play();
			};
		};
	};
}

function playUnplayedNotes(){
	var oqh = Math.sqrt(Math.pow(o.x-q.x, 2) + Math.pow(o.y-q.y, 2));
	for(var i=0; i<notes.length; i++){
		if(played_notes[i] < 0){
			var p = new GPoint(notes[i].x, notes[i].y);
			played_notes[i] = i;
			var ip = dotLineIntersection(p.x, p.y, n.x, n.y, m.x, m.y);
			var pipl = Math.sqrt(Math.pow(p.x-ip.x, 2) + Math.pow(p.y-ip.y, 2));
			var note_number = Math.floor(pipl/oqh*available_notes.length);
			sounds[available_notes[note_number]].play();
		};
	};
}

function movePlayhead() {
	drawPlayhead();
	playNotes();
	if((playHeadXStep >= 0 && q.x > n.x) || (playHeadXStep < 0 && q.x < n.x)){
		playUnplayedNotes();
		stopScore();
	};
	
	o.x += playHeadXStep;
	q.x += playHeadXStep;
	o.y += playHeadYStep;
	q.y += playHeadYStep;
}

function resetPlayedNotes(){
	for(var x=0; x<notes.length; x++){
		played_notes[x] = -1;
	}
}

function setRoute(){
	$('#play_score').attr("disabled", "disabled");
	$('#save_route').attr("disabled", "disabled");
	notes = [];
	played_notes = [];
	map.clearOverlays();
	gdir = new GDirections(map);
	gdir.load('from: '+$('#start_address').attr('value')+' to: '+$('#end_address').attr('value'), {"getSteps":true, "avoidHighways":($('#avoid_highways').attr('value')=="1")});
	GEvent.addListener(gdir, "addoverlay", getRouteRectangle);
	GEvent.addListener(gdir, "error", noRoute);
}

function noRoute(){
	alert("We were unable to find your route. Please try again.");
}

dotLineIntersection = function(x, y, x0, y0, x1, y1){
    if(!(x1 - x0))
        return {x: x0, y: y};
    else if(!(y1 - y0))
        return {x: x, y: y0};
    var left, tg = -1 / ((y1 - y0) / (x1 - x0));
    return {x: left = (x1 * (x * tg - y + y0) + x0 * (x * - tg + y - y1)) / (tg * (x1 - x0) + y0 - y1), y: tg * left - tg * x + y};
};

function getRouteRectangle(){
	if(gdir.getStatus().code == G_GEO_SUCCESS) {
		var marker_a = gdir.getMarker(0);
		var marker_b = gdir.getMarker(1);
		var marker_a1 = new GMarker(marker_a.getLatLng(), marker_a.getIcon(), true);
		map.addOverlay(marker_a1);
		map.removeOverlay(marker_a);
		var marker_b1 = new GMarker(marker_b.getLatLng(), marker_b.getIcon(), true);
		map.addOverlay(marker_b1);
		map.removeOverlay(marker_b);

		$('#play_score').attr("disabled", "");
		$('#save_route').attr("disabled", "");
		// route
		var groute = gdir.getRoute(0);
		// polyline contains all the points along a route
		var gpoly = gdir.getPolyline();
		// a is the start point of the route: ax is the x coordinate of a; ay is the y coordinate of a
		var a = map.fromLatLngToContainerPixel(groute.getStep(0).getLatLng());
		var b = map.fromLatLngToContainerPixel(groute.getEndLatLng());
		var abl = Math.sqrt(Math.pow(a.x-b.x, 2) + Math.pow(a.y-b.y, 2));
		
		var c = a;
		var d = a;
		var cabl = 0;
		var dabl = 0;
		for(var i=0; i<gpoly.getVertexCount(); i++){
			var p = map.fromLatLngToContainerPixel(gpoly.getVertex(i));
			var pabh = ((a.x*(b.y-p.y)) + (b.x*(p.y-a.y)) + (p.x*(a.y-b.y)))/abl;

			if(pabh > cabl){
				c = p;
				cabl = pabh;
			}
			if(pabh < dabl){
				d = p;
				dabl = pabh;
			}
		};
		
		var ic = dotLineIntersection(c.x, c.y, a.x, a.y, b.x, b.y);
		var id = dotLineIntersection(d.x, d.y, a.x, a.y, b.x, b.y);
		var e = new GPoint(a.x + (d.x - id.x), a.y + (d.y - id.y));
		var f = new GPoint(a.x + (c.x - ic.x), a.y + (c.y - ic.y));
		var g = new GPoint(b.x + (c.x - ic.x), b.y + (c.y - ic.y));
		var h = new GPoint(b.x + (d.x - id.x), b.y + (d.y - id.y));
		
		var efl = Math.sqrt(Math.pow(e.x-f.x, 2) + Math.pow(e.y-f.y, 2));
		var ghl = Math.sqrt(Math.pow(g.x-h.x, 2) + Math.pow(g.y-h.y, 2));
		
		var i = e;
		var j = g;
		var iefl = 0;
		var jghl = 0;
		for(var x=0; x<gpoly.getVertexCount(); x++){
			var p = map.fromLatLngToContainerPixel(gpoly.getVertex(x));
			var pefh = ((e.x*(f.y-p.y)) + (f.x*(p.y-e.y)) + (p.x*(e.y-f.y)))/efl;
			var pghh = ((g.x*(h.y-p.y)) + (h.x*(p.y-g.y)) + (p.x*(g.y-h.y)))/ghl;
			if(pefh > iefl){
				i = p;
				iefl = pefh;
			}
			if(pghh > jghl){
				j = p;
				jghl = pghh;
			}
		};
		
		if(e.equals(i)){
			l = e;
			m = f;
		} else {
			var ii = dotLineIntersection(i.x, i.y, e.x, e.y, f.x, f.y);
			l = new GPoint(e.x + (i.x - ii.x), e.y + (i.y - ii.y));
			m = new GPoint(f.x + (i.x - ii.x), f.y + (i.y - ii.y));
		} 
		
		if(g.equals(j)){
			k = h;
			n = g;
		} else {
			var ij = dotLineIntersection(j.x, j.y, g.x, g.y, h.x, h.y);
			n = new GPoint(g.x + (j.x - ij.x), g.y + (j.y - ij.y));
			k = new GPoint(h.x + (j.x - ij.x), h.y + (j.y - ij.y));
		}
		
		a = map.fromContainerPixelToLatLng(a);
		b = map.fromContainerPixelToLatLng(b);
		var latlngs = makeRectangle([l,m,n,k]);
		a = map.fromLatLngToContainerPixel(a);
		b = map.fromLatLngToContainerPixel(b);
		l = map.fromLatLngToContainerPixel(latlngs[0]);
		m = map.fromLatLngToContainerPixel(latlngs[1]);
		n = map.fromLatLngToContainerPixel(latlngs[2]);
		k = map.fromLatLngToContainerPixel(latlngs[3]);
		var lsp = a;
		notes.push(a);
		for(var i=1; i<groute.getNumSteps()-1; i++){
			var sll = groute.getStep(i).getLatLng();
			var sp = map.fromLatLngToContainerPixel(sll);
			var splspl = Math.sqrt(Math.pow(sp.x-lsp.x, 2) + Math.pow(sp.y-lsp.y, 2));
			var bspl = Math.sqrt(Math.pow(b.x-sp.x, 2) + Math.pow(b.y-sp.y, 2));
			if(splspl > 5 && bspl > 5){
				notes.push(sp);
				map.addOverlay(new GMarker(sll));
				lsp = sp;
			};
		};
		notes.push(b);
		resetPlayedNotes();
		lmh = Math.sqrt(Math.pow(l.x-m.x, 2) + Math.pow(l.y-m.y, 2));
		lmo = Math.abs(l.y-m.y);
		lmt = Math.asin(lmo/lmh);
		var xdir = (n.x > m.x) ? 1: -1;
		var ydir = (n.y > m.y) ? 1: -1;
		playHeadStep = lmh/30;
		playHeadXStep = Math.sin(lmt)*playHeadStep*xdir;
		//layHeadYStep = Math.cos(lmt)*playHeadStep*ydir;
		playHeadYStep = Math.abs((n.y-m.y)/(n.x-m.x))*Math.abs(playHeadXStep)*ydir;
		o = new GPoint(l.x, l.y);
		q = new GPoint(m.x, m.y);
		drawPlayhead();
	} else {
		alert("We were unable to find your route. Please try again.");
	};
}

function playScore(){
	makeScale();	
	animatePlayhead = setInterval("movePlayhead()", 100);
	$('#play_score').attr("disabled", "disabled");
	$('#save_route').attr("disabled", "disabled");
	$('#set_route').attr("disabled", "disabled");
	$('#pause_score').attr("disabled", "");
	$('#stop_score').attr("disabled", "");
}

function pauseScore(){
	clearInterval(animatePlayhead);
	$('#pause_score').attr("disabled", "disabled");
	$('#set_route').attr("disabled", "");
	$('#play_score').attr("disabled", "");
	$('#save_route').attr("disabled", "");
}

function stopScore(){
	clearInterval(animatePlayhead);
	o = new GPoint(l.x, l.y);
	q = new GPoint(m.x, m.y);
	resetPlayedNotes();
	drawPlayhead();
	$('#stop_score').attr("disabled", "disabled");
	$('#pause_score').attr("disabled", "disabled");
	$('#set_route').attr("disabled", "");
	$('#play_score').attr("disabled", "");
	$('#save_route').attr("disabled", "");
}



function createDefaultMap(){
	map = new GMap2(document.getElementById("map"));
	var center = new GLatLng(0, 0);
	map.setCenter(center, 1);
	map.disableDragging();
}

function ajaxSubmitError(XMLHttpRequest, textStatus, errorThrown) {
	alert("Sorry, there was an error while saving your route");
	$('#play_score').attr("disabled", "");
	$('#save_route').attr("disabled", "");
	$('#set_route').attr("disabled", "");
}

function ajaxSubmitSuccess(data) {
	alert("Your route was saved successfully");
	$('#play_score').attr("disabled", "");
	$('#save_route').attr("disabled", "");
	$('#set_route').attr("disabled", "");
}

function saveRoute(){
	var missed_fields = [];
	if($('#start_address').attr('value') == '' || typeof($('#start_address').attr('value')) == 'undefined') missed_fields.push("Start");
	if($('#end_address').attr('value') == '' || typeof($('#end_address').attr('value')) == 'undefined') missed_fields.push("End");
	if($('#name').attr('value') == '' || typeof($('#name').attr('value')) == 'undefined') missed_fields.push("Name");
	if($('#description').attr('value') == '' || typeof($('#description').attr('value')) == 'undefined') missed_fields.push("Description");
	if(missed_fields.length > 0){
		alert('Please fill in the following fields: '+missed_fields.join(', '));
	} else {
		var formdata = $(".music_box_controls").serialize();
		$('#play_score').attr("disabled", "disabled");
		$('#save_route').attr("disabled", "disabled");
		$('#pause_score').attr("disabled", "disabled");
		$('#stop_score').attr("disabled", "disabled");
		$('#set_route').attr("disabled", "disabled");
		$.ajax({
			type: "POST",
			url: "save_route.php",
			data: formdata,
			timeout: 2000,
			error: function (XMLHttpRequest, textStatus, errorThrown) {
				ajaxSubmitError(XMLHttpRequest, textStatus, errorThrown);
			},
			success: function (data) {
				ajaxSubmitSuccess(data);
			}
		});
	};
}

function assignControlFunctions(){
	$('#set_route').click(function(){
		setRoute();
		this.blur();
		return false;
	})
	$('#play_score').click(function(){
		playScore();
		this.blur();
		return false;
	})
	$('#pause_score').click(function(){
		pauseScore();
		this.blur();
		return false;
	})
	$('#stop_score').click(function(){
		stopScore();
		this.blur();
		return false;
	})
	$('#save_route').click(function(){
		saveRoute();
		this.blur();
		return false;
	})
	$('#play_score').attr("disabled", "disabled");
	$('#save_route').attr("disabled", "disabled");
	$('#pause_score').attr("disabled", "disabled");
	$('#stop_score').attr("disabled", "disabled");
	$('#set_route').attr("disabled", "");
}

$(document.body).unload(function() {
	if (GBrowserIsCompatible()) {
		stopScore();
		GUnload();
	}
});

$(document).ready(function(){
	if (GBrowserIsCompatible()) {
		createDefaultMap();
		assignControlFunctions();
	}
});