// To create our namespace
var Mobileguide = {};

// This is our class creation function
Mobileguide.klass = function() {
  return function(){
    if( this.init ) {
      return this.init.apply(this, arguments);
    } else {
      throw 'Cannot have a Mobileguide class without an init function...';
    }
  };
};

Mobileguide.extend = function(inherited, base) {
  for (var prop in base) {
    inherited[prop] = base[prop];
  }
  return inherited;
};

// "2010-04-22T17:00:00.000Z"
Mobileguide.parseDate = function( dateStr ) {
	var date = dateStr.substring(0, dateStr.indexOf("T"));
	var temp = new Array();
	temp = date.split("-");
	var year = temp[0];
	var month = parseInt(temp[1])-1;
	var day = temp[2];
	
	var time = dateStr.substring(dateStr.indexOf("T")+1, dateStr.indexOf("."));
	temp = new Array();
	temp = time.split(":");
	var hours = temp[0];
	var minutes = temp[1];
	
	return new Date(year, month, day, hours, minutes, 0, 0);
};

Mobileguide.prettyDateInterval = function( startDate, endDate ) {
   	var startFormatted = startDate.formatDate("ddd dd.MMM");
   	var endFormatted = endDate.formatDate("ddd dd.MMM");
	        	
   	var dateStr = "";
   	if ( startFormatted == endFormatted ) {
   		dateStr = startFormatted + " kl. " + startDate.formatDate("HH:mm") + " - " + endDate.formatDate("HH:mm");
   	} else {
   		dateStr = startFormatted + " kl. " + startDate.formatDate("HH:mm")
   			+ " - "
   			+ endFormatted + " kl. " + endDate.formatDate("HH:mm");
   	}
   	return dateStr;
};

var MobileguideHasher = Mobileguide.klass();

MobileguideHasher.prototype = {
	init: function() {
		this.parseHash(location.hash);
	},
	
	parseHash: function( hash ) {
		var map = new Array();
		if ( hash != null && hash != '' && hash != '#' ) {
			hash = hash.substring(1);
			var pairs = hash.split("&");
			for ( var i = 0; i < pairs.length; i++ ) {
				var pair = pairs[i].split("=");
				if ( pair.length > 1 ) {
					map[pair[0]] = pair[1];
				} else {
					map[pair[0]] = "";
				}
			}
		}
		this.params = map;
	},
	
	toHash: function() {
		var hash = "#";
		for ( var key in this.params ) {
			if ( this.params[key] != '' && this.params[key] != null ) {
				if ( hash != '#' ) {
					hash += "&";
				}
				hash += key + "=" + this.params[key];
			} else if ( this.params[key] == '' ) {
				if ( hash != '#' ) {
					hash += "&";
				}
				hash += key;
			}
		}
		return hash;
	},
	
	hasParam: function( key ) {
		return this.params[key] != undefined 
			&& this.params[key] != null 
			&& this.params[key] != '';
	},
	
	getParam: function( key ) {
		return this.params[key];
	},
	
	setParam: function( key, value ) {
		this.params[key] = value;
	},
	
	removeParam: function( key ) {
		this.params[key] = null;
	}
};

/* ===============================================================
 *   Base widget for Lists of Records
 * ===============================================================
 */
var MobileguideBaseListWidget = Mobileguide.klass();

MobileguideBaseListWidget.prototype = {

	setUp : function() {
		var selfRef = this;
		$(window).bind( 'hashchange', function(){
			// called every time the hash changes
			selfRef.processHash();
		});
	},
	
	processHash: function() {
		var selfRef = this;
		var hasher = new MobileguideHasher();
		if ( hasher.hasParam('rid') ) {
			// display a record
			this.detailWidget.displayRecord(hasher.getParam('rid'), this.apiKey, function() {
				selfRef.getList();
			});
		} else {
			// display the list
			selfRef.getList();
		}
	},

	getDetailLink: function( rid, value ) {
		var hasher = new MobileguideHasher();
		hasher.setParam("rid", rid);
		return $("<a/>")
			.attr("href", hasher.toHash())
			.append(value);
	},
	
	render: function() {
		this.processHash();
	},
	
	getList: function() {
		alert("getList() not implemented!");
	}
}

