// Workaround for console.log is undefined in IE
if (typeof console == "undefined") { var console = { log: function() {} }; }


function GuiController(template,items) {
	var _me = this;
	
	_me.name = "GuiController";
	_me.eventList = {};
	_me.isVisible = false;
	_me.isEnabled = true;
	_me.isLoading = false;
	_me.isLoaded = false;
	_me.isAttached = false;
	_me.jqObject = $();
	_me.itemsById = {};
	_me.currentItem = undefined;
	_me.template = template;
	_me.items = items;
}


GuiController.prototype.init = function() {
	var _me = this;

	// Disable input
	_me.isEnabled = false;
	
	_me.jqObject = $("#dm_page");

	// Calculate gui dimensions based on browser window size
	_me.calculateGuiDimensions();

	// Initialize items
	if(_me.template.id == 'start' || _me.template.id == 'gallery') {
		
		for(var i in _me.items) {
            if (i == 'indexOf') continue; 
			var item = _me.items[i];
			item.jqRef = $('<div id="scroller_'+item.id+'" class="item inactive"><div class="item-overlay"></div><div class="preview"><img class="image"/></div></div>');
			item.jqRef.find('img').css('opacity','0.5');
			if(item.type) {
				item.jqRef.addClass(item.type);
			}
			$("#scroller").append(item.jqRef);
			_me.itemsById[item.id] = item;
			item.index = Number(i);
			item.prev = items[i-1];
			if(items[i-1]) { items[i-1].next = item; }
			_me.positionItem(item);
			item.jqRef.click(jQuery.proxy(function() {
				if(this == _me.currentItem) {
					_me.dispatchEvent("onClickCurrentItem");
				}
                else{
                    _me.dispatchEvent("onClickOtherItem");
                    _me.gotoItemById(this.id);
                }
			},item));
		}

		// Setup prev and next buttons
		$('#scroller_button_left').click(function() {
			if(_me.isEnabled)
            {
    			_me.dispatchEvent("onClickPrev");
	    		_me.gotoPrevItem();
            }
		});
		$('#scroller_button_right').click(function() {
			_me.dispatchEvent("onClickNext");
			if(_me.isEnabled) 
            {
                _me.gotoNextItem();
            }
		});

	}
	
	// Initialize thumbnails
	if(_me.template.id == 'gallery') {
		_me.thumbs = [];
		_me.thumbCategories = {};
		
		for(var i in _me.items) {
		
            if (i == 'indexOf') continue; 
			_me.thumbs[i] = _me.items[i].thumb;
			
			_me.thumbs[i].visible = true;
			_me.thumbs[i].categories = _me.items[i].categories;

			for(var j in _me.thumbs[i].categories) {

                if (j == 'indexOf') continue; 
				_me.thumbCategories[_me.thumbs[i].categories[j]] = "visible";
			}
			
			_me.thumbs[i].jqRef = $('<div id="thumb_'+item.id+'" class="thumb"><img class="image"><p>' + i + " " + _me.thumbs[i].caption + '</p></div>');
			_me.thumbs[i].jqRef.css('width',_me.template.thumb.width).css('height',_me.template.thumb.height).css('margin-left',_me.template.thumb.spacing/2).css('margin-right',_me.template.thumb.spacing/2);
			
			_me.thumbs[i].jqRef.click(jQuery.proxy(function() {
				_me.gotoItem(this,true);
			},_me.items[i]));
			
			$("#thumbs").append(_me.thumbs[i].jqRef);
		}

		_me.visibleThumbs = _me.thumbs;

		$("#button_thumb_prev").click(function() {
			_me.thumbGotoPrevPage();
		});

		$("#button_thumb_next").click(function() {
			_me.thumbGotoNextPage();
		});

		_me.addEventListener("onFilterThumbs",function(_me) {
			_me.positionThumbs();
		});
		_me.addEventListener("onResize",function(_me) {
			_me.positionThumbs();
		});
	}
	
	// Position the GUI
	_me.positionGui();
	_me.dispatchEvent("onResize");
	
	// Check for hash tag, goto the correct item if it exists
	if(_me.itemsById[window.location.hash.substr(1)]) {
		_me.gotoItem(_me.itemsById[window.location.hash.substr(1)],false);
	}
	else {
		_me.gotoItem((_me.items.length > 1 ? _me.items[1] : _me.items[0]),false);
	}
	
	$(window).resize(function() {
		_me.calculateGuiDimensions();
		_me.positionGui();
		if(_me.template.id != 'content') {
			for(var i=0;i<_me.items.length;i++) {
                if (i == 'indexOf') continue; 
				_me.positionItem(items[i]);
			}
            _me.respaceItems(0,_me.currentItem.index);
			_me.centerItem(_me.currentItem,false);
			_me.dispatchEvent("onResize");
		}
	});
	
	// Enable input
	_me.isEnabled = true;
};


