function Destinations() {
	this._search_list = {};
	this._temp_list = {};
	this._pending_list = {};
	this._completed_list = {};
	this._trip_list = {};
	this._pendingTrip_list = {};
	this._premadeTrips = {};
	
	this._search_list_count = 0;
	this._temp_list_count = 0;
	this._pending_list_count = 0;
	this._completed_list_count = 0;
	this._trip_list_count = 0;
	this._pendingTrip_list_count = 0;
	
	this._list_container = 'Destinations';
	this._category_container = 'Category';
}
Destinations.prototype = {
	_selectedDestination:null,
	_list_container:null,
	_startingAddress:null,

	// destination lists
	_search_list:null,
	_pending_list:null,
	_completed_list:null,
	
	// list counts
	_search_list_count: null,
	_pending_list_count: null,
	_completed_list_count: null,
	_trip_list_count: null,
	_pendingTrip_list_count: null,

	// trip builder
	_trip_list:null,
	_pendingTrip_list:null,

	// premade trips
	_premadeTrips:null,
	
	routeTrip: function() {
		var self = this;
		var points = [];

		// interating through DOM to get order
		this.getListContainer('trip').children(this.getListContainer('trip').sortable('option', 'items')).each(function() {
			var destination = self.getDestinationFrom($(this).attr('destination_id'), 'trip');
			points[points.length] = destination.getGLatLng();
		});
		gm.directions(points, this._startingAddress);
	},

	plot: function(tripIdOrListType) {
		var self = this;
		if (typeof(tripIdOrListType) == 'number' && typeof(this._premadeTrips[tripIdOrListType]) != 'undefined') {
			var destinations = this._premadeTrips[tripIdOrListType];
			// select first destination
			if (destinations[0]) {
				destinations[0].select();
			}
		}
		else {
			var destinations = this.getList(tripIdOrListType);
		}
		gm.plotDestinations(destinations);
	},

	isDestinationInList: function(destinationOrId, listType) {
		var id = (typeof(destinationOrId) == 'object') ? destinationOrId.getId() : destinationOrId;
		return (typeof(this.getList(listType)[id]) != 'undefined');
	},

	getSelectedDestination: function() {
		return this._selectedDestination;
	},

	getList: function(type) {
		return this['_' + type +'_list'];
	},
	
	getListCount: function(type) {
		return this['_' + type +'_list_count'];
	},
	
	getPartOfTripCount: function() {
		var count = 0;
		var destinations = this.getList('pending');
		for (var i in destinations) {
			if (destinations[i].isPartOfTrip()) {
				count++;
			}
		}
		return count;
	},
	
	getListContainer: function(type) {
		return $('#' + type + this._list_container);
	},
	
	getCategoryContainer: function(type) {
		return $('#' + type + this._category_container);
	},

	getDestination: function(id) {
		// check all 4 lists for destination, return the first one
		var listTypes = ['search', 'temp', 'pending', 'completed'];
		for (var i = 0; i < listTypes.length; i++) {
			if (this.isDestinationInList(id, listTypes[i])) {
				return this.getDestinationFrom(id, listTypes[i]);
			}
		}
		return false;
	},

	getDestinationFrom: function(id, listType) {
		return this.getList(listType)[id];
	},
	
	getDirections: function() {
		var self = this;
		var ids = [];
		
		// interating through DOM to get order
		this.getListContainer('trip').children(this.getListContainer('trip').sortable('option', 'items')).each(function() {
			var destination = self.getDestinationFrom($(this).attr('destination_id'), 'trip');
			ids[ids.length] = destination.getId();
		});

		if (ids.length > 1 || (this._startingAddress && ids.length > 0)) {
			window.open(BASE_URL + '/destination/directions/' + ids.join(','),null,'status=0,scrollbars=1,toolbar=1,menubar=1,resizable=1,width=786,height=768'); return false;
		}
	},
	
	getSortedList: function(listType, ignorePartOfTrip) {
		// need array to sort
		var tmpDestinations = [];
		var destinations = this.getList(listType);
		for (var i in destinations) {
			if (ignorePartOfTrip) {
				tmpDestinations[tmpDestinations.length] = destinations[i];
			}
			else if (!destinations[i].isPartOfTrip()) {
				tmpDestinations[tmpDestinations.length] = destinations[i];
			}
		}
		tmpDestinations.sort(function(a, b) {
			a = a.getName().toLowerCase();
			b = b.getName().toLowerCase();
			if (a > b) return 1;
			if (a < b) return -1;
			return 0;
		});
		return tmpDestinations;
	},

	addToPreMadeTrip: function(id, destination) {
		if (destination) {
			destination.setContainer($('#preMadeTrip' + id + ' .' + destination.getUId()));
			if (!this._premadeTrips[id]) {
				this._premadeTrips[id] = [];
			}
			this._premadeTrips[id][this._premadeTrips[id].length] = destination;
		}
	},
	
	getDestinationsFromPreMadeTrip: function(id) {
		return this._premadeTrips[id];
	},
	
	addTripDestinationsToPending: function(id) {
		if (typeof(this._premadeTrips[id]) != 'undefined') {
			var destinations = this._premadeTrips[id];
			for (var i in destinations) {
				destinations[i].save();
			}
		}
	},

	addDestination: function(jsonInfo, type) {
		var destination = new Destination(jsonInfo, this, type);
		this['_' + type +'_list_count']++;
		this.getList(type)[destination.getId()] = destination;
		this.toggleListVisibility(destination);
		return destination;
	},

	removeDestination: function(destination) {
		var type = destination.getType();
		// keep a copy in case of deletetion
		if (type == 'pending' && !this.isDestinationInList(destination, 'temp')) {
			this.copyDestinationTo(destination, 'temp', true);
		}

		if ((type != 'trip' && type != 'pendingTrip') && this.isDestinationInList(destination, 'trip')) {
			this.removeDestinationHelper(this.getDestinationFrom(destination.getId(), 'trip'));
		}

		if (this.isDestinationInList(destination, type)) {
			this.removeDestinationHelper(destination);
		}
		
		this.toggleListVisibility(destination);
	},
	
	removeDestinationHelper: function(destination, dataOnly) {
		if (!dataOnly) {
			destination.getContainer().remove();
		}
		var destinations = this.getList(destination.getType());
		this['_' + destination.getType() +'_list_count']--;
		destinations[destination.getId()] = null;
		delete(destinations[destination.getId()]);
	},
	
	copyDestinationTo: function(destination, listType, copyOnly) {
		var newContainer = destination.getClonedContainer();
		if (!copyOnly) {
			if (listType == 'pending') {
				newContainer.appendTo(this.getCategoryContainer('pending'));
			}
			else {
				newContainer.appendTo(this.getListContainer(listType));
			}
		}
		return this.addDestination(destination.getInfo(), listType).setType(listType).setContainer(newContainer);
	},
	
	moveDestinationTo: function(destination, list) {
		this.copyDestinationTo(destination, list);
		this.removeDestination(destination);
	},
	
	destinationSelected: function(destination) {
		if (this._selectedDestination && this._selectedDestination != destination) {
			this._selectedDestination.deselect();
		}
		this._selectedDestination = destination;
	},
	
	destinationDeselected: function(destination) {
		if (this._selectedDestination == destination) {
			this._selectedDestination = null;
		}
	},
	
	resetSelectedDestination: function() {
		// each time the map changes, remove selected destination
		if (selected = this.getSelectedDestination()) {
			selected.deselect();
			$('#destinationDetailsContainer').empty()
		}
	},
	
	setStartingAddress: function(address) {
		this._startingAddress = address;
	},
	
	clearList: function(listType) {
		this['_' + listType +'_list'] = {};
		this['_' + listType +'_list_count'] = 0;
		this.getListContainer(listType).empty();
		
		// toggle result instructions on empty
		if (listType == 'search') {
			$('#searchDestinationWrapper').hide();
			$('#searchInstructions').show();
		}
	},
	
	sortList: function(listType) {
		var destinations = this.getSortedList(listType);
		var parity = 0;
		for (var i in destinations) {
			destinations[i].getContainer().appendTo(destinations[i].getContainer().parent().get(0));
			destinations[i].getContainer().removeClass('odd').addClass((++parity % 2 == 0) ? 'even': 'odd');
		}
	},

	setupBuilder: function() {
		var self = this;

		this.getListContainer('trip').sortable({
			items: 'div.destination',
			axis: 'y',
			handle: '.dragme',
			update: function(event, ui) { self.fixDirectionsParity(); self.routeTrip(); }
		}).disableSelection();

		this.clearList('pendingTrip');
		this._pendingTripBackup_list = [];
		this._setupBuilderHelper('pending');
		this._setupBuilderHelper('completed');
		this.routeTrip();
		this.directionsInstructionsToggle();
	},
	
	_setupBuilderHelper: function(listType) {
		var self = this;
		var destinations = this.getSortedList(listType, true);
		for (var i in destinations) {
			var destination = destinations[i];
			makeHeader(destination);
			var newDestination = this.copyDestinationTo(destination, 'pendingTrip');

			if (this.isDestinationInList(destination, 'trip')) {
				newDestination.getContainer().hide();
			}
		}

		function makeHeader(destination) {
			var type = (destination.isPartOfTrip()) ? 'current' : destination.getType();
			if (self.getListContainer('pendingTrip').children('h3.' + type).length == 0) {
				$("<h3 class='" + type + "'>" + type + "</h3>").appendTo(self.getListContainer('pendingTrip'));
			}
		}
	},
	
	removeDestinationFromTrip: function(destination) {
		this.removeDestination(destination);
		$(this.getListContainer('pendingTrip').children('[destination_id="' + destination.getId() + '"]')).show();
	},
	
	setClassToDestinations: function(listType) {
		var destinations = this.getList(listType);
		for (var i in destinations) {
			destinations[i].setClass(listType);
		}
	},
	
	toggleListVisibility: function(destination) {
		var type = destination.getType();

		if (type == 'completed' || type == 'pending') {
			type = (type == 'pending' && destination.isPartOfTrip()) ? 'trip' : type;
			switch (type) {
				case 'pending':
					var count = this.getListCount(type) - this.getPartOfTripCount();
				break;
				case 'trip':
					var count = this.getPartOfTripCount();
				break;
				default:
					var count = this.getListCount(type);
				break;
			}

			var categoryContainer = (type == 'completed') ? this.getListContainer(type) : this.getCategoryContainer(type);
			if (count > 0 && categoryContainer.is(':hidden')) {
				categoryContainer.show();
			}
			else if (count == 0 && categoryContainer.is(':visible')) {
				categoryContainer.hide();
				ViewManager.showStep(2);
			}

			var userDestinationsElt = $('#userDestinations');
			var userHasDestinations = (this.getListCount('completed') + this.getListCount('pending')) > 0;
			if (userDestinationsElt.is(':hidden') && userHasDestinations) {
				$('#listInstructions').hide();
				userDestinationsElt.show();
			}
			else if (userDestinationsElt.is(':visible') && !userHasDestinations) {
				userDestinationsElt.hide();
				$('#listInstructions').show();
			}
		}
		else if (type == 'search') {
			var count = this.getListCount(type);
			if (count > 0) {
				$('#searchDestinationWrapper').show();
				$('#searchInstructions').hide();
			}
			else {
				$('#searchDestinationWrapper').hide();
				$('#searchInstructions').show();
			}
		}
	},
	
	updateListWith: function(listType, html) {
		this.getListContainer(listType).html(html);
	},
	
	fixDirectionsParity: function() {
		var i = 1;
		this.getListContainer('trip').children('.destination').each(function() {
			$(this).find(".icon").css('background-image', 'url(http://maps.google.com/intl/en_us/mapfiles/icon_green' + String.fromCharCode(64 + i) + '.png)');
			if (i % 2 == 0) {
				$(this).addClass('even');
				$(this).removeClass('odd');
			}
			else {
				$(this).addClass('odd');
				$(this).removeClass('even');
			}
			i++;
		});
		
		var i = 0;
		this.getListContainer('pendingTrip').children().each(function() {
			if ($(this).hasClass('destination')) {
				if ($(this).is(':visible')) {
					i++;
				}
				if (i % 2 == 0) {
					$(this).addClass('even');
					$(this).removeClass('odd');
				}
				else {
					$(this).addClass('odd');
					$(this).removeClass('even');
				}
			}
			else {
				i = 0;
			}
		});
	},
	
	directionsInstructionsToggle: function() {
		if (this.getListCount('trip') == 0) {
			$('#directionInstructions').show();
			$('#tripBuilderCol2').hide();
			$('#tripDetailsContainer').hide();
			ViewManager.showStep(4);
		}
		else {
			$('#directionInstructions').hide();
			$('#tripBuilderCol2').show();
		}
	}
};