// all coal 2009 js

// Douglas Crockford's prototypal inheritance
// http://javascript.crockford.com/prototypal.html
if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
};
shortcase = function(s) {
  s = s.toLowerCase();
  s = s.gsub(/[^a-z0-9]/, '_');
  s = s.gsub(/__*/,'_');
  s = s.gsub(/_$/,'');
  s = s.gsub(/^_/,'');
  return s;
};

// COOKIE JAR
/**
 * Javascript code to store data as JSON strings in cookies. 
 * It uses prototype.js 1.5.1 (http://www.prototypejs.org)
 * 
 * Author : Lalit Patel
 * Website: http://www.lalit.org/lab/jsoncookies
 * License: Apache Software License 2
 *          http://www.apache.org/licenses/LICENSE-2.0
 * Version: 0.5
 * Updated: Jan 26, 2009 
 * 
 * Chnage Log:
 *   v 0.5
 *   -  Changed License from CC to Apache 2
 *   v 0.4
 *   -  Removed a extra comma in options (was breaking in IE and Opera). (Thanks Jason)
 *   -  Removed the parameter name from the initialize function
 *   -  Changed the way expires date was being calculated. (Thanks David)
 *   v 0.3
 *   -  Removed dependancy on json.js (http://www.json.org/json.js)
 *   -  empty() function only deletes the cookies set by CookieJar
 */

var CookieJar = Class.create();

CookieJar.prototype = {

	/**
	 * Append before all cookie names to differntiate them.
	 */
	appendString: "__CJ_",

	/**
	 * Initializes the cookie jar with the options.
	 */
	initialize: function(options) {
		this.options = {
			expires: 3600,		// seconds (1 hr)
			path: '',			// cookie path
			domain: '',			// cookie domain
			secure: ''			// secure ?
		};
		Object.extend(this.options, options || {});

		if (this.options.expires != '') {
			var date = new Date();
			date = new Date(date.getTime() + (this.options.expires * 1000));
			this.options.expires = '; expires=' + date.toGMTString();
		}
		if (this.options.path != '') {
			this.options.path = '; path=' + escape(this.options.path);
		}
		if (this.options.domain != '') {
			this.options.domain = '; domain=' + escape(this.options.domain);
		}
		if (this.options.secure == 'secure') {
			this.options.secure = '; secure';
		} else {
			this.options.secure = '';
		}
	},

	/**
	 * Adds a name values pair.
	 */
	put: function(name, value) {
		name = this.appendString + name;
		cookie = this.options;
		var type = typeof value;
		switch(type) {
		  case 'undefined':
		  case 'function' :
		  case 'unknown'  : return false;
		  case 'boolean'  : 
		  case 'string'   : 
		  case 'number'   : value = String(value.toString());
		}
		var cookie_str = name + "=" + escape(Object.toJSON(value));
		try {
			document.cookie = cookie_str + cookie.expires + cookie.path + cookie.domain + cookie.secure;
		} catch (e) {
			return false;
		}
		return true;
	},

	/**
	 * Removes a particular cookie (name value pair) form the Cookie Jar.
	 */
	remove: function(name) {
		name = this.appendString + name;
		cookie = this.options;
		try {
			var date = new Date();
			date.setTime(date.getTime() - (3600 * 1000));
			var expires = '; expires=' + date.toGMTString();
			document.cookie = name + "=" + expires + cookie.path + cookie.domain + cookie.secure;
		} catch (e) {
			return false;
		}
		return true;
	},

	/**
	 * Return a particular cookie by name;
	 */
	get: function(name) {
		name = this.appendString + name;
		var cookies = document.cookie.match(name + '=(.*?)(;|$)');
		if (cookies) {
			return (unescape(cookies[1])).evalJSON();
		} else {
			return null;
		}
	},

	/**
	 * Empties the Cookie Jar. Deletes all the cookies.
	 */
	empty: function() {
		keys = this.getKeys();
		size = keys.size();
		for(i=0; i<size; i++) {
			this.remove(keys[i]);
		}
	},

	/**
	 * Returns all cookies as a single object
	 */
	getPack: function() {
		pack = {};
		keys = this.getKeys();

		size = keys.size();
		for(i=0; i<size; i++) {
			pack[keys[i]] = this.get(keys[i]);
		}
		return pack;
	},

	/**
	 * Returns all keys.
	 */
	getKeys: function() {
		keys = $A();
		keyRe= /[^=; ]+(?=\=)/g;
		str  = document.cookie;
		CJRe = new RegExp("^" + this.appendString);
		while((match = keyRe.exec(str)) != undefined) {
			if (CJRe.test(match[0].strip())) {
				keys.push(match[0].strip().gsub("^" + this.appendString,""));
			}
		}
		return keys;
	}
};