/* ===============================================================
 *   Record Details
 * ===============================================================
 */
var MobileguideRecordDetailWidget = Mobileguide.klass();

MobileguideRecordDetailWidget.prototype = {

	init: function( l, p, cid ) {
		this.lang = l;
		this.packageId = p;
		this.containerId = cid;
		this.baseURL = "http://api.mobileguide.is/feed/" + l + "/packages/" + p + "/records/";
		this.displayMap = true;
		this.displayImg = true;
		this.layoutType = 1;
	},
	
	displayRecord : function( id, apiKey, backListener ) {
		var url = this.baseURL 
			+ id 
			+ "?apiKey=" + apiKey 
			+ "&width=320"
			+ "&jsoncallback=?";
		var selfRef = this;
		var container = $(this.containerId);
		container.children().remove();
		
		$.getJSON(url, function(r){
        	var div = $("<div/>").attr("class", "mobileguide-record-details");
        	container.append(div);
        	
        	div.append(
           		$("<h2/>").append(r.title)
           	);
        	
        	var primaryDiv = $("<div/>").attr("class", "primary");
        	div.append(primaryDiv);
        	
        	var secondaryDiv = $("<div/>").attr("class", "secondary");
        	div.append(secondaryDiv);
           	
            if ( r.description != '' ) {
	           	primaryDiv.append(
	           		$("<p/>").append(r.description)
	           	);
	        }
	        
	        if ( selfRef.displayImg && r.image ) {
	        	var imgDiv = $("<div/>").attr("class","imgContainer").append(
	        		$("<img/>").attr("src",r.image.url + "?apiKey=" + apiKey)
	        	);
	        	if ( selfRef.layoutType == 1 ) {
		        	secondaryDiv.append(imgDiv);
		        } else {
		        	primaryDiv.append(imgDiv);
		        }
	        }
	        
	        if ( r.dateInterval ) {
	        	var startDate = new Date(r.dateInterval.startDateAndTime.milliseconds);
	        	var endDate = new Date(r.dateInterval.endDateAndTime.milliseconds);
	        	
	        	var dateStr;
	        	if ( r.dateInterval.onSameDay == true ) {
	        		dateStr = startDate.formatDate("ddd dd.MMM")
	        			+ " " + startDate.formatDate("HH:mm") + " - " + endDate.formatDate("HH:mm");
	        			;
	        	} else {
	        		dateStr = startDate.formatDate("ddd dd.MMM HH:mm") + " - " + endDate.formatDate("ddd dd.MMM HH:mm");
	        	}
	        
	        	primaryDiv.append(
	        		$("<div/>").attr("class", "dateInterval")
	        			.append($("<h3>Hvenær</h3>"))
	        			.append($("<p/>").append(dateStr))
	        	);
	        }
	        
	        if ( r.location ) {
	        	primaryDiv.append(
	        		$("<div/>").attr("class", "location")
	        			.append($("<h3>Hvar</h3>"))
	        			.append($("<p/>").attr("class","title").append(r.location.name))
	        			.append($("<p/>").attr("class","street").append(r.location.street))
	        			.append($("<p/>").attr("class","city").append(r.location.postCode + " " + r.location.city))
	        	);
	        }
	        
        	if ( selfRef.displayMap && r.location && r.location.coordinates ) {
        		secondaryDiv.append(
        			$("<div/>").attr("class","mapContainer").append(
        				$("<div/>").attr("id","mobileguide_map_canvas")
        			)
        		);
			    var latlng = new google.maps.LatLng(r.location.coordinates.latitude, r.location.coordinates.longitude);
			    var myOptions = {
			      zoom: r.location.coordinates.mapZoomLevel,
			      center: latlng,
			      mapTypeId: google.maps.MapTypeId.ROADMAP
			    };
			    var mapCanvas = document.getElementById("mobileguide_map_canvas");
			    var map = new google.maps.Map(mapCanvas, myOptions);
   
		    	var marker = new google.maps.Marker({
		        	position: latlng, 
		        	map: map,
		        	title:r.location.name
		    	});  
        	}
	        
	        var hasher = new MobileguideHasher();
	        hasher.removeParam("rid");
	        
			var backLink = $("<a/>")
				.attr("href", hasher.toHash())
				.attr("class", "backLink")
				.append("Til baka");
			
			div.append(backLink);
		});
	}
}

