var Fadr = Class.create({
  initialize: function() {
    Element.extend(document.body);

    this.from = readCookie('fadr:colour');
    this.to = this.santizeColour(document.body.getStyle('backgroundColor'));

    if (this.from != null && this.to != null && this.from != this.to) {
      document.body.setStyle({ backgroundColor: this.from });
      document.observe("dom:loaded", function() {
        new Effect.Highlight(document.body, {
          delay: 0.3, duration: 2.5, endcolor: this.to, restorecolor: this.to,
          startcolor: this.from });
      }.bind(this));
    }

    createCookie('fadr:colour', this.to, 0);
  },

  santizeColour: function(colour) {
    var match = colour.match(/(\d+), (\d+), (\d+)/);
    if (match != null) {
      return '#' + (match[1] << 16 | match[2] << 8 | match[3]).toString(16);
    } else if (/^#[0-9a-f]{3}$/i.test(colour)) {
      return colour.replace(/#(.)(.)(.)/, '#$1$1$2$2$3$3');
    }
    return colour;
  }
});


var Imagr = Class.create({
  initialize: function(elem) {
    this.elem = elem;
    this.previous = 0;
    this.current = 0;
    this.images = elem.select('img');

    // Don't continue if there are no images.
    if (this.images.length == 0) return;

    // Make sure elem has a height as images are floated.
    this.elem.insert('<div class="clear"></div>')

    this.container = elem.wrap('div', { 'class': 'imagr-container' });

    // Copy other classNames to the container.
    var className = elem.className.sub(/\bimagr\b/, '').strip();
    if (!className.blank()) this.container.addClassName(className);

    // Add dot container.
    this.container.insert('<div class="dots"></div>');
    var dot_container = this.container.down('.dots');

    // Add image cycling functionality.
    this.images.each(function(img, i) {
      img.observe('click', this.cycle.bind(this, i));
      dot_container.insert('<span class="dot"></span>');
    }.bind(this));

    // Make dots clickable.
    this.dots = dot_container.select('.dot');
    this.dots.each(function(dot, i) {
      dot.observe('click', this.select.bind(this, i));
    }.bind(this));
    this.dots.first().addClassName('selected');
  },

  cycle: function(index) {
    this.previous = this.current;
    this.current = (index == this.images.length - 1 ? 0 : index + 1);
    this.show(this.current);
  },

  select: function(index) {
    this.previous = this.current;
    this.current = index;
    this.show(index);
  },

  show: function(index) {
    this.dots[this.previous].removeClassName('selected');
    this.dots[index].addClassName('selected');
    var elem = this.images[index];
    var x = elem.positionedOffset()[0];
    var myEffect = new Effect.Move(this.elem, {
      duration: 0.3, mode: 'absolute', x: -x
    });
  }
});


var Scalr = Class.create({
  initialize: function(elem) {
    // Add an extra hook for styling tweaks.
    elem.addClassName('scalr-active');
    var width = elem.getWidth();
    var spans = elem.select('span').map(function(span) {
      var obj = new ScalrSpan(span);
      obj.fitTo(width);
      return obj;
    });
    // Add an extra hook for styling tweaks.
    elem.addClassName('scalr-complete');
  }
});

var ScalrSpan = Class.create({
  initialize: function(elem) {
    this.span = elem;
    this.fontSize = parseInt(elem.getStyle('fontSize')); // px.
    this.lineHeight = parseInt(elem.getStyle('lineHeight')) / this.fontSize; // em.
    this.initialWidth = elem.getWidth();
    this.scale = 1;
  },

  fitTo: function(width) {
    // Approximate.
    this.setScale(width / this.initialWidth);

    var newWidth = this.span.getWidth();

    // Check / tweak.
    if (newWidth > width) {
      this.setScale(this.scale * (width / newWidth));
    }
  },

  setScale: function(scale) {
    this.scale = scale;
    var size = this.fontSize * scale;
    this.span.setStyle({
      fontSize: size + 'px',
      lineHeight: (size * this.lineHeight) + 'px'
    });
  }
});
