
GAP.Proposal = Class.create({
	sizes: $H({'a': [750,450],
			 'b': [800,510],
			 'c': [900,550],
			 'd': [950,640],
			 'e': [1020,750]
			})
	,
	initialize: function(current,prev,next) {
		this.cur_id = current;
		this.prev_id = prev;
		this.next_id = next;

		this.proposal = $('proposal');
		this.proposal.setStyle({overflow:'hidden'});
		
		this.slides_wrapper = $('proposal_slides');
		this.slides = $$('#proposal_slides .slide');
		this.slides.each(function(slide){slide.setStyle({overflow:'hidden'})});
		this.current_slide = 0;
		
		// resize
		this.size_cat = 'a';
		this.set_window_sizes();
		this.check_resize();
		this.slides_wrapper.setStyle({width: (this.get_width()*this.slides.length + 200) + 'px'});
		this.header = $$('#content h2')[0];
		this.header_top = this.header.cumulativeOffset()[1];
		
		
		// zooming: build a kind of lightbox
		this.zoomed = false;
		this.zoom_div = new Element('div', { 'id': 'zoom_wrapper', 'style': 'display: none;' });
		$('wrapper').insert({before:this.zoom_div});
		
		this.zoom_loading_div = new Element('div', { 'id': 'zoom_loading', 'style': 'display: none;' });
		this.zoom_div.insert(this.zoom_loading_div);
		
		this.zoom_info_div = new Element('div', { 'id': 'zoom_info', 'style': 'display: none;' });
		this.zoom_info_div.insert('<p><strong>ZOOMED.</strong> Click and drag to scroll. Click here to exit, or hit [esc].</p>');
		this.zoom_div.insert(this.zoom_info_div);
		
		this.zoom_img = new Element('img',{'style':'display: none;'});
		this.zoom_tmp_img = new Element('img');
		this.zoom_div.insert(this.zoom_img);		
		this.zoom_load_observer = this.zoom_ready.bindAsEventListener(this);
		this.zoom_exit_observer = this.zoom_exit.bindAsEventListener(this);
		
		this.add_zoom_indicator();
		this.remove_image_clicks();

		// set height based on text height
		if($('text_slide').getHeight() > this.get_height()) {
			var ht = $('text_slide').getHeight() + 25;
			this.slides[0].setStyle({height: ht + 'px'});
			this.slides_wrapper.setStyle({height: ht + 'px'});
		}
		// next/previous links
		this.next_prev = $('next_prev').show();
		$('prev_slide').observe('click',this.go_click.bindAsEventListener(this));
		$('next_slide').observe('click',this.go_click.bindAsEventListener(this));
		
		// navigation 
		
		this.check_help_box();
		
		this.keyobserver = this.proposal_keybind.bindAsEventListener(this);
		this.observe_keys();
		this.window_resize_observer = this.window_resize.bindAsEventListener(this);
		Event.observe(window,'resize',this.window_resize_observer);
		// start at home
		this.go(0);
	},
	add_zoom_indicator: function() {
		$$('.drawing_image').each(function(image_div){
			image_div.observe('click', this.toggle_zoom.bindAsEventListener(this));
		},this);
	},
	observe_keys: function() {
		Event.observe(document,'keydown', this.keyobserver);
	},
	stop_keys: function() {
		Event.stopObserving(document,'keydown', this.keyobserver);
	},
	pause_keys: function() {
		this.stop_keys();
		setTimeout('my_prop.observe_keys()',50);
	},
	get_width: function() {
		return this.sizes.get(this.size_cat)[0];
	},
	get_height: function() {
		return this.sizes.get(this.size_cat)[1];
	},
	check_help_box: function() {
		var nav_help = GAP.readCookie('pc_nav_help');
		if(nav_help != 5) {
			new Effect.BlindDown('navigation_help', { duration: .6});
			
			// watch close event
			this.eventCloseHelp = this.close_help_box.bindAsEventListener(this);
		    Event.observe($('close_navigation_help'),'click', this.eventCloseHelp);
			
			// set the value to zero if it's null
			if(!nav_help) {nav_help == 0;}
			nav_help++;
			GAP.createCookie('pc_nav_help',nav_help,365);
		}
	},
	close_help_box: function(e) {
		new Effect.BlindUp('navigation_help', { duration: .4});
		GAP.createCookie('pc_nav_help',5,365);
		Event.stop(e);
	},
	window_resize: function() {
		// prevent firing the check_resize over and over (IE anyone?). not perfect but passable.
		var old_w = this.vp_width;
		var old_h = this.vp_height;
		
		this.set_window_sizes();
		if(old_w != this.vp_width || old_h != this.vp_height) {
			if(this.check_resize()) {
				this.go_to_current();
			}
		}
		return true;
	},
	set_window_sizes: function() {
		var vp = document.viewport.getDimensions();
		this.vp_height  = vp.height;
		this.vp_width = vp.width;
	},
	check_resize: function() {
		this.set_window_sizes();
		var max_width = this.vp_width - 230;
		var max_height = this.vp_height - this.slides_wrapper.cumulativeOffset()[1];
		var size_keys = this.sizes.keys().sort();
		this.prev_cat = this.size_cat;
		this.size_cat = size_keys[0];
		size_keys.each(function(size_key){
		 	if(max_width >= this.sizes.get(size_key)[0] && 
				max_height >= this.sizes.get(size_key)[1]) {
					this.size_cat = size_key;
				}
		},this);
		if(this.size_cat != this.prev_cat) {
			this.resize_to_category();
			return true;
		}
		else {
			return false;
		}
	},
	resize_to_category: function() {
		var w = this.sizes.get(this.size_cat)[0];
		var h = this.sizes.get(this.size_cat)[1];
		// size wrapper
		$('wrapper').setStyle({width: (w + 230)+'px'});
		// size content
		$('content').setStyle({width: w + 'px'});
		
		// size this.proposal.width
		this.proposal.setStyle({width: w+'px'});
		// size this.slides_wrapper.height
		this.slides_wrapper.setStyle({height: h+'px'});
		// size #proposal .slide width + height
		$$('#proposal .slide').invoke('setStyle',{height: h+'px', width: w+'px'});
		
		// now change src on images
		$$('#proposal .slide img').each(function(el) {
			el.src = el.src.replace('/' + this.prev_cat + '/','/' + this.size_cat + '/');
		},this);
	
	},
	proposal_keybind: function(e) {
		var keycode = e.keyCode;
		var key = String.fromCharCode(keycode).toLowerCase();
		if(keycode == Event.KEY_RIGHT || keycode == 190) {
			this.pause_keys(); // for safari 2.x repeating bug
			this.go(1);
		}
		else if(keycode == Event.KEY_LEFT || keycode == 188) {
			this.pause_keys();  // for safari 2.x repeating bug
			this.go(-1);
		}
		else if(key == 'n' || key == 'p' || key == 'j' || key == 'k') {
			this.go_proposal(key);
		}
		else if(key == 'z') {
			this.toggle_zoom();
		}
		else if(keycode == Event.KEY_ESC) {
			this.zoom_out();
		}
		else if(key == 'u') {
			new Ajax.Request(GAP.urls.thumbs_up + this.cur_id, {asynchronous:true, evalScripts:true});
		}
		else if(key == 'd') {
			new Ajax.Request(GAP.urls.thumbs_down + this.cur_id, {asynchronous:true, evalScripts:true});
		}
		
	},
	toggle_zoom: function() {
		if(!this.slides[this.current_slide].hasClassName('drawing')) {
			return false;
		}
		if(this.zoomed) {
			this.zoom_out();
		}
		else {
			this.zoom_in();
		}
		return true;
	},
	zoom_in: function() {
		this.zoom_tmp_img.src = this.slides[this.current_slide].getElementsByTagName('a')[0].href;
		this.zoom_info_div.hide();
		this.zoom_div.show();
		this.zoom_loading_div.show();
		
		// hide footer (to remove scrollbar)
		$$('body')[0].setStyle({overflow:'hidden'});
		if(Prototype.Browser.IE) {$$('html')[0].setStyle({overflow:'hidden'});} // ie, doesn't break FF/webkit
		
		// new Effect.Appear(this.zoom_div, { duration: .3});
		this.zoom_scroll = new DragScrollable(this.zoom_div);
		if(this.zoom_tmp_img.width) {
			this.zoom_ready();
		}
		else {
			Event.observe(this.zoom_tmp_img,'load', this.zoom_load_observer);
		}
		this.zoomed = true;
	},
	// triggered by zoom_load_observer
	zoom_ready: function() {
		this.zoom_loading_div.hide();
		this.zoom_info_div.show();
		Event.observe(this.zoom_info_div,'click', this.zoom_exit_observer);
		
		this.zoom_img.src = this.zoom_tmp_img.src;
		new Effect.Appear(this.zoom_img, { duration: .5});
		this.zoom_tmp_img.src = '';
		Event.stopObserving(this.zoom_tmp_img,'load', this.zoom_load_observer);
	},
	zoom_out: function() {
		if(!this.zoomed) {return};
		
		this.zoom_scroll.destroy();
		this.zoom_scroll = null;
		this.zoom_div.scrollTo(0,0);
		this.zoom_div.hide();
		this.zoom_img.hide();
		$$('body')[0].setStyle({overflow:'auto'});
		if(Prototype.Browser.IE) {$$('html')[0].setStyle({overflow:'auto'});} // ie, doesn't break FF/webkit
		// scroll to top
		this.zoomed = false;
	},
	// triggered by zoom_exit_observer
	zoom_exit: function() {
		Event.stopObserving(this.zoom_info_div,'click', this.zoom_exit_observer);
		this.zoom_out();
	},
	remove_image_clicks: function() {
		$$('#proposal_slides .drawing a').each(function(el) {
			el.onclick = function(){return false};
		},this);
	},
	go_proposal: function(direction) {
		if(direction == 'n' || direction == 'j') {var dest = this.next_id}
		else {var dest = this.prev_id}
		if(dest) {
			 this.slides[this.current_slide].setOpacity(.5);
			 if(location.href.include('admin')) {location.href = GAP.urls.admin_proposal + dest;}
			 else {location.href = GAP.urls.choice_entry + dest;}
		}
	},
	go_click: function(e) {
		if(Event.element(e).id == 'next_slide') {
			this.go(1);
		}
		else {this.go(-1);}
		Event.stop(e);
	},
	go: function(direction) {
		if(this.zoomed) {this.zoom_out();}
		
		this.current_slide += direction;
		
		// error correction
		if(this.current_slide < 0) this.current_slide = 0;
		else if(this.current_slide == this.slides.length) this.current_slide = this.slides.length - 1;
		
		this.go_to_current();
	},
	go_to_current: function() {
		new Effect.ScrollToInside(this.proposal,this.slides[this.current_slide],
		 						0,{ duration: 0.3, queue: {position:'end', scope: 'proposalscroll', limit:1}  }); //,afterFinish:this.observe_keys()
		// if below level
		var top = document.viewport.getScrollOffsets().top;
		if (top > this.header_top) {
			new Effect.ScrollTo(this.header);
		}
		// next_prev disable
		if(this.current_slide == 0) {
			$('prev_slide').addClassName('disabled');
		}else {
			$('prev_slide').removeClassName('disabled');
		}
		if(this.current_slide == (this.slides.length -1)){
			$('next_slide').addClassName('disabled');
		}else {
			$('next_slide').removeClassName('disabled');
		}
	}
	
});


