var ElementTransition = Class.create({
  initialize: function(element, options) {
    this.element = $(element);
    this.options = $H({
      elements_selector: '.transition-element',
      effect: 'appear',
      delay: 8,
      duration: 2,
      even_height: false,
      out_effect: false,
      on_transition: function() {},
      condition: function() {return false;}
    }).merge(options);
    this.options.set('condition', this.options.get('condition').bind(this));
    this.options.set('on_transition', this.options.get('on_transition').bind(this));
    if(this.options.get('effect') == 'appear')
      this.options.set('cleanup', function(prev) {prev.setOpacity(0.01)});

    this.elements = this.element.select(this.options.get('elements_selector'));
    if(this.options.get('even_height')) {
      var max_height = this.elements.max(function(e) {return e.getHeight()});
      this.elements.each(function(e) {e.setStyle({height: max_height + 'px'})});
      this.element.setStyle({height: max_height + 'px'});
    }
    this.index = 0;
    this.start();
  },

  start: function() {
    this.rotator = new PeriodicalExecuter(this.transition.bind(this), this.options.get('delay'));
  },

  stop: function() {
    if(this.rotator) this.rotator.stop();
  },

  move_to: function(idx) {
    this.stop();
    if(idx == this.index) return;
    var prev = this.out();
    this.index = idx;
    this.enter(prev);
  },

  transition: function() {
    if(this.options.get('condition')()) return;
    var prev = this.out();
    this.index++;
    if(this.index >= this.elements.length) this.index = 0;
    this.enter(prev);
  },

  out: function() {
    this.elements[this.index].setStyle({zIndex: 0});
    if(this.options.get('out_effect'))
      Effect[Effect.PAIRS[this.options.get('effect')][1]](
        this.elements[this.index],
        {duration: this.options.get('duration')}
      );
    return this.elements[this.index];
  },

  enter: function(prev) {
    this.elements[this.index].setStyle({zIndex: 1});
    Effect[Effect.PAIRS[this.options.get('effect')][0]](
      this.elements[this.index], {
        duration: this.options.get('duration'),
        beforeStart: this.options.get('on_transition'),
        afterFinish: (function() {
          if(this.options.get('cleanup')) this.options.get('cleanup')(prev)
        }).bind(this)
      });
  },

  observing_mouse: false,
  last_x: 0,
  last_y: 0,
  over_element: function() {
    if(!this.observing_mouse) {
      this.observing_mouse = true;
      Event.observe(document.body, 'mouseover', (function(e) {
        this.last_x = e.pointerX();
        this.last_y = e.pointerY();
      }).bindAsEventListener(this));
    }
    return Position.within(this.element, this.last_x, this.last_y);
  }
});