// MENU
COAL.Menu = {
  
  menu_position: null,
  menu_json: null,
  menu_opened: null,
  first_time: null,
  menu_column: null,
  menu_items: null,
  page_state: null,
  animate_background: null,
  saveEl: null,
  
  init: function(page_state) {
    
    this.page_state = page_state;
    if(this.page_state == 'menu_page') {
      this.animate_background == false;
    } else {
      this.animate_background == true;
    }
    // overriding this
    this.animate_background == false;
    
    this.menu_column = $('menu-column');
    this.menu_items = $$('.menu-item');
    if(this.menu_items.length > 0) {
      this.addMenuEvents();
    }
    
    this.menu_json = COAL.menu_json;
    this.first_time = COAL.first_time;
    if(this.first_time == true) {
      this.animateFirstRun();
    }
    
    COAL.Background.init( this.menu_json, this.animate_background);
    
  },
  addMenuEvents: function(){
    this.menu_items.each( function(mi){
      // add menu_item click handlers
      var children = mi.childElements();
      var link = children[0];
      link.observe( 'mouseover', COAL.Menu.respondToMouseOver, false);
      var ul = children[1];
      if(ul != null) {
        if(ul.tagName.toLowerCase() == 'ul' ) {
          link.observe( 'click', COAL.Menu.respondToClick, false );
          link.onclick = function() {return false;};
        }
      }
    });
  },
  respondToMouseOver: function(event) {
    var element = event.element();
    if(element.tagName.toLowerCase() == 'span' ) {
      element = element.up();
    }
    var el_id = element.up().readAttribute('id');
    var shortname = el_id.gsub('_li', '');
    //COAL.Background.changeBackground( shortname );
  },
  hideAndSeek: function() {
    var element = COAL.Menu.saveEl;
    var ul = element.next();
    var li = element.up();
    var li_siblings = li.siblings();
    li_siblings.each( function(sib) {
      var sib_ul = sib.childElements()[1];
      if( sib_ul != null ) {
        if( sib_ul.visible() == true ) {
          COAL.Menu.hideUL(sib_ul);
        }
      }
    });    
    COAL.Menu.showUL(ul);
    //element.up().addClassName('active');
  },
  respondToClick: function(event) {
    
    var element = event.element();
    
    if(element.tagName.toLowerCase() == 'span' ) {
      element = element.up();
    }
    COAL.Menu.saveEl = element;
    var hast = setTimeout('COAL.Menu.hideAndSeek()',600);
    background_name = 'default';
    var li = element.up();
    var classname_array = li.className.split(' ');
    classname_array.each(function(classname){
      if( classname.include('background_') ) {
        background_name = classname.gsub('background_','');
      };
    });
    //console.log(background_name);
    
    // EK TAKEOUT for Internet Explorer Error
    //COAL.Background.changeBackground( background_name );
  },
  hideUL: function(ul) {
    ul.childElements().each(function(cli) {
      new Effect.Fade( cli, { duration: 0.15, queue: 'front' } );
    });
    new Effect.BlindUp( ul, { duration: 1 } );
    //new Effect.Appear(ul.previous(), { duration: 1 });
  },
  showUL: function(ul) {
    ul.childElements().each(function(cli) {
      cli.show();
      cli.setStyle({'opacity':'0.01'})
      new Effect.Opacity( cli, { from: 0.01, to: 1, duration: 0.35, queue: 'end' } );
    });
    new Effect.BlindDown( ul, { duration: 0.75 } );
    //new Effect.Fade(ul.previous(), { duration: 1 });
  },
  animateFirstRun: function() {
    COAL.Background.animateFirstRun();
    new Effect.Appear( this.menu_column , { duration: 2, queue: 'end' });
    $$('.parent_open').each(function(mi) {
      mi.hide();
      new Effect.Appear( mi, { duration: 0.65, queue: 'end' });
    });
    
  },
  getMenuJSON: function() {
    return this.menu_json;
  },
  getMenuPosition: function(){
    return this.menu_position;
  },
  getMenuOpened: function(){
    return this.menu_opened;
  },
  setMenuJSON: function(mj){
    this.menu_json = mj;
  },
  setMenuPosition: function(mp){
    this.menu_position = mp;
  },
  setMenuOpened: function(mo) {
    this.menu_opened = mo;
  }
}