/* ===============================================================
 *   Search Results
 * ===============================================================
 */
var MobileguideSearchResultsWidget = Mobileguide.klass();

MobileguideSearchResultsWidget.prototype = {

	init: function( l, p, cid ) {
		this.lang = l;
		this.packageId = p;
		this.containerId = cid;
		this.baseURL = "http://api.mobileguide.is/feed/" + l + "/packages/" + p + "/search";
		this.startIndex = 0;
		this.resultSize = 10;
		this.sortField = "date";
		this.query = "";
		this.category = "";
		this.day = null;
		this.detailWidget = new MobileguideRecordDetailWidget(l, p, cid);
	},
	
	getURL : function() {
		var url = this.baseURL 
			+ "?apiKey=" + this.apiKey 
			+ "&sort=" + this.sortField
			+ "&startIndex=" + this.startIndex 
			+ "&resultSize=" + this.resultSize
			+ "&jsoncallback=?";
		if ( this.query != '' ) {
			url += "&q=" + this.query;
		}
		if ( this.category != '' ) {
			url += "&c=" + this.category;
		}
		if ( this.day != null ) {
			url += "&day=" + this.day.formatDate("yyyy-MM-dd");
		}
		return url;
	},
	
	search: function() {
		var container = $(this.containerId);
		var apiKey = this.apiKey;
		var resultSize = this.resultSize;
		var selfRef = this;
		this.startIndex = 0;
		
		// clear the container
		container.children().remove();
		
		var moreBtn = $("<input/>")
			.attr("type","button")
			.attr("value","Sækja fleiri færslur")
			.click(function() {
				selfRef.startIndex += 10;
				$.getJSON(selfRef.getURL(), function(data) {
	    		    $.each(data.records, function(i,r) {
        		    	var div = createRecordDiv(r);
        		    	moreBtn.before(div);
        		  	});
        		  	if ( data.totalHits <= (selfRef.startIndex + selfRef.resultSize) ) {
        		  		moreBtn.remove();
        		  	}
				});
			});

		var createRecordDiv = function( r ) {
	        	var div = $("<div/>").attr("class", "mobileguide-record");
	        	div.append(
            		$("<h2/>").append(r.title).click(function(){
            			selfRef.detailWidget.displayRecord(r.recordId, selfRef.apiKey, function() {
            				selfRef.search();
            			});
            		})
            	);

            	if ( r.location ) {
            		div.append(
            			$("<div/>").attr("class", "location").append(r.location.name)
            		);
            	}
            	if ( r.startDate && r.endDate ) {
            		var startDate = Mobileguide.parseDate(r.startDate);
            		var endDate = Mobileguide.parseDate(r.endDate);
            		div.append(
            			$("<div/>").attr("class", "dateAndTime")
            				.append(Mobileguide.prettyDateInterval(startDate, endDate))
            		);
            	}
            	
            	if ( r.desc != '' ) {
	            	div.append(
	            		$("<p/>").append(r.desc)
	            	);
	            }
	            
	            /*
	            div.append($("<a/>").click(function() {
            		selfRef.detailWidget.displayRecord(r.recordId, selfRef.apiKey, function() {
            			selfRef.search();
            		});
	            }).append("Nánari upplýsingar"));
	            */
	            
	            return div;
		};
		
		$.getJSON(selfRef.getURL(),
        function(data){
	        $.each(data.records, function(i,r) {
            	var div = createRecordDiv(r);
            	div.appendTo(container);
          	});
          	if ( data.totalHits > resultSize ) {
	          	container.append(moreBtn);
	        }
        });
	}
}

