/**
  @description    Global JavaScript for ABC 2010 website project
  @author         J. Flores, Elliance, inc.
  @contact        jflores@elliance.com
  @client         Appalachian Bible College
**/

//master dom:ready observer
document.observe("dom:loaded", function() {
  bgSwitch.change(bgSwitch.current());
});

//master window loaded observer
Event.observe(window,'load', function() {
        bgSwitch.initialize();

});

//master cookieJar. Put all the cookies in here.
var abcJar = new CookieJar({
  expires: 31556926, //a year
  path: '/'
});

//bgswitcher - Widget to change the background image on all pages.
var bgSwitch = {
  body: function() { return $(document.body); },
  switchBox: function() { return $('switchBox'); },
  trigger: function() { return $('switchTab'); },
  teaser: function() { return $('switchTease'); },
  initialize: function() {
    this.body().setStyle({ height: document.body.offsetHeight + 'px' }); //hack to make photo appear in the right place.
    $('bgSwitcher').show().observe('click', this.handleClick.bind(this)); //handle clicks on the switcher
    this.change(this.current()); //set the initial background
    this.teaser().observe('mouseover', this.tease.bind(this)); //teaser observer
  },
  
  tease: function(event) {
    if (this.switchBox().visible() || this.teasing) return false; //no need to tease if it's already open
    new Effect.Tease(this.teaser().down('h4'), {
      duration: .75,
      to: '4px'
    });
  },
  
  handleClick: function(event) {
    event.stop(); //prevent bubbling
    var element = event.element();
    if ('IMG' != element.tagName && 'H4' != element.tagName) { //exit if the click wasn't on an image
      return false;
    } else { //we click on an image and thus need to handle it
      if ('switchTab' == element.id || 'H4' == element.tagName) { //if it's the toggle tab
        this.toggle(this.trigger());
      } else { //it's a background image
        this.change(element.src.gsub('/thumbs',''));
      }
    }
    return false;
  },
  
  current: function() {
    var cookiePath = abcJar.get('userBackground');
    return cookiePath || this.switchBox().down('div.thumbs img').src.gsub('/thumbs','');
  },
  
  cookieIt: function(path) {
    abcJar.put('userBackground',path);
  },
  
  change: function(path) {
    this.body().setStyle({ backgroundImage: 'url(' + path + ')' });
    this.cookieIt(path);
  },
  
  toggle: function(box) {
    var isVisible = this.switchBox().visible();
    var direction = isVisible ? "SlideUp" : "SlideDown"
    var easing = isVisible ? "easeIn" : "easeOut";
    
    //stop the teasing, if needed
    Effect.Queues.get(this.trigger().id).invoke('cancel');
    this.trigger().setOpacity(1); //reset the opacity in case canceling left it transluscent
    
    new Effect[direction](this.switchBox(), {
      duration: .35,
      scaleContent: false,
      transition: Effect.Transitions.Back[easing],
      afterFinish: function() {
        box.src = '/_images/interface/icons/switchTab' + (isVisible ? 'Down.png' : 'Up.png');
      }
    });
  }
}

