/************************************************************************
 * 		Hauptklasse	für den Tour Planner								*
 * 		C 2008 by René Lange & Thomas Müller & Steve Rohrlack @ mindbox	*
 ************************************************************************/

var TourPlanner = new Class({
	// Hilfsklassen
	dh : new DataHandler(), 	// Kommunikation mit PHP via JSON
	sb : '',					// StatusBox
	wd : '',					// Bitte Warten Bildschirm
	map: '',
	userStatus: '',
	mm: '',
	mapSelector: 'tpMap',
	
	// Objekthaltung 
	currentTour: new DcTour(),	// aktuell gehaltene Tour
	newTour: new DcTour(),		// neue leere Tour (und Starttour)
	notepadItems: new Array(),	// Items des Notepad
	tourIDs: new Array(),		// Tournamen und ID´s für Notepad
	
	currentTourChanged: false,	// Aktuelle Tour ist geändert -> Speicherabfrage
	currentTourBooked: false,	// Aktuelle Tour wurde gebucht -> erneutes Buchen

	tabs: '',					
	title: 'tourplanner',
	
	// Konstruktor
	initialize: function(){
		TourPlanner.instance = this;
		this.sb = new StatusBox();
		this.wd = new WaitingDiv();
		
		this.userStatus = this.dh.getUserStatus();
		this.map = new HuberMap(this.mapSelector);
		
		// Daten holen
		this.changeCurrentTour('new');
		this.tourIDs = this.dh.getTourIDs();

		// Die Haupttabs erstellen
		var tabArray = new Array();
		tabArray.push(new Editor());
		tabArray.push(new ReadyTours());
		if (this.userStatus == 'true') {
			tabArray.push(new SavedTours()); // Saved Tours nur wenn eingeloggt
		} 
		
		this.tabs = new TabManager(tabArray, {
			'tabList': 'tabNav tpNav',
			'wrapper': 'content-container',
			'tabCon': 'tourplanner'
		});
		
		this.tabs.showTab('editor'); // Editor anzeigen
		this.sendMessage('editor', 'showPlanner'); // danach Planner im Editor anzeigen
		
		this.map.initMap();
		
		this.wd.hide();
	},
	
	/* Hauptfunktionen */
	
	// Neue Tour initialisieren	
	initNewTour : function () {
		this.newTour.title = 'My Tour';
		this.newTour.id_tour = 'newTour';
		this.newTour.length = 1;
		
		var tmpDay = new DcDay(); // 1. Tag
		tmpDay.id_day = 'tmp_0';
		tmpDay.no = 0;
		tmpDay.color = 'blue';
		
		// Memoeinträge in 1. Tag werfen
		var allEntries =  this.dh.getData('', 'readmemo');
		tmpDay.dcEntries = allEntries.entries;
		this.newTour.dcAcco = (allEntries.accomodation ? allEntries.accomodation : new Array());
		this.newTour.dcDays = new Array();
		this.newTour.dcDays.push(tmpDay);
	},
	
	// EventHandler
	sendMessage : function (target, todo, args) {
		if(!args || $type(args) == 'false' || args == 'undefined'){
			args = new Hash();
		}
		switch (target) {
			case this.title: 	this.handleEvent(todo, args);
								break;
			default: 			this.tabs.sendMessage(target, todo, args);		
		}
	},

	// Nachrichten verarbeiten
	handleEvent : function (todo, args) {
		switch (todo) {
			case 'rebuildOn':					this.rebuild = true;
												break;
			case 'rebuildTab':					this.rebuildContent();
												break;		
			case 'showEditor': 					this.tabs.showTab('editor');
												break;
			case 'updatePlannerMap':			this.map.changeTour(this.currentTour);
												break;
			case 'updateDirections': 			this.map.updateGDirs();
												break;
		}
	},

	/* Daten per JSON holen, Speichern und Tourobjekte manipulieren */
	
	// Daten holen
	getData : function (id, todo){
		this.tour = this.dh.getData(id, todo);
	},

	// Einzelnen Entry holen
	getEntry : function (id){
		return this.dh.getData(id, 'singleentry');
	},
	
	// Tour speichern, liefert (evtl neue) ID der Tour zurück
	setTour : function (tour2save) {
		// HTML- und temporäre Informationen werden gelöscht
		var tour = $merge(tour2save);
		
		if(tour.dcDays[0].dcEntries[0].length == 0){
			alert('Your tour is empty');
			return false;
		}
		
		if (tour.tourStart.dcEntries.length > 0) {
			ts = tour.tourStart.dcEntries[0];
			
			if ((ts.id_entry == 'newTour')) {
				ts.id_entry = '';
			}
			ts.name_entry = '';
			ts.id_tour = '';
			ts.city = '';	
			ts.x = '';	
			ts.y = '';	
			ts.price = '';	
			ts.img = '';
			ts.shortDetails = '';
			ts.adressDetails = '';	
		}

		if ((tour.id_tour == 'newTour')) {
			tour.id_tour = '';
		}
		tour.dcDays.each(function(day) {
			if ((day.id_day == 'newTour')) {
				day.id_day = '';
			}
			day.dcEntries.each(function(entry) {
				if ((entry.id_entry == 'newTour')) {
					entry.id_entry = '';
				}
				entry.name_entry = '';
				entry.id_tour = '';	
				entry.city = '';	
				entry.x = '';	
				entry.y = '';	
				entry.price = '';	
				entry.img = '';
				entry.shortDetails = '';
				entry.adressDetails = '';				
			});			
		});

		tour.dcAcco.each(function(entry) {
			if ((entry.id_entry == 'newTour')) {
				entry.id_entry = '';
			}
			entry.name_entry = '';
			entry.id_tour = '';
			entry.city = '';
			entry.x = '';
			entry.y = '';
			entry.price = '';
			entry.img = '';
			entry.shortDetails = '';
			entry.adressDetails = '';
		});
		
		return this.dh.setTour(tour);
	},

	// Neue Tour in current Tour einladen
	changeCurrentTour : function (id, deleteID) {
		if (id == 'new') {
			this.initNewTour();
			this.currentTour = this.newTour;
		} else {
			var currentTours = this.dh.getData(id, 'editor');
			if (currentTours.length == 1) {
				this.currentTour = currentTours[0];
				if (deleteID) {
					this.currentTour.id_tour = '';
					this.currentTour.id_user = '';
					var tmpstr = Date.parse(new Date())/1000;
					var diff = this.currentTour.end - this.currentTour.start;
					this.currentTour.start = tmpstr;
					this.currentTour.end = tmpstr + diff;
					this.currentTour.dcDays.each(function(day) {
						day.id_day = day.id_day
						day.dcEntries.each(function(entry) {
							entry.id_entry = entry.id_entry;				
						}.bind(this));
					}.bind(this));
				}
			}
		}
	},
	
	// Speichern der aktuellen Tour
	saveCurrentTour : function () {
		var id = this.setTour(this.currentTour);
		if (id) {
			this.currentTour.id_tour = id.replace(/\"/g, '');
			this.rebuildSavedTours = true; // Saved Tours und Ready Tours müssen neu laden
			this.currentTourChanged = false;
		}
		return id;
	},
	
	deleteTour : function (id, sender) {
		if (id == 'current') {
			id = this.currentTour.id_tour;
		}

		if (id == 'newTour') {  // neue Touren müssen nicht gelöscht werden
			return false;
		}
	
		this.dh.deleteTour(id);	
		
		// Leere Tour laden, falls aktuelle gelöscht
		if (id == this.currentTour.id_tour) {
			this.changeCurrentTour('new');		
		}
		
		// Anzeigen neu bauen
		this.sendMessage('readytours', 'rebuildTab');
		this.sendMessage('savedtours', 'rebuildTab');
//		this.sendMessage('editor', 'rebuildTab');
		this.map.deleteTour();
	
		switch (sender) {
			case 'savedtours': 	this.tabs.showTab(sender);
								break;
			case 'planner':		this.sendMessage('editor', 'showPlanner');
								break;
		}
		return true;
	},
	
	bookTour : function (tour) {	
		// Ist das Senden sinvoll/möglich
		if(this.currentTour.dcDays[0].dcEntries.length == 0){
			this.sb.showBox('You have no entries in this tour.');
			return false;
		}
		if(this.currentTourBooked && !this.currentTourChanged){
			this.sb.showBox('You have already booked your tour.');
			return false;
		}
		
		// HTML- und temporäre Informationen werden gelöscht
		if (tour.tourStart.dcEntries.length > 0) {		
			ts = tour.tourStart.dcEntries[0];
			
			if ((ts.id_entry == 'newTour')) {
				ts.id_entry = '';
			}
			ts.name_entry = '';
			ts.id_tour = '';	
			ts.city = '';	
			ts.x = '';	
			ts.y = '';	
			ts.price = '';	
			ts.img = '';
			ts.shortDetails = '';
			ts.adressDetails = '';	
		}

		if ((tour.id_tour == 'newTour')) {
			tour.id_tour = '';
		}
		tour.dcDays.each(function(day) {
			if ((day.id_day == 'newTour')) {
				day.id_day = '';
			}
			day.dcEntries.each(function(entry) {
				if ((entry.id_entry == 'newTour')) {
					entry.id_entry = '';
				}
				entry.name_entry = '';
				entry.id_tour = '';	
				entry.city = '';	
				entry.x = '';	
				entry.y = '';	
				entry.price = '';	
				entry.img = '';
				entry.shortDetails = '';
				entry.adressDetails = '';				
			}.bind(this));			
		}.bind(this));
		this.currentTourBooked = true;
		this.dh.bookTour(tour);
		TourPlanner.instance.sb.showBox('An Enquiry for this tour has been sent');
		return true;
	},
	
	/* Hilfsfunktionen */
	
	// Eintrag in der Current Tour verschieben
	updateEntry : function (id, newDay) {
		// zuerst alten Eintrag holen und löschen		
		var entry = this.sliceEntry(id,newDay);
		if (entry == null) { 
			return false;
		}
		
		// Entweder Startpunkt
		if (newDay == -1) {
			this.currentTour.tourStart.dcEntries[0] = entry;
		}		
		// Oder an den neuen Tag hintenanfügen
		else if (this.currentTour.dcDays[newDay].dcEntries.length == 0) {
			// Bei neuen Einträgen sind die Entry Arrays identisch, deswegen wird ein neues erstellt und angehängt
			this.currentTour.dcDays[newDay].dcEntries[0] = entry;			
		} else {
			this.currentTour.dcDays[newDay].dcEntries.push(entry);
		}
	},
	
	// Extrahiert einen Eintrag aus der current tour
	sliceEntry : function (id, newDay) {
		var found = null;
		// Dann in der current tour
		this.currentTour.dcDays.each(function(day) {
			for (var i = 0; i < day.dcEntries.length; ++i) {
				if (day.dcEntries[i].id_entry == id) {
					found = day.dcEntries[i];
					if (newDay != -1 ) {
						day.dcEntries.splice(i, 1);
					}
				}
			}			
		});
			
		if (found != null) {
			return found;			
		}
		
		this.currentTour.dcAcco.each(function(entry) {
			if (entry.id_entry == id) {
				found = entry;
			}	
		});
		
		if (found != null) {
			return found;			
		}
		
		return null;
	},
	
	// Eintrag kopieren
	copyEntry : function (entry1) {
		var entry2 = new DcEntry();
		for (var key in entry1) {
			entry2[key] = entry1[key];
			entry2.id_entry = this.getFreeID();
		}	

		return entry2;
	},
	
	// Freie ID für einen Entry holen
	getFreeID : function () {
		var ok = true;
		do {
			var id = Math.random();
			this.currentTour.dcDays.each(function(day) {
				for (var i = 0; i < day.dcEntries.length; ++i) {
					if (day.dcEntries[i].id_entry == id) {
						ok = false;
					}
				}			
			}.bind(this));			

		} while (!ok);
		return id;
	},
	
	// Anbieter/Angebot löschen 
	removeItem : function (el) {
			var id = el.getProperty('name').replace(/.*\_/,'');
			this.removeElement(id);
	},
	
	// Werte eines Angebotes/Anbieters ändern
	changeValue : function (id, newValue, todo) {
		// Dann im Tour Start
		if (this.currentTour.tourStart.dcEntries.length > 0) {	
			if (this.currentTour.tourStart.dcEntries[0].id_entry == id) {
				switch (todo) {
						case 'tpPersonsOfEntry': this.currentTour.tourStart.dcEntries[0].persons = newValue;
										break;
						case 'tpStayTimeOfEntry': this.currentTour.tourStart.dcEntries[0].stayTime = newValue;
										break;
					}
			}
		}

		// Dann in der current tour
		this.currentTour.dcDays.each(function(day) {
			for (var i = 0; i < day.dcEntries.length; ++i) {
				if (day.dcEntries[i].id_entry == id) {
					switch (todo) {
						case 'tpPersonsOfEntry': day.dcEntries[i].persons = newValue;
										break;
						case 'tpStayTimeOfEntry': day.dcEntries[i].stayTime = newValue;
										break;
					}
				}
			}			
		}.bind(this));		
	},
	
	// Aktualisiert die Distanzen der aktuellen Tour, da sie nur asynchron angefragt werden können
	updateDistances : function () {
		this.sendMessage('overview', 'updateTour');				// Overview
	},	
	
	// Gibt zurück, von wo nach wo eine Tagestour geht
	getStartToEnd : function(i) {
		var to = this.getEnd(i); // Zuerst das Ziel bestimmen (letzter Punkt des Tages)
		
		var from = '';
		if (i > 0) {  // Dann den Ausgangspunkt (= Ziel des Tages i-1)
			from = this.getEnd(i-1);
		}
		
		if (to == '') {
			return to;
		} else if (from == '') {
			return to;
		} else if (from == to) {
			return from;		
		} else {
			return 'From ' + from + ' to ' + to;
		}
	},
	
	// Gibt letztes Ziel eines Tages aus
	getEnd : function (i) {
		var day = this.currentTour.dcDays[i];
		if (day != null) {
			switch(day.dcEntries.length) {
				case 0: 	return ''; // Gar kein Entry an diesem Tag, also nix anzeigen
							break;
				default:	return day.dcEntries.getLast().city;
			}
		}
		return '';		
	},
	
	// Gibt Zeitstring zurück (Stay Time)
	getFormattedTime : function (time) {
		var hours = Math.floor(Number(time)/60/60);
		var minutes = Number(time) % 60;
		
		return hours + ' h ' + minutes + ' min';
	},

	// Gibt Zeitstring zurück (alles Andere)
	getFormattedTimeSeconds : function (time) {
		var hours = Math.floor(Number(time)/3600);
		var minutes = (Math.floor(Number(time)/60))-60*hours;
		
		return hours + ' h ' + minutes + ' min';
	},
	
	// Tag aus Index berechnen
	calcDate : function(day) {		
		var dayCounter = 0;
		for(var i = this.currentTour.start;;i=parseInt(i)+86400) {
			if(dayCounter == day) {
				break;
			}
			dayCounter++;
		}
		
		return convertToDate(i);
	},
	
	// Gibt korrekte Endung der Date für Überschriften
	calcDays : function(tour) {
		var days = tour.dcDays.length;
		if(days == 1) {
			return days + ' Day';			
		} else {
			return days + ' Days';
		}
	},
	
	// Bereichnet Preise aller Einträge einer Tour
	calcAllEntriesPrices : function(tour) {
		var price = 0;
		tour.dcDays.each(function(day){
			day.dcEntries.each(function(entry) {
				price += Number(entry.price);
			}.bind(this));	
		}.bind(this));	
		
		return number_format(price,2,',','');		
	},
	
	// Berechnet die maximale Anzahl an Personen einer Tour
	calcMaxPersons : function(tour) {
		var maxPersons = 0;
		tour.dcDays.each ( function (day){
			day.dcEntries.each( function(entry){
				if(entry.persons > maxPersons) {
					maxPersons = entry.persons;
				}
			});
		});
		return maxPersons;
	},

	
	// Ist ein Objekt in currentTour?
	inCurrentTour : function(id) {
		var ret = false;

		if (this.currentTour.tourStart.dcEntries.length > 0) {	
			if(this.currentTour.tourStart.dcEntries[0].id_sg_entry == id) {
				ret = true;
			}
		}
		
		this.currentTour.dcAcco.each(function(entry) {
			if(entry.id_sg_entry == id) {
				ret = true;	
			}
		});

		this.currentTour.dcDays.each(function(day) {
			day.dcEntries.each(function(entry) {
				if(entry.id_sg_entry == id) {
					ret = true;	
				}
			});
		});
		return ret;
	},
	
	// Fügt ein Element zum Merkzettel hinzu
	addElement : function(id) {
		if (!this.inCurrentTour(id)) {
			var tmpEntry = this.getEntry(id);
			if (tmpEntry != null) {
				if (tmpEntry.category == 'Accomodation') {
					this.currentTour.dcAcco.push(tmpEntry);
					this.sendMessage('editor', 'addElement', new Hash().set('acco',true));
				}else{
					tmpEntry.id_tour = 'currentTour';
					this.currentTour.dcDays[0].dcEntries.push(tmpEntry);
					this.sendMessage('editor', 'addElement', new Hash());
				}
				this.currentTourChanged = true;
			}
		}
		return true;
	},

	// Löscht ein Element aus der Plannerklist
	removeElement : function(id) {		
		if (this.inCurrentTour(id)) {
			
			// entry aus tourstart entfernen
			if (this.currentTour.tourStart.dcEntries[0]) {
				if (this.currentTour.tourStart.dcEntries[0].id_sg_entry == id) {
					this.currentTour.tourStart.dcEntries.splice(0, 1);
					this.sendMessage('editor', 'removeElement', new Hash().set('start', id));
					this.currentTourChanged = true;
				}
			}
			
			// std-entry entfernen
			this.currentTour.dcDays.each(function(day){
				day.dcEntries.each(function(e,i){
						if (e.id_sg_entry == id) {
							day.dcEntries.splice(i, 1);
							this.sendMessage('editor', 'removeElement', new Hash().set('entry', id));
							this.currentTourChanged = true;
						}
				}.bind(this));
			}.bind(this));
			
			// accomodation entfernen
			this.currentTour.dcAcco.each(function(e,i){
					if (e.id_sg_entry == id) {
						this.currentTour.dcAcco.splice(i, 1);
						this.removeAccoFromtourData(id);
						this.sendMessage('editor', 'removeElement', new Hash().set('acco', id));
						this.currentTourChanged = true;
					}
			}.bind(this));
		} 
	},
	
	removeAccoFromtourData: function(id){
		TourPlanner.instance.currentTour.dcDays.each(function(day){
			if(day.id_acco == id){
				day.id_acco = '';
			}
		})		
	},
	
	// Verschiebt einen Eintrag innerhalb eines Tages
	moveElement : function(el){
		var entryId = el.getProperty('name');
		var posInfo = this.getDayOfSelListEntry(el.getParent('.accContentItem'));
		var cDayEntries = this.currentTour.dcDays[posInfo.entryDay].dcEntries;
		var cDayLength = cDayEntries.length;
		
		switch(el.getProperty('class').substr(6)){
			case 'Up':
				var entryBefore = posInfo.entryPos - 1;
				if (!cDayEntries[entryBefore]) {
					return false;
				}
				var tmp = cDayEntries[posInfo.entryPos];
				cDayEntries[posInfo.entryPos] = cDayEntries[entryBefore];
				cDayEntries[entryBefore] = tmp;
				break;
			case 'Down':
				var entryNext = posInfo.entryPos + 1;
				if(!cDayEntries[entryNext]){
						return false;
				}
				var tmp = cDayEntries[posInfo.entryPos];
				cDayEntries[posInfo.entryPos] = cDayEntries[entryNext];
				cDayEntries[entryNext] = tmp;
				break;
		};
		this.currentTour.dcDays[posInfo.entryDay].dcEntries = cDayEntries;
		TourPlanner.instance.currentTourChanged = true;
		return true;
	},	
	
	// Berechnet die Position eines Eintrages im Tag anhand der ID
	getDayOfSelListEntry : function(parent){
		var classData = parent.getProperty('id').split('_');		
		var posInfo = {'entryDay':parseInt(classData[1]),'entryPos':parseInt(classData[2])};
		return posInfo;
	},
	
	// Verschiebt einen Tag im Planner
	changeDayOfEntry : function(el){
		if(el.get('tag') == 'select'){
			var entry_id = el.getProperty('id').replace(/[^_]+_/,'');
			var newDay = el.getProperty('value');
		}

		if(el.get('tag') == 'a'){
			var newDay = -1;
			var entry_id = el.getProperty('name');
		}
		
		this.updateEntry(entry_id, newDay);
		TourPlanner.instance.currentTourChanged = true;
		return newDay;
	},
	
	
	// Ändert Tourname, Titel und Bild einer Tour
	changeValueOfTour : function(el){
		var todo = el.getProperty('name');
		var newValue = el.getProperty('value');
		
		switch(todo) {
			case 'tourName': 
				if (this.currentTour.title != newValue) {
					this.currentTour.title = newValue;
					TourPlanner.instance.currentTourChanged = true;
					$('editorTitle').set('text','Edit Tour - "' + this.currentTour.title + '"');
					return true;
				}
				break;
		}
		return false;
	},
	
	
	//
	changeAccoEntryOfDay: function(el){
		var entry_id = el.get('value');
		var day = el.getProperty('name').replace(/[^_]+_/,'');
		
		this.currentTour.dcDays[day].id_acco = entry_id;
		TourPlanner.instance.currentTourChanged = true;
	},
	

	// Verändert Stay Time und Anzahl Personen eines Entry
	changeValueOfEntry : function(el, todo){
		var entry_id = el.getProperty('name');
		var newValue = el.getProperty('value');
		

		this.changeValue(entry_id, newValue, todo);
		this.currentTourChanged = true;
		return true;
	},
	
	getAccoFromId : function(id_acco, tour) {
		var ret = null;
		tour.dcAcco.each(function(entry) {	
			if (entry.id_entry == id_acco) {
				ret = entry;
			}
		})	
		return ret;
	},
	
	// Logfunktion der Statusbox
	log : function(msg, status){
		if(status){
			switch(status){
				case 'false':
					this.sb.setColor({
						'border' : '2px solid #ff426e',
						'border-right-width' : '0',
						'color' : '#d70033'
					});
			}
		}
		this.sb.showBox(msg);
	}
});