window.addEvent('domready', function() {
  
  
  /*
  ** Theme switcher
  */
  
  $('theme').addEvent('click:relay(li)', function(e) {
    e.stop();
    
    var theme   = this.get('data-value');
    var id      = 'css-theme';
    var sheet   = $(id);
    var uri     = new URI(sheet.href);
    
    uri.set('directory', uri.get('directory').replace(/\/[a-zA-Z-]+\/css\/$/, '/' + theme + '/css/'));
    
    var href = uri.toString();
    
    $('theme').getElements('li').removeClass('active');
    this.addClass('active');
    
    sheet.dispose();
    new Asset.css(href, { id: id });
    
    Ashe.THEME = theme;
    
    Cookie.write(Ashe.SITE_PREFIX + 'Theme', theme, { duration: 365, path: '/' });
    
  }); // end event handler for theme switcher
  
  
  
  /*
  ** Syntax highlighting
  */
  
  // Blocks
  $$('pre > code').each(function(el) {
    var lighter = new Lighter(el, {
      altLines: 'odd',
      container: el.getParent()
    });
  });
  
  // Inline
  $$('code').filter(function(el) {
    return el.getParent().get('tag') != 'pre';
  }).light();
  
  
  
  /*
  ** Front page promo
  */
  
  (function() {
    
    var promo = $('promo');
    
    /* Cycle */
    if(promo) {
      var cycle = new Cycle({
        container: $$('#promo ul.showcase')[0]
      });
      
      cycle.fixDimensions();
      
      window.addEvent('load', function(e) {
        cycle.fixDimensions();
      });
    
    }
    
  })(); // end promo
  
  
  
  /*
  ** Table of contents auto-generation.
  */
  
  (function() {
    
    // Grab all second-level headings (except those exempted through .no-toc).
    var els = $$('h2').filter(':not(.no-toc)');
    
    if(els.length >= 3) { // Don't generate a toc when less than N headings.
      
      // Dynamically determine highlight color to be used.
      var color     = $$('#nav a')[0].getStyle('background-color');
      
      // Create some needed elements.
      var container = new Element('div', { 'id': 'toc' });
      var list      = new Element('ul');
      var heading   = new Element('h3').set('text', Ashe.text['toc-prefix'][Ashe.LANG]);
      
      // container.grab(heading); Not liking this too much right now.
      container.grab(list);
      
      // Loop through the headings to retrieve the heading text and link targets.
      // We're using a fairly site-specific way to determine the anchor href here -- if the heading has its own @id, use that; if not, get the @id of the first ancestor element that has one. This may prove problematic when multiple second-level, @id-less headings exist within a <div> with @id... but then again, in such a situation the headings will (or at least should) probably have their own @ids.
      els.each(function(el) {
        var text   = el.get('data-toc') ? el.get('data-toc') : el.get('text');
        var href   = el.get('id') ? '#' + el.get('id') : '#' + el.getParent().get('id');
        var anchor = new Element('a', { href: href, text: text });
        
        list.grab(new Element('li').grab(anchor));
      });
      
      // Inject the toc.
      container.inject($('nav'), 'after');
      
      // Create a tooltip for the toc... this is custom stuff just for this site.
      var tip = new Element('div', { 'class': 'tip' }).set('text', Ashe.text['toc-prefix'][Ashe.LANG]);
      
      tip.inject(container, 'top');
      
    } // endif
    
    // Enable SmoothScroll.
    var SmoothScroll = new Fx.SmoothScroll({
      onScrolledTo: function(anchor, dest) {
        dest.highlight(color);
      }
    });
    
  })(); // end toc auto-generation
  
  
  
  /*
  ** "Likes" widget.
  */
  
  (function() {
    
    if($$('html[data-page-id="home"]').length && $('likes')) {
      
      // Preparations
      var likes    = $('likes');
      var wrapper  = likes.getChildren('.wrapper')[0];
      var sections = wrapper.getChildren('div');
      var menu     = new Element('ul', { 'class': 'menu' });
      
      likes.addClass('active');
      
      // Build menu.
      likes.getElements('h2').each(function(el, index) {
        var text = el.get('text');
        var id   = el.getParent().getParent().get('id');
        menu.grab(new Element('li', { 'data-id': id, 'text': text }));
        el.dispose();
      });
      
      menu.inject(likes, 'top');
      
      menu.getLast().grab(new Element('span', { 'class': 'corner' }), 'bottom');
      
      // Fixed height... :/
      var height = Math.ceil(parseFloat(menu.getStyle('height'), 10));
      sections.each(function(el) {
        var h = Math.ceil(parseFloat(el.getStyle('height'), 10));
        if(h > height) height = h;
      });
      
      wrapper.setStyle('height', height + 'px');
      menu.setStyle('height', height + 5 + 'px');
      menu.getLast().setStyle('height', Math.floor(parseFloat(menu.getLast().getStyle('height'))) + 5 + 'px');
      
      // Arrange sections
      var rand = $random(0, sections.length - 1);
      sections.filter(function(el, index) {
        return index != rand;
      }).slide('out');
      menu.getChildren()[rand].addClass('active');
      
      // Menu click event
      likes.addEvent('click:relay(.menu li)', function(e) {
        var id     = this.get('data-id');
        var active = menu.getElement('.active');
        sections.filter(function(el) {
          return el.get('id') != id;
        }).slide('out');
        $(id).slide('in');
        menu.getElements('li').removeClass('active');
        this.addClass('active');
      });
      
      // Tooltips
      var tips = new Tips(likes.getElements('[title]'), {
        'className' : 'likes-tip',
        'title'     : '',
        'text'      : function(el) {
          return el.get('title');
        }
      });
      
    } // end if
    
  })(); // end "Likes" widget.
  
  
  
  /*
  ** "Previous work" widget.
  */
  
  (function() {
    
    if($$('html')[0].get('data-page-id') != 'home') return;
    
    var list   = $$('#previous-work ul')[0];
    var links  = list.getElements('a');
    var ids    = list.getChildren().get('data-id');
    var thumb  = $$('#previous-work .thumb')[0];
    var title  = thumb.getElement('span');
    var id, text, thumbs = [], large = [];
    
    
    /*// Additional images (not shown when JS is unavailable). //*/
    
    // Pre-load thumbs.
    ids.each(function(id) {
      thumbs.push(Ashe.HTTP_INC_ROOT + '/assets/portfolio/' + id + '/thumb.png');
    });
    
    thumbs = new Asset.images(thumbs);
    
    // Pre-load large images.
    ids.each(function(id) {
      large.push(Ashe.HTTP_INC_ROOT + '/assets/portfolio/' + id + '/large.png');
    });
    
    large = new Asset.images(large);
    
    
    /*// List interaction. //*/
    links.addEvent('click', function(e) {
      
      e.stop();
      
      // Set selected list item.
      list.getChildren().removeClass('selected');
      this.getParent().addClass('selected');
      
      // Set new image caption.
      id   = this.getParent().get('data-id');
      text = this.get('text');
      
      // title.set('text', text); // not really liking this anymore
      
      // Set new thumbnail.
      thumb.getElement('img').set('src', Ashe.HTTP_INC_ROOT + '/assets/portfolio/' + id + '/thumb.png');
      
      // Set new link href and id.
      thumb.set('href', Ashe.HTTP_ROOT + '/portfolio/' + id + '/');
      thumb.set('data-id', id);
      
    });
    
    
    /*// Tooltips. //*/
    var tips = new Tips(list.getElements('li'), { fixed: true, offset: { x: 225, y: 10 } });
    
    
    /*// Hover popup logic. //*/
    var large = new Element('div', { 'class': 'large' });
    large.grab(new Element('img'));
    large.inject($('previous-work')).hide();
    
    thumb.addEvent('mouseover', function(e) {
      var id = this.get('data-id');
      large.getElement('img').set('src', Ashe.HTTP_ROOT + '/assets/portfolio/' + id + '/large.png');
      large.show();
    });
    
    thumb.addEvent('mouseout', function(e) {
      large.hide();
    });
    
  })(); // end "Previous work" widget
  
  
  
  /*
  ** Code and Portfolio thumb hover actions
  */
  
  (function() {
    
    if($$('html')[0].get('data-page-id') != 'code' &&
       $$('html')[0].get('data-page-id') != 'portfolio') return;
    
    $$('#code .thumb, #portfolio .thumb').addEvents({
      mouseover : function(e) {
        this.set('src', new URI(this.get('src')).set('file', 'thumb.png').toString());
      },
      mouseout  : function(e) {
        this.set('src', new URI(this.get('src')).set('file', 'logo.png').toString());
      }
    });
    
  })();
  
  
  
  /*
  ** Code block "tooltips"
  */
  
  (function() {
    
    var els = $$('pre > code');
    
    els.each(function(el) {
      var tip   = new Element('p', { 'class': 'tip' });
      var title = el.get('title');
      
      el.erase('title');
      tip.set('text', title);
      tip.inject(el, 'top');
    });
    
  }).delay(1000); // end code block tooltips // Delay is to wait for Lighter.js to do its job :/ No hurry with this anyway.
  
  
  
  /*
  ** Contract/expand widgets
  */
  
  (function() {
    
    return; /* !!!!!! */
    
    var text = {
      expanded   : '▲',
      contracted : '▼'
    };
    
    // Step 1: Trigger handling
    document.body.addEvent('click:relay(.expand-trigger)', function(e) {
      
      var subject = this.getParent('[data-expand-state]');
      var state   = subject.get('data-expand-state');
      var wrapper = subject.getElement('.expand-wrapper');
      
      if(state == 'expanded') {
        wrapper.dissolve();
        subject.set('data-expand-state', 'contracted');
        this.set('title', Ashe.text['expandable-show'][Ashe.LANG]);
        this.set('text', text.contracted);
        state = 'contracted';
      } else if(state == 'contracted') {
        wrapper.reveal();
        subject.set('data-expand-state', 'expanded');
        this.set('title', Ashe.text['expandable-hide'][Ashe.LANG]);
        this.set('text', text.expanded);
        state = 'expanded';
      }
      
      this.blur();
      
      Cookie.write('expandable[' + subject.get('id') + ']', state, { duration: 365, path: '/' });
      
      /* ADDITIONAL BEHAVIOUR FOR SPECIFIC ELEMENTS */
      
      if(subject.get('id') == 'promo' && $$('html[data-page-id="home"]').length) {
        var heading = subject.getElement('h2');
        heading.set('tween', { duration: 200 });
        if(state == 'contracted') {
          heading.fade('out');
          wrapper.get('reveal').chain(function() {
            subject.fade(.6).addClass('contracted');
            heading.fade('in');
          });
        } else if(state == 'expanded') {
          heading.fade('out').get('tween').chain(function() {
            subject.fade(1).removeClass('contracted');
            heading.fade('in');
          });
        }
      }
      
    });
    
    // Step 2: Trigger and wrapper insertion
    var els = $$('[data-expand-state]');
    
    els.each(function(el) {
      
      var state   = el.get('data-expand-state');
      var content = state == 'expanded' ? text.expanded : text.contracted;
      var wrapper = el.getElement('.expand-wrapper');
      var trigger = new Element('button', {
        'text'  : content,
        'title' : Ashe.text['expandable-hide'][Ashe.LANG],
        'class' : 'expand-trigger'
      });
      
      if(!wrapper) {
        var wrapper = new Element('div', {
          'class' : 'expand-wrapper'
        });
        wrapper.adopt(el.getChildren());
        el.grab(wrapper);
      }
      
      el.grab(trigger, 'top');
      
      if(state == 'contracted') {
        el.set('data-expand-state', 'expanded');
        trigger.click();
      }
      
    }); // end each()
    
  })();
  
  
  
  /*
  ** <video>
  */
  
  (function() {
    
    if($$('video').length && $$('video')[0].play) {
    
      var video = {
        'video'   : $$('video')[0],
        'id'      : 'avatar',
        'options' : {
          
          'debug'    : true,
          'playlist' : [
            {
              'id'    : 'alice',
              'src'   : Ashe.HTTP_INC_ROOT + 'assets/alice.ogv'
              
            },
            {
              'id'    : 'shrek',
              'src'   : Ashe.HTTP_INC_ROOT + 'assets/shrek.ogv',
              'title' : '<cite>Shrek Forever After</cite> theatrical trailer'
            }
          ]
        }
      };
      
      Moovie([video]);
      
    }
    
  })(); // end <video>
  
  
  
  /*
  ** Misc. constructors
  */
  
  DLWidget('dl.propdef', { captionClass: 'propdef-caption' });
  
  AutoCollapsibles($$('html[data-page-id^="articles~"] h2, html[data-page-id^="code~"] h2'));
  
  SectionLinks($$('h2'));
  
  
  
  /*
  ** Mooverview
  */
  
  var qs = new URI(location.toString()).get('query').parseQueryString();
  if($chk(qs.overview) && qs.overview == 'enable') {
    mooverview = new Mooverview();
  }
  
  
});