/* ===============================================================
 *   Search Form
 * ===============================================================
 */
var MobileguideSearchInputWidget = Mobileguide.klass();

MobileguideSearchInputWidget.prototype = {

	init: function( resultsWidget ) {
		this.resultsWidget = resultsWidget;
		this.containerId = "#mobileguideSearchForm";
	},

	getList: function() {
		var url = this.resultsWidget.baseURL 
			+ "?apiKey=" + this.resultsWidget.apiKey 
			+ "&startIndex=0"
			+ "&resultSize=1"
			+ "&jsoncallback=?";
	
		var container = $(this.containerId);
		var div = $("<div/>").attr("class", "mobileguide-searchform");
		
		var queryBox = $("<input/>").attr("class", "queryBox");
		queryBox.keyup(function(event) {
			if ( event.keyCode == 13 ) {
				doSearch();
			}
		});
		var searchBtn = $("<input/>").attr("type", "button").attr("class","searchBtn").attr("value", "Leita");
		searchBtn.click(function() {doSearch();});
		var doSearch = function() {
			resultsWidget.query = queryBox.val();
			resultsWidget.category = catList.val();
			resultsWidget.day = dateBox.datepicker("getDate");
			resultsWidget.search();
		};
		var catList = $("<select/>").attr("class","categoryList");
       	catList.change(function() {
       		doSearch();
       	});
		var dateBox = $("<input/>").attr("class", "dateBox").datepicker({ dateFormat: 'dd.mm.yy' });
		dateBox.change(function() {
       		doSearch();
       	});
		
		$.getJSON(url,
        function(data){
        	var p = data.package;
        	
        	catList.append($("<option/>").attr("value", "").append("Allir flokkar"));
        	for ( var c = 0; c < p.categories.length; c++ ) {
        		catList.append(
        			$("<option/>").attr("value", p.categories[c].id).append(p.categories[c].title)
        		);
        	}
        	
        	div.append($("<div/>").attr("class","queryContainer").append("<label>Leitarorð:</label>").append(queryBox).append(searchBtn));
        	div.append($("<div/>").attr("class","categoryBoxContainer").append("<label>Flokkur:</label>").append(catList));
        	div.append($("<div/>").attr("class","dateBoxContainer").append("<label>Dagur:</label>").append(dateBox));
			div.appendTo(container);
        });
	}
};

/* ===============================================================
 *   Event List
 * ===============================================================
 */

var MobileguideEventListWidget = Mobileguide.klass();
Mobileguide.extend(MobileguideEventListWidget.prototype, MobileguideBaseListWidget.prototype);

