var Preload =  {
  procs: new Array(),
  ran: false,
  register: function(proc) { 
    if(Preload.ran) {
      proc(); 
    }else{
      Preload.procs.push(proc); 
    }
  },
  run: function() {
    if(Preload.ran == true) { return; }
    Preload.ran = true;
    for(var i = 0; i < Preload.procs.length; i++){
      Preload.procs[i]();
    }
  }
}
Event.observe(document, "DOMContentLoaded", Preload.run);
Event.observe(window, "load", Preload.run);

var TourSegment = {
  initialize: function() {
    this.heading = $('page-main').getElementsByTagName('h1')[0];
    this.description = document.getElementsByClassName('description', $('page-main'))[0];
    this.slides = $('slides');
    if(this.slides) {
      [ this.heading, this.description ].compact().each(Element.hide);
      Object.extend(this.slides, Slides);
      this.slides.initialize();
    }
  },
  play: function() {
    Preload.run();
    if(!this.slides) return;
    this.slides.introduce();
    new Effect.Parallel([
      new Effect.BlindDown(this.heading, {sync:true}),
      new Effect.Appear(this.heading, {sync:true})
      ],{
        queue:'end',
        afterSetup:function(){
          this.slides.style.height = this.slides.frames[0].image.offsetHeight + 'px';
          this.heading.style.marginBottom = '20px';
        }.bind(this)
    });
    new Effect.Appear(this.description, { 
       duration:1, 
       queue:'end', 
       afterFinish:this.slides.enableHover.bind(this.slides)}
    );
  }
};

Preload.register(TourSegment.initialize.bind(TourSegment));
Event.observe(window, 'load', TourSegment.play.bind(TourSegment));

var Slides = {
  initialize: function() {
    this.frames = document.getElementsByClassName('frame', this);
    this.length = this.frames.length;
    for(var i = 0; i < this.frames.length; i++) { 
      Object.extend(this.frames[i], Frame);
      this.frames[i].initializeFrame(this, i);
    }
  },
  introduce: function() {
    for(var i = 0; i < this.frames.length; i++) {
      this.frames[i].introduce();
    }
  },
  enableHover: function() {
    for(var i = 0; i < this.frames.length; i++) {
      this.frames[i].enableHover();
    }
  }
};

var Frame = {
  initializeFrame: function(slides, pos) {
    this.frameIndex = pos;
    Element.hide(this);
    this.slides = slides;
    this.bullet = this.getElementsByTagName("h2")[0];
    this.graphic = document.getElementsByClassName('screenshot', this)[0];
    this.image = this.graphic.getElementsByTagName("img")[0];
    this.image.originalWidth = this.image.getAttribute('width') || 530;
    this.image.originalHeight = this.image.getAttribute('height') || 423;
    [ this.bullet, this.graphic ].compact().each(Element.hide);
  },
  getTinyFrameOffsets: function() {
    var x = ((530 / this.slides.length) * this.frameIndex);
    var y = 0;
    return [x, y];
  },
  introduce: function() {
    Element.show(this);
    this.bullet.style.width = '530px';
    new Effect.Appear(this.bullet, {queue:'end',duration:1});
    new Effect.Parallel([],{duration:0.5,queue:'end'});
    this.graphic.style.zIndex = 11;
    this.image.style.zIndex = 11;
    new Effect.Parallel([
      new Effect.DropOut(this.bullet, {duration:1,sync:true}),
      new Effect.Appear(this.graphic, {duration:1,sync:true})
    ], {queue:'end'});
    new Effect.Parallel([],{duration:1,queue:'end'});
    this.shrink();
  },
  selected:false,
  big:false,
  transitioning:false,
  enableHover: function() {
    this.graphic.style.zIndex = 10;
    this.image.style.cursor = 'pointer';
    this.minimizedOpacity = 0.7;
    new Effect.Opacity(this.graphic,{to:this.minimizedOpacity,queue:'end',duration:0.3});
    Event.observe(this.graphic, 'mouseover', function() {
      if(!this.selected && !this.big) {
        this.selected = true;
        new Effect.Opacity(this.graphic, {from:this.minimizedOpacity, 
                                         to:1.0, duration:0.1});
      }
    }.bind(this));
    Event.observe(this.graphic, 'mouseout', function() {
      if(this.selected && !this.big) {
        this.selected = false;
        new Effect.Opacity(this.graphic, {from:1.0, to:this.minimizedOpacity, 
                                       duration:0.1});
      }
    }.bind(this));
    Event.observe(this.graphic, 'click', function() {
      this.big ? this.shrink() : this.grow();
    }.bind(this));
  },
  minimizedOpacity:0.2,
  shrink: function() {
    if(this.transitioning) return;
    this.transitioning = true;
    this.graphic.style.position = 'absolute';
    var pos = this.getTinyFrameOffsets();
    var effects = [
      new Effect.MoveBy(this.graphic, 0, pos[0], {sync:true}),
      new Effect.Scale(this.image, (100 / this.slides.length) - 1, {sync:true}),
      new Effect.Opacity(this.graphic, {
        to:this.minimizedOpacity, 
        sync:true
      })
    ];
    if(this.big) {
      for(var i = 0; i < this.slides.frames.length; i++) {
        if(i == this.frameIndex) continue;
        var frame = this.slides.frames[i];
        Element.show(frame)
        effects.push(
          new Effect.Opacity(frame.graphic, {
            to:this.minimizedOpacity,
            sync:true
          })
        );
      }
    }
    new Effect.Parallel(effects, {
      duration:0.6,
      queue:'end',
      afterFinish:function(){
        this.graphic.style.zIndex = 10;
        this.transitioning = false;
        this.big = false;
      }.bind(this)}
    );
  },
  grow: function() {
    if(this.transitioning) return;
    this.transitioning = true;
    this.graphic.style.zIndex = 11;
    var pos = this.getTinyFrameOffsets();
    var effects = [
       new Effect.MoveBy(this.graphic, 0, -pos[0], {sync:true}),
       new Effect.Scale(this.image, (100 * this.slides.length) + (this.slides.length * 2), {sync:true}),
       new Effect.Opacity(this.graphic, {from:this.minimizedOpacity,
                                         to:1.0,sync:true})
    ];
    for(var i = 0; i < this.slides.frames.length; i++) {
      if(i == this.frameIndex) continue;
      var frame = this.slides.frames[i];
      effects.push(
        new Effect.Opacity(frame.graphic, {
          from:this.minimizedOpacity,
          to:0,
          sync:true,
          afterFinish:function(){Element.hide(this)}.bind(frame)
        })
      );
    }
    new Effect.Parallel(effects, {
      duration:0.4,
      queue:'end',
      afterFinish:this.originalizeImageWidths.bind(this)
    });
  },
  originalizeImageWidths: function() {
    this.image.style.height = this.image.originalHeight + 'px';
    this.image.style.width = this.image.originalWidth + 'px';
    this.big = true;
    this.transitioning = false;
  }
}