GuiController.prototype.positionItem = function(item) {
	var _me = this;
    if (item.index == 0){
	    item.jqRef.css('left',0);
    } else {
        item.jqRef.css('left',(_me.template.body.inactive.itemWidth * (item.index - 1)) + (_me.template.margin.horizontal * item.index) + _me.template.body.active.width);
    }
	item.jqRef.css('top',((_me.template.body.height - _me.template.body.inactive.itemHeight)/2));
	item.jqRef.css('width',_me.template.body.inactive.itemWidth);
	item.jqRef.css('height',_me.template.body.inactive.itemHeight);
};


GuiController.prototype.showButtons = function() {
	var _me = this;
	
	if(_me.currentItem.prev) { $('#scroller_button_left').show(); }
	if(_me.items.length > 1) { $('#scroller_button_right').show(); }
};


GuiController.prototype.hideButtons = function() {
	$('#scroller_button_left').hide();
	$('#scroller_button_right').hide();
};


GuiController.prototype.gotoPrevItem = function() {
	var _me = this;
	
	if(_me.currentItem.prev){
		_me.gotoItem(_me.currentItem.prev,true);
    }
};


GuiController.prototype.gotoNextItem = function() {
	var _me = this;
	
	if(_me.currentItem.next) {
		_me.gotoItem(_me.currentItem.next,true);
	}
	else {
		_me.gotoItem(_me.items[0],true);
	}
};


GuiController.prototype.gotoItemById = function(id) {
	var _me = this;
	
	_me.gotoItem(_me.itemsById[id],true);
};


GuiController.prototype.gotoItem = function(item,animate) {
	var _me = this;

	if(item == _me.currentItem) {
		return;
	}

	// Disable Input
	_me.isEnabled = false;

	_me.hideButtons();

	// Preload Queue
	var itemsToLoad = [];
    var extraItemsToLoad = [];
	
	// Add the item we're going to
	if(!item.loaded) {
		itemsToLoad.push(item);
	}
	
	// Add the items before and after the one we're going to (if they exist and aren't loaded)
	if(item.prev && !item.prev.loaded) {
		extraItemsToLoad.push(item.prev);
	}
	if(item.prev && item.prev.prev && !item.prev.loaded) {
		extraItemsToLoad.push(item.prev.prev);
	}
	if(item.next && !item.next.loaded) {
		extraItemsToLoad.push(item.next);
	}
    if (item.next && item.next.next && !item.next.next.loaded) {
        extraItemsToLoad.push(item.next.next);
    }
	if(itemsToLoad.length > 0) {
		// Show loader
		_me.showLoader();
		_me.preload(itemsToLoad,function(){
			_me.hideLoader();
            _me.preload(extraItemsToLoad,function(){});
            }
		);
	} else if (extraItemsToLoad.length > 0)
    {
        _me.preload(extraItemsToLoad, function(){});
    }
	_me.dispatchEvent("beforeGotoItem");

	// Set hash tag
	window.location.hash = item.id;
	
	if(_me.currentItem) {
		// Process old currentItem
		_me.dispatchEvent("onItemDeactivated");
		_me.currentItem.jqRef.removeClass('active');
		if (animate) {
			_me.currentItem.jqRef.find('.image').animate({opacity:0.5},{duration:200});
        }
        _me.currentItem.jqRef.css('width',_me.template.body.inactive.itemWidth);
        _me.currentItem.jqRef.css('height',_me.template.body.inactive.itemHeight);
    	_me.currentItem.jqRef.css('top',((_me.template.body.height - _me.template.body.inactive.itemHeight)/2));
        _me.currentItem.jqRef.addClass('inactive');
	}

    //adjust positioning of intermediary items
    oldindex = (_me.currentItem ? _me.currentItem.index : 0);
    _me.respaceItems(oldindex,item.index);
	
	// Set currentItem
	_me.currentItem = item;
	
	// Apply class
	_me.currentItem.jqRef.removeClass('inactive');
	item.jqRef.addClass('active');
	
	var onComplete = function() {
		_me.showButtons();
		_me.isEnabled = true;
		_me.dispatchEvent("onItemActivated");
	};

	_me.centerItem(item,animate,onComplete);
};