FancyAccordion = Class.create({
  initialize: function(parent, triggerPattern, contentPattern, options) {
    this._parent = $(parent);
    this._triggerPattern = triggerPattern;
    this._contentPattern = contentPattern;
    this._triggers = $$('#' + parent + ' > ' + triggerPattern);
    this._options = options;
    
    //initialize observer
    this._parent.observe('click', this.handleClick.bind(this));
    
    //if we're using opacity, make sure we're starting at the right opacity
    if (this._options.useOpacity && this._options.initialOpacity != 1) {
      this.setInitialOpacity();
    }
    
    //are we supposed to open a panel on load?
    if ("number" == typeof this._options.openOnLoad) {
      this.forceTrigger(this._options.openOnLoad);
    }
  },
  
  setInitialOpacity: function() {
    var effects = $A();
    var pattern = this._options.opacityPattern;
    var opacity = this._options.initialOpacity;
    this._triggers.each(function(e) {
      var element = e.down(pattern);
      if (element) {
        effects.push(new Effect.Opacity(element, {
          sync: true,
          from: 1,
          to: opacity
        }));
      }
      
      if (effects.length > 0) {
        new Effect.Parallel(effects, {
          duration: 0.2
        });
      }
    });
  },
  
  forceTrigger: function(position) {
    var trigger = this._triggers[position];
    this.triggerClick(trigger);
  },
  
  triggerClick: function(trigger) {
    var content = trigger.next(this._contentPattern);
    var isVisible = content.visible();
    effects = this.prepareEffects(trigger,content,isVisible); //the action for the passed trigger
    
    var openContent = this._parent.select(this._contentPattern + '.open').reject( function(item) {
      return item == content; }).first();
    if (openContent) {
      openTrigger = openContent.previous(this._triggerPattern);
      effects.push(this.prepareEffects(openTrigger,openContent,true)); //the action for any other visible content
      effects = effects.flatten();
    }

    this.handleEffects(effects); //fire animation
  },
  
  handleClick: function(event) {
    var element = event.element();
    if (this._triggers.include(element) || this._triggers.include(element.up(this._triggerPattern))) {
      event.stop(); //prevent bubbling
      this.triggerClick(this._triggers.include(element) ? element : element.up(this._triggerPattern));
    }
  },
  
  prepareEffects: function(trigger, content, isVisible) {
    var effects = $A();
    var direction = isVisible ? "SlideUp" : "SlideDown";
    effects.push(new Effect[direction](content, {
      sync: true,
      transition: this._options.easing,
      afterFinish: function() { content.toggleClassName('open'); }
    }));
    
    if (this._options.useRotation) {
      var rotationElement = trigger.down(this._options.rotatePattern);
      var degree = isVisible ? this._options.rotation * -1 : this._options.rotation;
      effects.push(new Effect.Rotate(rotationElement,degree, {
        sync: true,
        transition: this._options.easing
      }));
    }
    
    if (this._options.useOpacity) {
      var opacityElement = trigger.down(this._options.opacityPattern);
      var nowOpacity = opacityElement.getStyle('opacity');
      var newOpacity = isVisible ? this._options.closedOpacity : this._options.openOpacity;
      effects.push(new Effect.Opacity(opacityElement, {
        from: nowOpacity,
        to: newOpacity,
        sync: true
      }));
    }
    return effects;
  },
  
  handleEffects: function(effects) {
    var timing = this._options.duration ? this._options.duration : 1;
    new Effect.Parallel(effects, {
      afterFinish: this._options.afterChange || null,
      duration: timing,
      queue: {
        position: 'end',
        scope: this._parent.id,
        limit: 1
      }
    });
  }
});