// BACKGROUND
COAL.Background = {
  photos: [],
  image_folder: '/images/backgrounds/',
  load_count: 0,
  shortnames: new Array(),
  // setup
  ih: 0,
  iw: 0,
  iar: 1,
  war: 1,
  img: '',
  timeOut: null,
  ww: null,
  wh: null,
  wr: null,
  holder: null,
  current_photo: null,
  PE: null,
  newPhoto: null,
  switchTimeout: null,
  animate_background: null,
  
  init: function( json, animate ) {
    this.holder = $('background');
    this.animate_background = animate;
    this.parseJSON(json);
    this.shortnames = this.shortnames.uniq();
    startTimeout = setTimeout("COAL.Background.startMeUp()", 500)
  },
  startMeUp: function(){
    // shortnames is an array of the necessary background images
    // load each one into a COAL.Photo object then put it in the background
    for (i = 0; i < COAL.Background.shortnames.length; i++) {
        shortname = COAL.Background.shortnames[i];
        newPhoto = Object.create(COAL.Photo);
        newPhoto.init(COAL.Background);
        newPhoto.folder = COAL.Background.image_folder;
        newPhoto.shortname = shortname;
        COAL.Background.photos.push(newPhoto);
    };
    COAL.Background.initResizer();
    //COAL.Background.loadNextPhoto(COAL.Background);
    COAL.Background.startObservers();
  },
  changeBackground: function(shortname) {
    //clearTimeout(COAL.Background.switchTimeout);
    this.photos.each(function(photo){
      if(photo.shortname == shortname){
        if(photo.active != true) {
          COAL.Background.newPhoto = photo;
          //COAL.Background.switchTimeout = setTimeout("COAL.Background.switchPhotos()",10);
          COAL.Background.switchPhotos();
        }
      }
    });
  },
  switchPhotos: function() {
    new Effect.Appear( COAL.Background.newPhoto.element, { duration: 0.3, queue:  { position: 'end', scope: 'background' } } );
    COAL.Background.newPhoto.active = true;
    if(this.current_photo != null) {
      oldPhoto = this.current_photo;
      new Effect.Fade( oldPhoto.element, { duration: 0.3, queue: { position: 'end', scope: 'background' } } );
      oldPhoto.active = false;
    }
    this.current_photo = COAL.Background.newPhoto;
  },
  parseJSON: function(obj) {
    var page = obj['page'];
    var shortname = obj['shortname'];
    var background = obj['background'];
    var children = obj['children'];
    var animate = obj['animate'];
    if(background && animate) {
      this.shortnames.push( background );
    }
    if(children.length > 0) {
      children.each( function(child){
        COAL.Background.parseJSON( child );
      });
    }
  },
  startObservers: function() {
    Event.observe(window, 'resize', function(e) { COAL.Background.resize(e); } );
    COAL.Background.PE = new PeriodicalExecuter( function(pe) {
      COAL.Background.resize(pe);
    }, 1);
  },
  loadNextPhoto: function(context) {
    if(context.load_count < context.photos.length) {
      context.photos[context.load_count].loadImage();
      context.load_count = context.load_count + 1;
    } else {
      COAL.Background.resize();
    }
  },
  imageLoaded: function(photoObj) {
    COAL.Background.loadNextPhoto(COAL.Background);
    COAL.Background.insertPhoto(photoObj);
    COAL.Background.resize();
  },
  insertPhoto: function(photoObj) {
			var img = new Element('img', { 'id': photoObj['shortname'], 'class': 'background_image' });
			img.setStyle({'opacity':0});
			$("background-holder").insert( img );
			photoObj.element = img;
			img.src = photoObj.image.src;
  },
  animateFirstRun: function() {
    $("background-holder").setStyle( { 'opacity' : 0.1, 'display' : 'block' } );
    new Effect.Appear($('background-holder'), { duration: 3, queue: 'front' } );
    // console.log(COAL.Background.holder.show());
    //new Effect.Appear('anim_logo', { duration: 2.5, queue: 'end', afterFinish: function() { Menu.start(); } });
  },
  GetWindowSize: function(w) {
    w = w ? w : window;
    var width = w.innerWidth || ( w.document.documentElement.clientWidth || w.document.body.clientWidth );
    var height = w.innerHeight || ( w.document.documentElement.clientHeight || w.document.body.clientHeight );
    return [width, height];
  },
  // initialize
  initResizer: function() {
    // image height, width and aspect ratio
    COAL.Background.images_array = $$('.background_image');
    COAL.Background.holder = $('background-holder');
    COAL.Background.number_of_images = COAL.Background.images_array.length;
    COAL.Background.img = COAL.Background.images_array[0];
    COAL.Background.ih = 800;
    COAL.Background.iw = 1200;
    COAL.Background.iar = COAL.Background.iw / COAL.Background.ih;
    COAL.Background.resize();
  },
  resize: function() {
    // window width, height and aspect ratio
    var window_dimensions = COAL.Background.GetWindowSize(window);
    COAL.Background.images_array = $$('.background_image');
    
    if( COAL.Background.ww !== window_dimensions[0] || COAL.Background.wh !== window_dimensions[1] || COAL.Background.number_of_images !== COAL.Background.images_array.length ) {
      COAL.Background.number_of_images = COAL.Background.images_array.length;
      COAL.Background.ww = window_dimensions[0];
      COAL.Background.wh = window_dimensions[1];
      COAL.Background.resizeExecute(window_dimensions[0],window_dimensions[1]);
      return true;
    } else {
      return false;
    }
  },
  resizeExecute: function( window_width, window_height ) {
    
    //COAL.Background.ih = COAL.Background.img.getHeight();
    //COAL.Background.iw = COAL.Background.img.getWidth();
    image_width = COAL.Background.iw;
    image_height = COAL.Background.ih;
    image_ratio = COAL.Background.iar;
    
    new_image_width = window_width;
    new_image_height = ( new_image_width / image_width ) * image_height;
    width_diff = '0';
    height_diff = -( new_image_height - window_height ) / 2;
    
    if( new_image_height < window_height ) {
      new_image_height = window_height;
      new_image_width = ( new_image_height / image_height ) * image_width;
      height_diff = '0';
      width_diff = -( new_image_width - window_width ) / 2;
    };
    
    niw = Math.ceil(new_image_width);
    nih = Math.ceil(new_image_height);
    
    COAL.Background.images_array.each( function(simage, index) {
      simage.setStyle({ 
        'width': niw+"px", 
        'height': nih+"px", 
        'top': height_diff+'px', 
        'left': width_diff+'px' 
      });
    });
    
    COAL.Background.holder = $("background-holder");
    $("background-holder").setStyle( { height: window_height+"px", display: 'block' } );
    
    var background_dimensions = { height: nih, width: niw, top: height_diff+'px', left: width_diff+'px' };
    COAL.cookie_jar.put( 'background_dimensions', background_dimensions );
    
  }

}