/* 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.ScrollToInside = Class.create(Effect.Base, {
  initialize: function(wrapper,toElement,offset) {
	this.wrapperElement = $(wrapper);
	if(!this.wrapperElement) 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
	// made wrapper element 'position:relative' and could remove "- this.wrapperElement.offsetLeft" from below 
    var offset_x = this.toElement.offsetLeft - this.wrapperElement.scrollLeft - offset; // change this in your project
	var options = Object.extend({x: offset_x, y: 0}, arguments[3] || { });
    this.start(options);
  },
  setup: function() {
    var scrollOffsets = (this.wrapperElement == window) 
                ? document.viewport.getScrollOffsets() 
                : Element._returnOffset(this.wrapperElement.scrollLeft, this.wrapperElement.scrollTop) ;
    this.originalScrollLeft = scrollOffsets.left;
    this.originalScrollTop  = scrollOffsets.top;
  },
  update: function(pos) {
    this.wrapperElement.scrollTo(Math.round(this.options.x * pos + this.originalScrollLeft), Math.round(this.options.y * pos + this.originalScrollTop));
  }
});

// http://wiki.script.aculo.us/scriptaculous/show/DragScrollable


var DragScrollable = Class.create();
DragScrollable.prototype = {
  initialize: function(element) {
    this.element = $(element);
    this.active = false;
    this.scrolling = false;

    this.element.style.cursor = 'pointer';

    this.eventMouseDown = this.startScroll.bindAsEventListener(this);
    this.eventMouseUp   = this.endScroll.bindAsEventListener(this);
    this.eventMouseMove = this.scroll.bindAsEventListener(this);

    Event.observe(this.element, 'mousedown', this.eventMouseDown);
  },
  destroy: function() {
    Event.stopObserving(this.element, 'mousedown', this.eventMouseDown);
    Event.stopObserving(document, 'mouseup', this.eventMouseUp);
    Event.stopObserving(document, 'mousemove', this.eventMouseMove);
  },
  startScroll: function(event) {
    this.startX = Event.pointerX(event);
    this.startY = Event.pointerY(event);
    if (Event.isLeftClick(event) &&
        (this.startX < this.element.offsetLeft + this.element.clientWidth) &&
        (this.startY < this.element.offsetTop + this.element.clientHeight)) {
      this.element.style.cursor = 'move';
      Event.observe(document, 'mouseup', this.eventMouseUp);
      Event.observe(document, 'mousemove', this.eventMouseMove);
      this.active = true;
      Event.stop(event);
    }
  },
  endScroll: function(event) {
    this.element.style.cursor = 'pointer';
    this.active = false;
    Event.stopObserving(document, 'mouseup', this.eventMouseUp);
    Event.stopObserving(document, 'mousemove', this.eventMouseMove);
    Event.stop(event);
  },
  scroll: function(event) {
    if (this.active) {
      this.element.scrollTop += 1 *(this.startY - Event.pointerY(event));
      this.element.scrollLeft += 1 *(this.startX - Event.pointerX(event));
      this.startX = Event.pointerX(event);
      this.startY = Event.pointerY(event);
    }
    Event.stop(event);
  }
}