Panelizer = Class.create({
  initialize: function(panelBox, panelThumbs, thumbsPattern, indicator, options) {
    this._panelBox = $(panelBox);
    this._panels = this._panelBox.select('div.panel');
    this._panelThumbBox = this._panelBox.down(panelThumbs);
    this._panelThumbs = this._panelThumbBox.select(thumbsPattern);
    this._indicator = this._panelBox.down(indicator);
    this._options = options;
    this._activePanel = null;
    
    //attach observers
    this._panelThumbBox.observe('click', this.thumbClick.bind(this)); //click observer
    
    if (this._options.useOpacity) {
      this._panelThumbBox.observe('mouseover', this.thumbMouseOver.bind(this)); //mouseover observer
      this._panelThumbBox.observe('mouseout', this.thumbMouseOut.bind(this)); //mouseout observer
    }
    
    //auto switch position?
    if (this._options.autoSwitch) {
      this.startTimer(this._options.switchDelay);
    }

    //activate initial
    this.switchTo(this._options.startPosition || 0);
  },
  
  thumbMouseOver: function(event) {
    var element = event.element();
    if ("IMG" == element.tagName) { //we got a thumb
      new Effect.Opacity(element, {
        from: this._options.opacityValues.initial,
        to: this._options.opacityValues.hover,
        duration: this._options.opacityValues.timing
      });
    } else {
      return false;
    }
  },
  
  thumbMouseOut: function(event) {
    var element = event.element();
    if ("IMG" == element.tagName) { //we got a thumb
      new Effect.Opacity(element, {
        from: this._options.opacityValues.hover,
        to: this._options.opacityValues.initial,
        duration: this._options.opacityValues.timing,
        queue: { //by checking the queue, we prevent this fading from happening if our hovered element is the same as our clicked element
          position: 'end',
          scope: this._panelBox.id,
          limit: 1
        }
      });
    } else {
      return false;
    }
  },
  
  thumbClick: function(event) {
    var element = event.element();
    if (this._panelThumbs.include(element)) {
      this.switchTo(this._panelThumbs.indexOf(element), true);
    }
  },
  
  switchTo: function(index, isClick) {
    if (this._activePanel === index) return false; //same panel, don't do anything
    var newThumb = this._panelThumbs[index];
    var indicator = this._indicator;
    
    //determine locations
    var thumbPosition = newThumb.cumulativeOffset();
    var containerPosition = this._panelBox.cumulativeOffset();
    var newPosition = {
      left: thumbPosition.left - containerPosition.left + (this._options.indicatorOffsetLeft || 0),
      top: thumbPosition.top - containerPosition.top + (this._options.indicatorOffsetTop || 0)
    };
    
    var effects = $A();
    
    if (this._options.useOpacity) {
      var opacityFadeOptions = {
        sync: true,
        from: this._options.opacityValues.full,
        to: this._options.opacityValues.initial,
        transition: this._options.easing
      };
      var opacityAppearOptions = {
        sync: true,
        from: this._options.opacityValues.initial,
        to: this._options.opacityValues.full,
        transition: this._options.easing
      };
    }
    
    //indicator shifting animation
    if (!indicator.visible()) { //make it visible; initial load
      effects.push(new Effect.Appear(this._indicator, {
        sync: true,
        beforeStart: function() {
          indicator.setStyle("left: " + newPosition.left + 'px; ' + 'top: ' + newPosition.top + 'px; position: absolute;');
        }
      }));
    } else { //indicator is visible, just move it to the new thumb
      effects.push(new Effect.Move(this._indicator, {
        sync: true,
        mode: 'absolute',
        x: newPosition.left,
        y: newPosition.top,
        transition: this._options.easing
      }));
    }

    //inactive thumb opacity shift animation
    if (this._options.useOpacity) {
      if (!indicator.visible()) {
        this._panelThumbs.each(function(e) {
          if (e != newThumb) {
            effects.push(new Effect.Opacity(e, opacityFadeOptions));
          }
        });
      } else {
        effects.push(new Effect.Opacity(this._panelThumbs[this._activePanel], opacityFadeOptions));
      }
      
      //active thumb opacity shift
      effects.push(new Effect.Opacity(newThumb, opacityAppearOptions));
    }
    
    if (this._options.useMorph) {
      //old thumb should morph to off
      if (indicator.visible()) {
        effects.push(new Effect.Morph(this._panelThumbs[this._activePanel], {
          sync: true,
          style: this._options.morphStyles.off
        }));
      }
      
      //new thumb should morph to on
      effects.push(new Effect.Morph(newThumb, {
        sync: true,
        style: this._options.morphStyles.on
      }));
    }
    
    //if there's a content height difference, morph the container
    //we need to do this since the panels are (most likely) absolutely positioned, taking them out of the page flow
    //morphing the panel container ensures that the surrounding elements respond appropriately to the changing panel size.
    if (!indicator.visible() || (this._panels[index].getHeight() != this._panels[this._activePanel].getHeight())) {
      effects.push(new Effect.Morph(this._panels.first().up(), {
        sync: true/*,
        style: "height: " + this._panels[index].getHeight() + "px;"*/
      }));
    }
    
    //newPanel appearing animation
    effects.push(new Effect.Appear(this._panels[index], {
      sync: true,
      transition: this._options.easing,
      afterFinish: this.setPanel.bind(this, index)
    }));
    
    //oldPanel, if any, fading animation
    if ("number" == typeof this._activePanel) {
      effects.push(new Effect.Fade(this._panels[this._activePanel], {
        sync: false,
		duration: 0,
        transition: this._options.easing
      }));
    }
    
    //pause autoSwitching if it's a click
    if (isClick && this._options.autoSwitch) this.pauseTimer();
    this.handleEffects(effects);
  },
  
  handleEffects: function(effects) {
    var timing = this._options.duration ? this._options.duration : 1;
    new Effect.Parallel(effects, {
      duration: timing,
      queue: {
        position: 'end',
        scope: this._panelBox.id,
        limit: 1
      },
      afterFinish: this._options.afterChange || null
    });
  },
  
  startTimer: function(delay) {
    this.timer = setInterval(this.autoMove.bind(this), delay * 1000);
  },
  
  pauseTimer: function() {
    clearInterval(this.timer);
    if (this.paused) clearTimeout(this.paused);
    this.paused = setTimeout(this.startTimer.bind(this, this._options.switchDelay), this._options.pauseTime * 1000);
  },
  
  autoMove: function() {
    var totalThumbs = this._panelThumbs.length;
    var index = this._activePanel == totalThumbs - 1 ? 0 : this._activePanel + 1;
    this.switchTo(index, false);
  },
  
  setPanel: function(index) {
    this._activePanel = index;
  }
});

