/*
Reinventing GAP project site panoramas
david reese / Whatcould.com
*/

var WC = function() {
	return {
		// straight from lightbox
		// pause(numberMillis)
		// Pauses code execution for specified time. Uses busy code, not good.
		// Help from Ran Bar-On [ran2103@gmail.com]
		//
		pause: function(ms){
			var date = new Date();
			var curDate = null;
			do{var curDate = new Date();}
			while( curDate - date < ms);
		}
	};
}();


WC.Panoramas = Class.create({
	initialize: function() {
		this.current_panorama = 0;
		this.current_map_button = 0;
		this.panorama_div = $('panoramas');

		var panorama_items = $$('#panoramas div');
		this.setup_lightbox();
		panorama_items.each(function(item) {
			Event.observe(item, 'click', this.panorama_click.bindAsEventListener(this));
			Event.observe(item, 'mouseover',this.panorama_over.bindAsEventListener(this));
			Event.observe(item, 'mouseout',this.panorama_out.bindAsEventListener(this));
		},this);
		var map_links = $$('#map a');
		map_links.each(function(item) {
			Event.observe(item, 'click', this.map_click.bindAsEventListener(this));
		},this);
	},
	map_click: function(e) {
		var index = e.element().id.substr(7);
		if(this.current_index == index) { //jump directly on second hit, accessibility
			this.panorama_jump(index);
		}
		else {
			this.remove_current();
			this.set_current(index);
			new Effect.ScrollTo(this.panorama_div,this.current_panorama, 10,{ duration: 0.2,highlight: false}); 
		}
		e.stop();
	},
	panorama_over: function(e) {
		var el = e.findElement('div');
		var index = el.id.substr(9);
		$('marker_'+index).addClassName('highlight');
		el.addClassName('highlight');
	},
	panorama_out: function(e) {
		var el = e.findElement('div');
		var index = el.id.substr(9);
		$('marker_'+index).removeClassName('highlight');
		el.removeClassName('highlight');
	},
	panorama_click: function(e) {
		var el = e.findElement('div');
		var index = el.id.substr(9);
		this.panorama_jump(index);
		e.stop();
	},
	panorama_jump: function(index) {
		this.remove_current();
		this.set_current(index);
		this.lightbox_prepare();
	},
	remove_current: function() {
		if(this.current_panorama) {
			this.current_panorama.removeClassName('current');
			this.current_map_button.removeClassName('current');
		}
	},
	set_current: function(index) {
		this.current_index = index;
		this.current_panorama =$('panorama_'+index);
		this.current_map_button = $('marker_'+index);
		this.current_panorama.addClassName('current');
		this.current_map_button.addClassName('current');
	},
	/* =========================== */
	
	setup_lightbox: function() {
		this.lightbox = {
			border_size: 10,
			resize_duration: .2,
			scrolltime: 5,
			large_image_path: '/projects/gap/resources/panoramas/images/large/gap_panorama_',
			original_image_path: '/projects/gap/resources/panoramas/images/originals/gap_panorama_',
			overlay: $('overlay'),
			main: $('lightbox'),
			container: $('outerImageContainer'),
			image: $('lightboxImage'),
			prev_link: $('prevLink'),
			next_link: $('nextLink'),
			hover_nav: $('hoverNav'),
			image_download: $('imageDownload'),
			download_size: $('downloadSize'),
			loading: $('loading'),
			caption: $('caption'),
			download_size: $('downloadSize'),
			close_link: $('bottomNavClose'),
			image_caption_container: $('imageDataContainer'),
			preloader: new Image()
		}
		Event.observe(this.lightbox.close_link,'click',this.lightbox_close.bindAsEventListener(this));
	},
	lightbox_prepare: function() {
		// fix for firefox bug (gasp!)... fixed in 3.0
		$('panoramas').setStyle({overflow:'hidden'});
		$('footer').hide();
		
		document.observe("mouse:wheel", this.lightbox_scroll);

		// enable keyboard
		Event.observe(document,'keydown', this.lightbox_keyboard.bindAsEventListener(this));
		
		this.lightbox_size_to_window();
		new Effect.Appear(this.lightbox.overlay, { duration: 0.2, from: 0.0, to: .8 });
		
		this.lightbox.main.show();
		this.lightbox_show();
	},
	lightbox_size_to_window: function() {
		var image_width = this.image_data[this.current_index][0];
		var image_height = this.image_data[this.current_index][1];
		
		// set the overlay size
		var viewport_width = document.viewport.getWidth();
		var viewport_height = document.viewport.getHeight();
		var frame_width = image_width+(this.lightbox.border_size*2);
		var overlay_width = frame_width < viewport_width ? viewport_width : frame_width;

		this.lightbox.overlay.setDimensions({width: overlay_width, height: (viewport_height - 20)});
		
		this.lightbox.loading.style.width = viewport_width + 'px';

		// calculate top and left offset for the lightbox	
		var scroll_offset = document.viewport.getScrollOffsets();
		var lightboxTop = scroll_offset.top + (viewport_height / 10);
		var lightboxLeft = scroll_offset.left;
		this.lightbox.main.setPosition({top: lightboxTop, left: lightboxLeft});
		
		// set the caption container top: this to fix safari 3 issue in positioning
		this.lightbox.image_caption_container.setPosition({left:0,top:(lightboxTop + image_height)});

		this.lightbox.hover_nav.setDimensions({height:image_height, width: viewport_width});

		this.lightbox.hover_nav.style.top = (lightboxTop + this.lightbox.border_size) + 'px';
	},
	lightbox_show: function() {
		// start by hiding
		this.lightbox.image.hide();
		this.lightbox.hover_nav.hide();
		this.lightbox.prev_link.hide();
		this.lightbox.next_link.hide();
		this.lightbox.image_caption_container.hide();
		this.lightbox.image_download.hide();
		
		// set dimensions
		var width = this.image_data[this.current_index][0];
		var height = this.image_data[this.current_index][1];
		this.lightbox.image.setDimensions({'width': width, 'height': height});
		
		this.lightbox.loading.show();

		// set onload listener
		// Event.observe(this.lightbox.preloader, 'load', this.lightbox_loaded.bindAsEventListener(this));
		
		this.lightbox.preloader.onload = this.lightbox_loaded.bindAsEventListener(this);
		
		// and go
		this.lightbox.preloader.src = this.lightbox.large_image_path + this.current_index + '.jpg';
	},
	lightbox_loaded: function() {
		this.lightbox_resize();
		this.lightbox.image.src = this.lightbox.large_image_path + this.current_index + '.jpg';
		this.lightbox.loading.hide();
		// show all that stuff
		// this.lightbox.hover_nav.show();
		// this.lightbox.prev_link.show();
		// this.lightbox.next_link.show();
		new Effect.Appear(this.lightbox.image, { duration: this.lightbox.resize_duration, queue: 'end', afterFinish: this.lightbox_info.bind(this)});
	
		this.lightbox.preloader.onload = function(){};
		// Event.stopObserving(this.lightbox.preloader, 'load', this.lightbox_loaded.bindAsEventListener(this));
	},
	lightbox_resize: function() {
		// copying all this ugly code from the lightbox
		
		// get current width and height
		var dimensions = this.lightbox.container.getDimensions();
		var cur_width = dimensions.width;
		var cur_height = dimensions.height;

		// get new width and height
		var new_width = (this.image_data[this.current_index][0]  + (this.lightbox.border_size * 2));
		var new_height = (this.image_data[this.current_index][1]  + (this.lightbox.border_size * 2));

		// scalars based on change from old to new
		var xScale = ( new_width / cur_width) * 100;
		var yScale = ( new_height / cur_height) * 100;

		// calculate size difference between new and old image, and resize if necessary
		var wDiff = cur_width - new_width;
		var hDiff = cur_height - new_height;

		if(!( hDiff == 0)){ new Effect.Scale(this.lightbox.container, yScale, {scaleX: false, duration: this.lightbox.resize_duration, queue: 'front'}); }
		if(!( wDiff == 0)){ new Effect.Scale(this.lightbox.container, xScale, {scaleY: false, delay: this.lightbox.resize_duration, duration: this.lightbox.resize_duration}); }

		// if new and old image are same size and no scaling transition is necessary, 
		// do a quick pause to prevent image flicker.
		if((hDiff == 0) && (wDiff == 0)){
			if (navigator.appVersion.indexOf("MSIE")!=-1){ WC.pause(250); } else { WC.pause(100);} 
		}
		this.lightbox.hover_nav.style.height = this.image_data[this.current_index][1] + 'px';
	},

	// show the caption and let keyboard listen to events
	lightbox_info: function() {
		// caption
		var caption = $$('#panorama_' + this.current_index + ' p')[0].innerHTML;
		this.lightbox.caption.innerHTML = caption;
		
		// set size
		// some of these parameters we get before, but here we are getting them again. we already showed the picture...
		
		var viewport_width = document.viewport.getWidth();
		var viewport_height = document.viewport.getHeight();
		var frame_width = this.image_data[this.current_index][0]+(this.lightbox.border_size*2);
		
		if(frame_width < viewport_width) {
			this.lightbox.image_caption_container.style.width = frame_width + 'px';
			this.lightbox.image_caption_container.style.left = this.lightbox.container.positionedOffset().left + 'px';
		}
		else {
			this.lightbox.image_caption_container.style.width = (viewport_width) + 'px';
		}
		
		// download link
		this.lightbox.image_download.href = this.lightbox.original_image_path + this.current_index + '.jpg';
		this.lightbox.download_size.innerHTML = '('+this.image_data[this.current_index][2] + ')';
		this.lightbox.image_download.show();
		this.lightbox.image_caption_container.show();
		

		// this.lightbox_scroll_enable();
	},
	lightbox_close: function(e) {
		e.stop();
		this.lightbox.main.hide();
		
		$('panoramas').setStyle({overflow:'auto'});
		$('footer').show();
		new Effect.Fade(this.lightbox.overlay, { duration: 0.2, from: 0.8, to: .0 });
		// stop observing events
		Event.stopObserving(document,"mouse:wheel", this.lightbox_scroll);
		Event.stopObserving(document,'keydown', this.lightbox_keyboard.bindAsEventListener(this));
		
		// this.lightbox.hover_nav.hide();
		// this.lightbox.prev_link.hide();
		// this.lightbox.next_link.hide();
		// this.lightbox.image_caption_container.hide();
		// this.lightbox.image_download.hide();
	},
	lightbox_keyboard: function(e) {
		var keycode = e.keyCode;
		var key = String.fromCharCode(keycode).toLowerCase();
		if(key == 'c' || keycode == Event.KEY_ESC) {
			this.lightbox_close(e);
		}
	},
	lightbox_scroll: function(e) {
		var offset = document.viewport.getScrollOffsets();
		var left = offset.left - 150*e.memo.delta;
		if(left < 0) {left = 0;}
		// todo: fix possible issue if you go off the left or right side?
		scrollTo(left,offset.top);
		e.stop();
	},
	lightbox_scroll_enable: function() {
		Event.observe(this.lightbox.prev_link,'mouseover',this.lightbox_start_scroll_back.bindAsEventListener(this));
		Event.observe(this.lightbox.prev_link,'mouseout',this.lightbox_stop_scroll_back.bindAsEventListener(this));
	},
	lightbox_start_scroll_back: function() {
		this.scroll_direction = 'back';
		this.scroll_timeout = window.setTimeout(this.lightbox_scroll_back.bindAsEventListener(this),this.lightbox.scrolltime);
	},
	lightbox_stop_scroll_back: function() {
		this.scroll_direction = 'stop';
	},
	lightbox_scroll_back: function() {
		var offset = document.viewport.getScrollOffsets();
		var left = offset.left - 8;
		if(left < 0) {left = 0;}
		scrollTo(left,offset.top);
		if(left != 0 && this.scroll_direction != 'stop') {window.setTimeout(this.lightbox_scroll_back.bindAsEventListener(this),this.lightbox.scrolltime);}
	},
	image_data: {
		'1': [7239,450,'2.1 MB'],
		'2': [8652,450,'1.8 MB'],
		'3': [5792,450,'2.1 MB'],
		'4': [8429,450,'1.5 MB'],
		'5': [6445,450,'2.1 MB'],
		'6': [6879,450,'1.2 MB'],
		'7': [7440,450,'1.9 MB'],
		'8': [2217,450,'559.2 KB'],
		'9': [8473,450,'1.6 MB'],
		'10': [7776,450,'3 MB'],
		'11': [4410,450,'671.4 KB'],
		'12': [6675,450,'1.1 MB'],
		'13': [1020,450,'195.3 KB'],
		'14': [4240,450,'563.9 KB'],
		'15': [2210,450,'406.5 KB'],
		'16': [5766,450,'2.1 MB'],
		'17': [2301,450,'715.7 KB'],
		'18': [2069,447,'388 KB'],
		'19': [2644,450,'375.7 KB'],
		'20': [5714,450,'2.5 MB'],
		'21': [5233,450,'2.7 MB'],
		'22': [3876,450,'2.6 MB'],
		'23': [4607,450,'2.6 MB'],
		'24': [2103,450,'1.4 MB'],
		'25': [2057,450,'2.6 MB']
	}
});