GuiController.prototype.respaceItems = function(oldindex,newindex){
    var _me = this;

    deviat = _me.template.body.active.width - _me.template.body.inactive.itemWidth;
    if (oldindex < newindex) { //advancing
        for (i = oldindex + 1; i <= newindex; i++){
            _me.items[i].jqRef.css('left', (_me.items[i].jqRef.position().left - deviat));
        }
    } else if (oldindex > newindex){ //rewinding
        for (i = oldindex; i > newindex; i--){
            _me.items[i].jqRef.css('left', _me.items[i].jqRef.position().left + deviat);
        }
    }
};

GuiController.prototype.centerItem = function(item,animate,onComplete) {
	var _me = this;
	
	// Calculate the body X position
	var itemPos = item.jqRef.position().left;
	var bodyPos = _me.template.body.inactive.width + _me.template.margin.horizontal - itemPos;
	onComplete = onComplete || new Function();

	// Set position
	if(animate) {
        item.jqRef.css("left", itemPos + Math.round((_me.template.body.active.width - _me.template.body.inactive.itemWidth)/2));
		$('#scroller').animate({
			left: bodyPos
		},
		{
			duration: 200,
            complete: function(){
		        item.jqRef.find('.image').animate({opacity:1},{duration:500});
                item.jqRef.animate({
                    top: 0,
                    height: _me.template.body.height,
                    width: _me.template.body.active.width,
                    left: itemPos
                },
                {
                    duration: 400,
                    complete: onComplete,
			        easing: "easeOutExpo"
                });
            }
		});
	}
	else {
		$('#scroller').css('left',bodyPos);
        item.jqRef.css('top', 0);
        item.jqRef.css('height', _me.template.body.height);
        item.jqRef.css('width', _me.template.body.active.width);
        item.jqRef.find('.image').css('opacity', 1);
		onComplete();
	}
};


GuiController.prototype.filterThumbs = function(category) {
	var _me = this;
	var action;
	
	if(_me.thumbCategories[category] == "visible") {
		// Hide
		_me.thumbCategories[category] = "hidden";
		$("#filter_" + category).addClass("hidden");
		
	}
	else {
		// Show
		_me.thumbCategories[category] = "visible";
		$("#filter_" + category).removeClass("hidden");
	}
	
	_me.visibleThumbs = [];
	
	for(i in _me.thumbs) {
		_me.thumbs[i].jqRef.hide();
		for(j in _me.thumbs[i].categories) {
			// check if that category is visible
			if(_me.thumbCategories[_me.thumbs[i].categories[j]] == "visible") {
				_me.visibleThumbs.push(_me.thumbs[i]);
				_me.thumbs[i].jqRef.show();
				break;
			}
		}
	}

	_me.dispatchEvent("onFilterThumbs");
};


GuiController.prototype.positionThumbs = function() {
	var _me = this;
	
	// Determine how many thumbs fit on the page
	var thumbWidth = _me.template.thumb.width + _me.template.thumb.spacing;
	_me.thumbsPerPage = Math.floor(_me.template.thumb.containerWidth/thumbWidth);

	_me.totalThumbPages = Math.ceil(_me.visibleThumbs.length/_me.thumbsPerPage);

	// Find the position of the active thumb, if visible
	_me.currentThumbIndex = -1;
	for(i in _me.visibleThumbs) {
		if(_me.visibleThumbs[i] == _me.currentThumb) {
			_me.currentThumbIndex = i;
		}
	}
	
	// Find startIndex
	var pageToShow = 0;
	if(_me.currentThumbIndex > 0) {
		pageToShow = Math.floor(_me.currentThumbIndex/_me.thumbsPerPage);
	}
	var startIndex = pageToShow * _me.thumbsPerPage;
	
	_me.currentThumbPage = pageToShow;

	_me.thumbGotoPage(pageToShow,false);
};


GuiController.prototype.thumbGotoPrevPage = function() {
	var _me = this;
	if(_me.currentThumbPage > 0) {
		_me.thumbGotoPage(_me.currentThumbPage-1,true);
    }
};
GuiController.prototype.thumbGotoNextPage = function() {
	var _me = this;
	if(_me.currentThumbPage < _me.totalThumbPages-1) {
		_me.thumbGotoPage(_me.currentThumbPage+1,true);
    }
};