//panelLoader - builds a set of panels for use with Panelizer
PanelLoader = Class.create({
  initialize: function(container, triggerContainer, panelList, options) {
    this._container = $(container);
    this._triggerContainer = $(triggerContainer);
    this._panelList = $A(panelList);
    this._options = options;
  },
  
  start: function() {
    this._panelList.each(function(e) {
      this.load(e);
    }.bind(this));
  },
  
  load: function(panel) {
    if (panel == this._panelList.first() && this._options.before) {
      this._options.before(); //execute before callback
    }
    new Ajax.Request(panel[1], {
      asynchronous: false,
      method: 'get',
      onSuccess: function(transport) {
        this.enable(panel[0],transport.responseText);
      }.bind(this)
    });
  },
  
  enable: function(label,content) {
    var trigger = new Element('li', {
      style: 'display: none;'}).update(label);
    var copy = new Element('div', {
      'class': 'panel',
      style: 'display: none;'
    }).update(content);
    
    this._container.insert({ bottom: copy });
    this._triggerContainer.insert({ bottom: trigger });
    
    new Effect.Appear(trigger, {
      duration: 0.25,
      queue: {
        position: 'end',
        scope: this._triggerContainer.id
      },
      transition: Effect.Transitions.Cubic.easeInOut,
      afterFinish: function(effect) {
        if (label == this._panelList.last()[0] && this._options.after)
          this._options.after(); //execute after callback
      }.bind(this)
    });
  }
});

//roleExplorer - simple hover interactions to highlight programs
//see it on the academics index
var roleExplorer = {
  initialize: function(container, options) {
    this._container = $(container);
    this._roleBoxes = this._container.select('p');
    this._options = options || {};
    this._activeElement = null;
    
    //set initial opacity
    this.initialOpacity();
    
    //initialize observers
    this._roleBoxes.each(function(box) {
      box.observe('mouseover', this.mouseOver.bind(this)); //mouseover observer
      box.observe('mouseout', this.mouseOut.bind(this)); //mouseout observer
    }.bind(this));
  },
  
  initialOpacity: function() {
    var opacity = this._options.offOpacity || .5;
    var effects = $A();
    this._roleBoxes.each(function(box) {
      effects.push(new Effect.Opacity(box.up('div'), {
        sync: true,
        from: 1,
        to: opacity
      }));
    });
    
    new Effect.Parallel(effects, {
      duration: this._options.duration || .5,
      transition: this._options.easing || Effect.Transitions.Cubic.easeInOut
    });
  },
  
  mouseOver: function(event) {
    var element = event.findElement('div');
    new Effect.Opacity(element, {
      from: this._options.offOpacity || .5,
      to: 1,
      duration: this._options.duration || .5,
      transition: this._options.easing || Effect.Transitions.Cubic.easeInOut    
    });
  },
  
  mouseOut: function(event) {
    var element = event.findElement('div');
    new Effect.Opacity(element, {
      to: this._options.offOpacity || .5,
      from: 1,
      duration: this._options.duration || .5,
      transition: this._options.easing || Effect.Transitions.Cubic.easeInOut    
    });
  }
}

//lifeExplorer rotates through a fixed set of objects, sliding and moving in a kind of perpetual slideshow
var LifeExplorer = {
  initialize: function(container, options) {
    this._container = $(container);
    this._options = options || {};
    this._timer = setInterval(this.nextMessage.bind(this), (this._options.scrollSpeed || 2) * 1000);
  },
  
  nextMessage: function() {
    var target = this._container.down(this._options.messagePattern || 'div');
    new Effect.SlideUp(target, {
      duration: this._options.duration || .5,
      transition: this._options.easing || Effect.Transitions.Quad.easeInOut,
      afterFinish: function(effect) {
        this._container.insert({ bottom: effect.element });
        effect.element.show();
      }.bind(this)
    });
  }
}

Effect.Tease = function(element) {
  element = $(element);
  if (element.isTeasing) return false;
  element.isTeasing = true;
  var options = Object.extend({
    from: '0px',
    to: '20px',
    duration: 0.5
  }, arguments[1] || {});
  var split = parseFloat(options.duration) / 4.0;
  return new Effect.Morph(element,
    { style: { paddingTop: options.to }, duration: split, afterFinish: function(effect) {
  new Effect.Morph(effect.element,
    { style: { paddingTop: options.from }, duration: split, afterFinish: function(effect) {
  new Effect.Morph(effect.element,
    { style: { paddingTop: options.to }, duration: split, afterFinish: function(effect) {
  new Effect.Morph(effect.element,
    { style: { paddingTop: options.from }, duration: split, afterFinish: function(effect) {
      effect.element.setStyle({ paddingTop: options.from });
      effect.element.isTeasing = false;
  }}); }}); }}); }});
};

function course_info(crs) {
	$('copy').insert("<div onclick='$(this).remove()'><div id='screen_shade' style='position:fixed; top:0px; left:0px; width:100%; height:100%; background:black; z-index:500; display:none;'></div><div id='crs_div' style='position:fixed; top:30%; left:50%; margin-left:-300px; width:600px; height:auto; z-index:600;'></div></div>");
	Effect.Appear($('screen_shade'), {from: 0, to: 0.7, duration:0.3});
	new Ajax.Updater('crs_div', '/catalog/courses/courses.php?course_only=true&search='+crs);
}