COAL.Photo = {
  
  active: null,
  shortname: '',
  folder: '/images/',
  extension: 'jpg',
  image: null,
  callbackObject: null,
  element: null,
  
  init: function(callbackObject) {
    this.callbackObject = callbackObject;
  },
  onLoad: function(photoObject) {
      // image preload callback
      // console.log(photoObject.getFilename() + ' is loaded.');
      photoObject.callbackObject.imageLoaded(photoObject);
  },
  onError: function(photoObject) {
      // image error callback
      //console.log(photoObject.getFilename() + ' has an error.');
      //photoObject.callbackObject.imageLoaded(photoObject);
  },
  getFilename: function() {
      return this.shortname + '.' + this.extension;
  },
  getPath: function() {
      return this.folder + this.getFilename();
  },
  loadImage: function() {
    imageObject = new Image();
    imageObject.that = this;
    imageObject.onload = function() { this.that.onLoad(this.that); }
    imageObject.onerror = function() { this.that.onError(this.that); }
    imageObject.onabort = function() { this.that.onError(this.that); }
    imageObject.src = this.getPath();
    this.image = imageObject;
  }
};

// SLIDE SHOW
COAL.SlideShow = {
  
  image_urls: [],
  image_elements: [],
  load_status: [],
  preloaded: false,
  interval_time: 5,
  transition_time: 1,
  container: '',
  target_image: '',
  current_index: '',
  preload_index: 1,
  container_class_name: '',
  timer: '',
  animation_timer: '',
  previous_index: -1,
  loadcheck_timer: '',
  check_time: 250,
  
  init: function( images_json, class_name, transition, interval ) {
    
    // grab variables
    this.image_urls = images_json;
    this.container_class_name = class_name;
    this.transition_time = transition;
    this.interval_time = interval * 1000;
    this.image_elements = [];
    this.current_index = 0;
    this.preload_index = 0;
    this.preloaded = false;
    this.previous_index = -1;
    this.loadcheck_timer = '';
    this.check_time = 250;
    
    // setup
    this.container = $$( '.' + this.container_class_name )[0];
    this.target_image = this.container.firstDescendant();
    this.image_elements.push(this.target_image);
    
    // create image elements
    var images = [];
    this.image_urls.each(function(image_url,index) {
      var img = new Element( 'img', { 'id': 'coal_slideshow' + index, 'alt': 'Coal Headwear', 'style':'display:none;' });
      images.push(img);
    });
    this.image_elements = images;
    
    // keep track of load status... start with all
    this.load_status[0] = true;
    for( i = 1; i <= this.image_elements; i++ ) {
      this.load_status.push(false);
    }
    
    // start loading
    this.preload_next();
    
    // set timer for transition
    // find out how to do this within our context... pass object instance variable name in as argument?
    this.timer = setInterval( 'COAL.SlideShow.next_slide();', this.interval_time );
    
  },
  change: function(new_url) {
    // animate to a new image
    
  },
  next_slide: function() {
    // animate to the next image in the array
    this.previous_index = this.current_index;
    this.current_index++;
    if(this.current_index >= this.image_elements.length ) {
      this.current_index = 0;
    }
    this.loadcheck_timer = setInterval( 'COAL.SlideShow.animate_transition();', this.check_time );
  },
  animate_transition: function() {
    clearInterval(this.loadcheck_timer);
    if( this.load_status[this.current_index] == true ) {
      if(this.current_index == 0) {
        this.image_elements[this.previous_index].fade({ duration: this.transition_time });
      } else {
        this.image_elements[this.current_index].appear({ duration: this.transition_time });
      }
      this.animation_timer = setInterval( 'COAL.SlideShow.appear_complete();', ( this.transition_time + 0.5 ) * 1000 );
    } else {
      this.loadcheck_timer = setInterval( 'COAL.SlideShow.animate_transition();', this.check_time );
    }
  },
  appear_complete: function() {
    // hide the previous image if this is beyond the first image...
    if(this.previous_index > 0) {
      this.image_elements[this.previous_index].hide();
    }
    clearInterval(this.animation_timer);
  },
  preload: function(index) {
    var img = this.image_elements[index];
    Event.observe( img, 'load', function() {
      COAL.SlideShow.preload_complete();
    });
    img.src = this.image_urls[index];
  },
  preload_complete: function() {
    // handler when loading is complete
    var img = this.image_elements[ this.preload_index ];
    Element.insert( this.container, { bottom: img });
    this.load_status[this.preload_index] = true;
    this.preload_next();
  },
  preload_next: function() {
    // see if the next image can be preloaded... if it can, do so.
    this.preload_index++;
    if( this.preload_index >= this.image_urls.length ) {
      this.preloaded = true;
    } else {
      this.preload( this.preload_index );
    }
  }
}

COAL.Favorites = {
  
  numFavs: null,
  
  init: function(num) {
    this.numFavs = num;
  },
  setNumPageText: function() {
    target = $('favorite_status');
    if( target != undefined ) {
      target_text = this.getNum() + ' Favorites';
      target.update(target_text);
      //console.log(target_text);
    }
  },
  setNum: function(num) {
    this.numFavs = num;
    this.setNumPageText();
    return num;
  },
  getNum: function() {
    return this.numFavs;
  },
  add: function(add_num) {
    var newNum = this.getNum() + add_num;
    this.setNum(newNum);
  },
  remove: function(remove_num) {
    var newNum = this.getNum() - remove_num;
    this.setNum(newNum);
  }
  
}