GuiController.prototype.thumbGotoPage = function(page,animate) {
	var _me = this;
	
	_me.currentThumbPage = page;
	
	var thumbsLoaded = function() {

		var onComplete = function() {
		};

		if(animate) {
			$('#thumbs').animate({
				left: -(_me.template.thumb.width + _me.template.thumb.spacing) * _me.thumbsPerPage * page
			},
			{
				duration: 500,
				queue:false,
				easing: "easeOutExpo",
				complete: onComplete
			});
		}
		else {
			$('#thumbs').css('left', -_me.template.thumb.containerWidth * page);
			onComplete();
		}

	};
	
	// Preload thumbs
	var thumbsToLoad = [];
	for(i=page*_me.thumbsPerPage;i<(page+1)*_me.thumbsPerPage+1;i++) {
		if(i == _me.visibleThumbs.length) { break; }
		thumbsToLoad.push(_me.visibleThumbs[i]);
	}
	_me.preload(thumbsToLoad,thumbsLoaded);	
};


GuiController.prototype.preload = function(items,callback) {
	var itemsToLoad = items.length;
	for(var i in items) {
        if (i == 'indexOf') continue; 
		var item = items[i];
		if(!item.loaded) {
			
			onLoadItem = jQuery.proxy(function() {
				this.jqRef.find('img').unbind();
				this.loaded = true;
				itemsToLoad--;
				if(itemsToLoad==0) {
					callback();
				}
			},item);
			item.jqRef.find('img').load(onLoadItem);
			item.jqRef.find('img').attr('src', item.image_url);
		}
		else {
			itemsToLoad--;
			if(itemsToLoad==0) {
				callback();
			}
		}
	}
};

GuiController.prototype.showCaption = function(item) {
	var _me = this;
	if(!item.captionVisible) {
		item.captionVisible = true;
		$("#caption .content").append(item.caption);
	}
};

GuiController.prototype.hideCaption = function(item) {
	var _me = this;
	if(item && item.captionVisible) {
		$("#caption .content").empty();
		item.captionVisible = false;
	}
};

GuiController.prototype.hideAllCaptions = function() {
	var _me = this;

	$("#scroller .caption").remove();
};

GuiController.prototype.calculateGuiDimensions = function() {
	var _me = this;

	// Browser width and height
	_me.template.total.height = $(window).height();
	_me.template.total.width = Math.max($(window).width(), 720);
	
	// Calculate header height based on defaultHeight (%) and minHeight (pixels)
    if( _me.template.header.height){
        //keep it as is
        _me.template.header.height = _me.template.header.height;
    }
    else if( _me.template.total.height * _me.template.header.defaultHeight < _me.template.header.minHeight ) {
		_me.template.header.height = _me.template.header.minHeight;
	}
	else {
		_me.template.header.height = Math.round(_me.template.total.height * _me.template.header.defaultHeight);
	}
	
	// Calculate footer height based on defaultHeight (%) and minHeight (pixels)
    if( _me.template.footer.height ) {
        //keep it as is
        _me.template.footer.height = _me.template.footer.height;
    }
    else if( _me.template.total.height * _me.template.footer.defaultHeight < _me.template.footer.minHeight ) {
		_me.template.footer.height = _me.template.footer.minHeight;
	}
	else {
		_me.template.footer.height = Math.round(_me.template.total.height * _me.template.footer.defaultHeight);
	}

	if(_me.template.id == 'content') {
        if (_me.template.body.border ) {
            //keep it as it is
            _me.template.body.border = _me.template.body.border;
        } else {
            _me.template.body.border = 0;
        }

		// Calculate the body height
		_me.template.body.height = _me.template.total.height - _me.template.header.height - _me.template.footer.height - _me.template.margin.vertical*2 - _me.template.body.border;
	}
	else {
		// Calculate the body height
		_me.template.body.height = Math.max(200, (_me.template.total.height - _me.template.header.height - _me.template.footer.height - _me.template.margin.vertical*3 - _me.template.lower.height));


		// Calculate size for body items based on aspect ratio
		_me.template.body.inactive.width = Math.round((_me.template.total.width - _me.template.body.height / _me.template.body.aspect - _me.template.margin.horizontal*2)/2);
		if(_me.template.body.inactive.width < _me.template.body.inactive.minWidth) {
			_me.template.body.inactive.width = _me.template.body.inactive.minWidth;
		}
		_me.template.body.active.width = _me.template.total.width - _me.template.body.inactive.width * 2-_me.template.margin.horizontal*2;
        _me.template.body.inactive.itemWidth = Math.round(2/3 * _me.template.body.active.width);
        _me.template.body.inactive.itemHeight = Math.round(2/3 * _me.template.body.height);
	}


	// Check which style size to apply based on total height
	if(_me.template.total.height > 900) {
		_me.template.vsize = 3;
	}
	else if(_me.template.total.height > 570) {
		_me.template.vsize = 2;
	}
	else {
		_me.template.vsize = 1;
	}
	if(_me.template.total.width > 1260) {
		_me.template.hsize = 4;
	}
	else if(_me.template.total.width > 1092) {
		_me.template.hsize = 3;
	}
    else if (_me.template.total.width > 950) {
        _me.template.hsize = 2;
    }
	else if (_me.template.total.width > 720) {
		_me.template.hsize = 1;
	}
    else {
        _me.template.hsize = 0;
    }

};