Mobileguide.extend(MobileguideEventListWidget.prototype, {

	init: function( l, p, cid ) {
		this.lang = l;
		this.packageId = p;
		this.containerId = cid;
		this.resultSize = 400;
		this.baseURL = "http://api.mobileguide.is/feed/" + l + "/packages/" + p + "/search";
		this.detailWidget = new MobileguideRecordDetailWidget(l, p, cid);
		this.setUp();
	},
	
	getList : function() {
		var container = $(this.containerId);
		var selfRef = this;
			
		// clear the container
		container.children().remove();
	
		var url = this.baseURL
			+ "?apiKey=" + this.apiKey 
			+ "&t=EVENT"
			+ "&sort=date"
			+ "&startIndex=0"
			+ "&resultSize=" + this.resultSize
			+ "&jsoncallback=?";

		$.getJSON(url,
        function(data){
        	var lastDateHeader = null;
	        $.each(data.records, function(i,r) {
		        var div = $("<div/>").attr("class", "mobileguide-eventlist");
            	var startDate = Mobileguide.parseDate(r.startDate);
            	var endDate = Mobileguide.parseDate(r.endDate);
            	
            	var dateHeader = startDate.formatDate("ddd dd.MMM");
            	
            	if ( dateHeader != lastDateHeader ) {
            		div.append($("<div/>")
            			.attr("class", "dateHeader")
            			.append(dateHeader));
            	}
            	lastDateHeader = dateHeader;
            	
            	var time = startDate.formatDate("HH:mm") + " - " + endDate.formatDate("HH:mm");
            	
            	div.append(
            		$("<div/>")
            			.attr("class", "event")
            			.append(
            				$("<span/>").attr("class", "time").append(time)
            			)
            			.append(
            				$("<span/>").attr("class", "title")
            				.append( selfRef.getDetailLink(r.recordId, r.title) )
            			)
            	);
            	
            	div.appendTo(container);
          	});
        });
	}
});


Date.prototype.formatDate = function(format)
{
    var date = this;
    if (!format)
      format="MM/dd/yyyy";               
 
    var month = date.getMonth() + 1;
    var year = date.getFullYear();
    
    var weekdays = ["Sunnudagur","Mánudagur","Þriðjudagur","Miðvikudagur","Fimmtudagur","Föstudagur","Laugardagur","Sunnudagur"];
    var dayName = weekdays[date.getDay()];
    
    var months = ["janúar", "febrúar", "mars", "apríl", "maí", "júní", "júlí", "ágúst", "september", "október", "nóvember", "desember"];
    var monthName = months[date.getMonth()];
 
 	format = format.replace("MMM", "XXX");
    format = format.replace("MM",month.toString().padL(2,"0"));        
 
    if (format.indexOf("yyyy") > -1)
        format = format.replace("yyyy",year.toString());
    else if (format.indexOf("yy") > -1)
        format = format.replace("yy",year.toString().substr(2,2));
 
 	format = format.replace("ddd", "YYY");
    format = format.replace("dd",date.getDate().toString().padL(2,"0"));
 
    var hours = date.getHours();       
    if (format.indexOf("t") > -1)
    {
       if (hours > 11)
        format = format.replace("t","pm")
       else
        format = format.replace("t","am")
    }
    if (format.indexOf("HH") > -1)
        format = format.replace("HH",hours.toString().padL(2,"0"));
    if (format.indexOf("hh") > -1) {
        if (hours > 12) hours - 12;
        if (hours == 0) hours = 12;
        format = format.replace("hh",hours.toString().padL(2,"0"));        
    }
    if (format.indexOf("mm") > -1)
       format = format.replace("mm",date.getMinutes().toString().padL(2,"0"));
    if (format.indexOf("ss") > -1)
       format = format.replace("ss",date.getSeconds().toString().padL(2,"0"));
       
    format = format.replace("XXX", monthName);
    format = format.replace("YYY", dayName);
       
    return format;
}

String.repeat = function(chr,count)
{    
    var str = ""; 
    for(var x=0;x<count;x++) {str += chr}; 
    return str;
}
String.prototype.padL = function(width,pad)
{
    if (!width ||width<1)
        return this;   
 
    if (!pad) pad=" ";        
    var length = width - this.length
    if (length < 1) return this.substr(0,width);
 
    return (String.repeat(pad,length) + this).substr(0,width);    
}    
String.prototype.padR = function(width,pad)
{
    if (!width || width<1)
        return this;        
 
    if (!pad) pad=" ";
    var length = width - this.length
    if (length < 1) this.substr(0,width);
 
    return (this + String.repeat(pad,length)).substr(0,width);
} 