Element.addMethods({
	setDimensions: function(element,dimensions) {
	   	element = $(element);
		element.style.width = dimensions.width + 'px';
		element.style.height = dimensions.height + 'px';
	},
	setPosition: function(element,coordinates) {
	   	element = $(element);
		element.style.top = coordinates.top + 'px';
		element.style.left = coordinates.left + 'px';
	}
});

(function() {
  function wheel(event) {
    var realDelta;

    // normalize the delta
    if (event.wheelDelta) // IE & Opera
      realDelta = event.wheelDelta / 120;
    else if (event.detail) // W3C
      realDelta = -event.detail / 3;

    if (!realDelta) return;
    
    var customEvent = event.element().fire("mouse:wheel", {
     delta: realDelta }); 
    if (customEvent.stopped) event.stop();
  }

 document.observe("mousewheel",     wheel);
 document.observe("DOMMouseScroll", wheel);
})();

/* Thanks to gary haran for this scrolling code! Saved me some thinkin'.
http://www.garyharan.com/index.php/2007/11/26/how-to-unobtrusively-scroll-a-div-with-prototype-scriptaculous/
*/

Element.addMethods({
  scrollTo: function(element, left, top){
    var element = $(element);
    if (arguments.length == 1){
      var pos = element.cumulativeOffset();
      window.scrollTo(pos[0], pos[1]);
    } else {
      element.scrollLeft = left;
      element.scrollTop  = top;
    }
    return element;
  }
});

Effect.ScrollTo = Class.create();
Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
  initialize: function(element,toElement,offset) {
    this.element = $(element);
    if(!this.element) throw(Effect._elementDoesNotExistError);
	this.toElement = $(toElement)
	if(!this.toElement) throw(Effect._elementDoesNotExistError);
	
    var offset_y = this.toElement.offsetTop - this.element.scrollTop - this.element.offsetTop - offset; // change this in your project
	var options = Object.extend({x: 0, y: offset_y}, arguments[1] || { });
    this.start(options);
  },
  setup: function() {
    var scrollOffsets = (this.element == window) 
                ? document.viewport.getScrollOffsets() 
                : Element._returnOffset(this.element.scrollLeft, this.element.scrollTop) ;
    this.originalScrollLeft = scrollOffsets.left;
    this.originalScrollTop  = scrollOffsets.top;
  },
  update: function(pos) {
    this.element.scrollTo(Math.round(this.options.x * pos + this.originalScrollLeft), Math.round(this.options.y * pos + this.originalScrollTop));
  },
finish: function() {
	// if(this.options.highlight) {
	// 	new Effect.Highlight(this.toElement,{duration:2});
	// }
  }
});