GuiController.prototype.positionGui = function() {
	var _me = this;

	$('#dm_page').removeClass('vsize0 vsize1 vsize2 vsize3 hsize0 hsize1 hsize2 hsize3 hsize4');
	$('#dm_page').addClass('vsize' + _me.template.vsize + ' hsize' + _me.template.hsize);

	$('#header').css('height',_me.template.header.height);
	$('#header').css('margin-bottom',_me.template.margin.vertical);

	$('footer').css('margin-top',_me.template.margin.vertical);
	$('footer').css('height',_me.template.footer.height);
	$('footer').css('top',_me.template.margin.vertical);

	$('#scroller .caption').css('top',_me.template.body.height);

    if (_me.template.id == 'content') {
        $('#scroller').css('min-height',_me.template.body.height);
    } else {
	    $('#scroller').css('height',_me.template.body.height);
    }

	if(_me.template.id == "start") {
		$('#scroller_button_left').css('left',_me.template.body.inactive.width).css('top',_me.template.header.height + _me.template.body.height/2 - 26);
		$('#scroller_button_right').css('left',_me.template.body.inactive.width+_me.template.body.active.width+_me.template.margin.horizontal).css('top',_me.template.header.height+_me.template.body.height/2 - 26);
		$('#lower').css('height',_me.template.lower.height);
		$('#lower').css('top',_me.template.margin.vertical);

		//$('#caption .content').css('width',_me.template.body.active.width);
		$('#callouts .content').css('width',_me.template.body.active.width);
	}

	if(_me.template.id == "gallery") {
		$('#scroller_button_left').css('left',_me.template.body.inactive.width).css('top',_me.template.header.height + _me.template.body.height/2 - 26);
		$('#scroller_button_right').css('left',_me.template.body.inactive.width+_me.template.body.active.width+_me.template.margin.horizontal).css('top',_me.template.header.height+_me.template.body.height/2 - 26);
		$('#lower').css('height',_me.template.lower.height);
		$('#lower').css('top',_me.template.margin.vertical);

		$("#thumb_filters").css('width',_me.template.thumb.filterWidth);
		$("#button_thumb_prev").css('left',_me.template.thumb.filterWidth);
		$("#button_thumb_prev").css('width',_me.template.thumb.buttonWidth);
		$("#button_thumb_next").css('left',_me.template.total.width-_me.template.thumb.buttonWidth);
		$("#button_thumb_next").css('width',_me.template.thumb.buttonWidth);
		_me.template.thumb.containerWidth = _me.template.total.width - _me.template.thumb.buttonWidth*2 - _me.template.thumb.filterWidth;
		$("#thumb_container").css('width',_me.template.thumb.containerWidth);
		$("#thumb_container").css('left',_me.template.thumb.buttonWidth+_me.template.thumb.filterWidth);
		$("#thumbs").css('width',20000);
	}

};


GuiController.prototype.showLoader = function() {
	var _me = this;
	console.log("SHOW LOADER");
};

GuiController.prototype.hideLoader = function() {
	var _me = this;
	console.log("HIDE LOADER");
};


GuiController.prototype.show = function() {
	var _me = this;

	// Show the object
	_me.isVisible = true;
	_me.jqObj.show();
	_me.dispatchEvent("onShow");
};


GuiController.prototype.hide = function() {
	var _me = this;

	// Hide the object
	_me.isVisible = false;
	_me.jqObj.hide();
	_me.dispatchEvent("onHide");
};


GuiController.prototype.addEventListener = function(eventId,functionToCall) {
	var _me = this;
	console.log(_me.name + ".addEventListener: " + eventId);
	if(!_me.eventList[eventId]) {
		_me.eventList[eventId] = new Array();
	}
	_me.eventList[eventId].push(functionToCall);
};


GuiController.prototype.dispatchEvent = function(eventId) {
	var _me = this;
	
	console.log(_me.name + ".dispatchEvent: " + eventId + (_me.eventList[eventId]?" (" + _me.eventList[eventId].length + " listeners)":" (no listeners)"));
	for(var functionToCall in _me.eventList[eventId]) {
		//console.log(_me.name + ".dispatchEvent: " + eventId + ": " + functionToCall);
		_me.eventList[eventId][functionToCall](this);
	}
};

