(function($) {
	$.fn.Directory = function(options) {
		// plugin defaults	
		var defaults = {
			limit: 25,
			total: 0,
			offset: 0,
			entries: [],
			basePath: '',
			dataSource: '/archive/json',
			onJsonComplete: onJsonComplete,
			onPreviewComplete: onPreviewComplete
		};
		// merge passed options
		if (options) {
			$.extend(defaults, options);
		}
		// cycle through matched elements
		return this.each(function() {
			var self  = this;
			var $this = $(self);
			var $tags = $('.tags a');
			
			$this.data('options', defaults);
			$this.data('tags',[]);
			$this.data('hasLoaded', false);
			
			$this.data('loader', $('<div>').attr('id', 'loader').html('LOADING'));
			$this.data('dirAll', $('<div>').attr('id','dir-all'));
			$this.data('dirTag', $('<div>').attr('id','dir-tag').hide());
			$this.data('dirPreview', $('<div>').attr('id','dir-preview').hide());
			
			$this.append($this.data('dirAll'));
			$this.append($this.data('dirTag'));
			$('#main').append($this.data('dirPreview'));
			$('#container').hide();
								
			$.address.change($.proxy(onAddressChange, this));				
			$(window).scroll($.proxy(onScroll, self));
			$tags.click($.proxy(onTagClick, self));
			
			$('#preview-close').live('click', $.proxy(onClosePreview, self));
			$('#preview-prev').live('click', $.proxy(onPrevPreview, self));
			$('#preview-next').live('click', $.proxy(onNextPreview, self));
			
			$.proxy(requestJson, self)();
		});
	};
	/*******************************************
	 *	Startup
	 *******************************************/
	 function setInitialState() {
	 	// activate tags
	 	var $tags = $('.tags a');
	 	$tags.each(function() {
	 		var $a = $(this);
	 		var tags = getTags();
	 		for(var i = 0; i < tags.length; i++) {
	 			if($a.data('tag') == tags[i]) {
	 				$a.addClass('active');
	 			}
	 		}
	 	});
	 	if($.address.parameter('entry')) {
	 		$('.item[href="'+$.address.parameter('entry')+'"]').trigger('click', this);
	 	}
	 }
	/**
	 * request json data
	 */
	function requestJson() {
		var self = this;
		var options = $(this).data('options');
		$.proxy(toggleLoader, self)();
		$.ajax({
			url: options.dataSource + "/" + options.entries.join("|"),
			dataType: 'json',
			context: self,
			success: options.onJsonComplete
		});
	}
	/**
	 * on request success
	 * @param Object data
	 * @param String status
	 * @param Object xhr
	 */
	 function onJsonComplete(data, status, xhr) {
	 	var $this = $(this);
	 	var media = data.media;
	 	$this.data('media', media);
	 	$this.data('hasLoaded', true);
	 	$.address.update();
	 	$.proxy(toggleLoader, this)();
	 	$.proxy(nextPage, this)();
	 	$.proxy(setInitialState, this)();
	 }
	 /**
	  * On page load
	  * @param Event e
	  */
	 function onAddressChange(e) {
	 	var $this = $(this);
	 	if($this.data('hasLoaded')) {
			$.proxy(filterPage, this)();
			if($.address.parameter('entry')) {
				$.proxy(requestPreview, this)();
			} else {
				$('#container').show();
			}
		}
	 }
	/*******************************************
	 *	Preview
	 *******************************************/
	 /**
	  * Request preview data
	  */
	 function requestPreview() {
	 	var self = this;
	 	var options = $(this).data('options');
	 	$.proxy(toggleLoader, self)();
	 	$.ajax({
	 		url: options.basePath + "/" + $.address.parameter('entry'),
	 		dataType: 'html',
	 		context: self,
	 		success: options.onPreviewComplete
	 	});
	 }
	 /**
	  * on request success
	  * @param Object data
	  * @param String status
	  * @param Object xhr
	  */
	  function onPreviewComplete(data, status, xhr) {
			var $this = $(this);
			$this.data('dirPreview').html(data);
			if($(this).data('prev') < 0 || $this.data('media').length == 1) {
				$('#preview-prev').hide();
			}
			if($(this).data('next') >= $this.data('media').length || $this.data('media').length == 1) {
				$('#preview-next').hide();
			}
			$.proxy(showPreview, this)();
			$.proxy(toggleLoader, self)();
	  }
	/*******************************************
	 *	Filtering
	 *******************************************/
	/**
	 * Get current filters
	 * @return Array
	 */
	function getTags() {
		var tags = $.address.parameter('tags');
		if($.isArray(tags)) {
			return tags;
		} else if(tags) {
			return [tags];
		}
		return [];
	}
	/**
	 * filter items
	 */
	function filterPage() {
		var $this = $(this);
		var media = $this.data('media');
		// get the selected filters
		var filters = getTags();
		// if something is selected
		if(filters.length > 0) {
		
			// setup elements during filtering
			$this.data('dirTag').empty();
			$.proxy(showTagged, this)();
			$.proxy(toggleLoader, this)();
			
			// iterate through media
			var total = 0;
			for(var i = 0; i < media.length; i++) {
				var found = 0;
				for(var j = 0; j < filters.length; j++) {
					// if the tag is found
					if(media[i].keywords.join(',').indexOf(filters[j]) > -1) {
						found++;
					}
				}
				// if all selected filters are found
				if(found == filters.length) {
					total++;
					var $a = createItem(media[i], i, this);
					$this.data('dirTag').append($a);
				}
			}
			$.proxy(toggleLoader, this)();
			if(total == 0) {
				$this.data('dirTag').html("No results found.");
			}
		} else {
			$.proxy(showAll, this)();
		}
/* 
	 	$(".item img").lazyload({
	 		effect : "fadeIn",
	 		threshold : 200,
	 		event: "scrollstop" 
	 	});
 */
		
	}
	/**
	 * on tag click
	 * @param Event e
	 */
	function onTagClick(e) {
		var $this = $(this);
		var $tag = $(e.target);
		if($this.data('hasLoaded')) {
			$tag.toggleClass('active');
			var params = getTags();
			if($tag.hasClass('active') || params.length > 0 && $.inArray($tag.data('tag'),params) == -1) {
				$.address.parameter('tags', $tag.data('tag'), true);
			} else if(!$tag.hasClass('active')) {
				if(params.length > 0) {
					params.splice($.inArray($tag.data('tag'),params), 1);
					$.address.parameter('tags', params, false);
				}
			}
		}
	}
	function resetTags() {
		$('.tags a').removeClass('active');
	}
	 /*******************************************
	  *	Paging
	  *******************************************/
	 /**
	  * will load more results
	  * @return Boolean
	  */
	 function willLoad() {
	 	var $this = $(this);
	 	var options = $this.data('options');
	 	return (options.total > (options.offset + options.limit));
	 }
	 /**
	  * show more results
	  */
	 function nextPage() {
	 	var $this = $(this);
	 	if($this.data('hasLoaded')) {
	 		var options = $this.data('options');
	 		var results = $this.data('media').slice(options.offset, options.offset + options.limit);
	 		$this.data('options').offset += options.limit;
	 		for(var i = 0; i < results.length; i++) {
				var $a = createItem(results[i], i, this);
	 			$this.data('dirAll').append($a);
	 		}
	 	}
/* 
	 	$(".item img").lazyload({
	 		effect : "fadeIn",
	 		threshold : 200,
	 		event: "scrollstop" 
	 	});
 */
		
	 }
	 /**
	  * on window scroll
	  * @param Event e
	  */
	 function onScroll(e) {
	 	var options = $(this).data('options');
	 	var isBottom = $(window).scrollTop() == ($(document).height() - $(window).height());
	 	var willLoad = true; //(options.total > (options.offset + options.limit));
	 	if(isBottom && willLoad){
	 		$.proxy(nextPage, this)();
	 	}	
	 }
	 /*******************************************
	  *	Containers
	  *******************************************/
	 /**
	  * Toggle loader
	  */
	 function toggleLoader() {
	 	if($('#loader').is(":visible")) {
	 		$('#loader').remove();
	 	} else {
	 		$('#main').append($(this).data('loader'));
	 	}
	 }
	 /**
	  * Show all
	  */
	 function showAll() {
	 	$(this).data('dirAll').show();
	 	$(this).data('dirTag').hide();
	 	$(this).data('dirPreview').hide();
	 };
	 /**
	  * Show tagged
	  */
	 function showTagged() {
	 	$(this).data('dirAll').hide();
	 	$(this).data('dirTag').show();
	 	$(this).data('dirPreview').hide();
	 }
	 /**
	  * Show preview
	  */
	 function showPreview() {
	 	var $this = $(this);
		$('#container').hide();
		$this.data('dirPreview').css('opacity', 0);
		$this.data('dirPreview').fadeTo('fast', 1.0);
	 }
	 /**
	  * Close preview
	  * @param Event e
	  */
	 function onClosePreview(e) {
	 	var $this = $(this);
	 	$this.data('dirPreview').fadeTo('fast', 0, function() {
	 		$(this).hide();
	 		$(this).empty();
	 		$('#container').fadeTo('fast', 1.0);
	 	});
	 	$.address.parameter('entry', null, false);
	 }
	 /**
	  * Next preview
	  * @param Event e
	  */
	 function onNextPreview(e) {
	 	var next = $(this).data('next');
	 	$('.item[data-index="'+next+'"]').trigger('click', this);
	 }
	 /**
	  * Prev preview
	  * @param Event e
	  */
	 function onPrevPreview(e) {
	 	var prev = $(this).data('prev');
	 	$('.item[data-index="'+prev+'"]').trigger('click', this);
	 }
	 /*******************************************
	  *	Thumbnails
	  *******************************************/
	 /**
	  * On item click
	  * @param Event e
	  */
	 function onItemClick(e, c) {
	 	var $this = (c) ? $(c) : $(this);
	 	var $target = $(e.currentTarget);
	 	$this.data('prev', $target.data('index') - 1);
	 	$this.data('next', $target.data('index') + 1);
	 	$.address.parameter('entry', $target.attr('href'), false);
	 	return false;
	 }
	 /**
	  * Create thumbnail
	  * @param Object data
	  * @return Element
	  */
	 function createItem(data,index,context) {
	 	var $a = $('<a>').attr({
	 		'title'				: data.summary,
	 		'href'				: data.urlTitle,
	 		'data-keywords'	: data.keywords.join(','),
	 		'data-index'		: index,
	 		'data-id'			: data.id,
	 		'class'				: 'item'	 	
	 	}).append($('<span>').attr({
	 		'class'				: "item-container"
	 	}).append($('<img/>').attr({
	 		//'data-original'	: data.preview,
	 		'src'					: data.preview
	 	}))).append($('<span>').attr({
	 		"class"				: "title"
	 	}).html(data.title));
	 	$a.click($.proxy(onItemClick, context));
	 	return $a;
	 }
})(jQuery);
