/*
 * Riddle.pl Scripting
 * http://riddle.pl
 *
 * Copyright 2010, Piotr Petrus
 * Date: 2010-04-01
 *
 * Use it for doing good.
 */

var Engine = {
  start: function() {
    this.initHTML();
    this.testSupport();
    this.preloadImages();
    this.shiftLayout();
  },
  
  initHTML: function() {
    // tell CSS it's gonna be ok
    $('html').addClass('js');
    
    // check any additional hashes
    var r_hash = /#.+$/,
        location = document.location.href;
    if (location.match(r_hash)) {
      var command = r_hash.exec(location)[0].slice(1);
      if (command === 'baseline') {
        $('body').addClass('baseline');
      }
    }
    
    // scaffold additional elements
    $('article')
      .find('div').append('<span/>').end()
      .find('figure').wrapInner('<a href=""/>')
        .find('a').append('<span/>');
  },
  
  preloadImages: function() {
    var preload = function(collection) {
      var path = 'http://riddle.pl/styles/';
      for (var i=0; i < collection.length; i += 1) {
        var img = new Image();
        img.setAttribute('src', path + collection[i]);
      }
    };
    
    if ($('body').is('.border-image')) {
      // preload border images only if they’re used
      preload(['selection.png', 'popover-dev.png', 'popover-design.png']);
    }
    
    preload(['popover-arrow.png']);
  },
  
  testSupport: function() {
    if (window.opera) {
      // i’m a small evil man, and I know it.
      // point is, even IE understood that ampersand’s typography
      var opera_styles = 'header h2 strong { padding-top: 24px; padding-bottom: 8px; margin-top: -20px; }';      
      var stylesheet = document.createElement('link');
      stylesheet.rel='stylesheet';
      stylesheet.href='data:text/css,' + escape(opera_styles);
      $('head link:last').after(stylesheet);      
    }
    
    // based on Modernizer.js by Aruk Fates and Paul Irish (http://modernizr.com)    
    var properties = ['border-image', 'box-shadow'];
    var test_element = document.createElement('span');
    
    var test_properties = function(properties) {
      for (var i=0; i < properties.length; i += 1) {
        if (test_element.style[properties[i]] !== undefined) {
          return true;
        }
      }
    };
    
    var test_properties_all = function(property) { 
      property = property.replace(/-([a-z])/ig, function(all, letter) {
        return letter.toUpperCase();
      });
      var vendor_property = property.charAt(0).toUpperCase() + property.slice(1),
      properties = [
        property,
            'Moz' + vendor_property,
            'moz' + vendor_property,
             'ms' + vendor_property,
              'o' + vendor_property,
         'webkit' + vendor_property
      ];
      return !!test_properties(properties);
    };
    
    for (var i=0; i < properties.length; i += 1) {
      if (test_properties_all(properties[i])) {
        $('body').addClass(properties[i]);
      }
    }
  },
  
  shiftLayout: function() {
    
    var shorten = function($original) {
      var words = $original.text().split(/\s/);
      var word = words[words.length - 1];
      var class_name = $original.attr('class');
      // capitalize first word
      if (class_name === 'first') {
        word = word.charAt(0).toUpperCase() + word.slice(1);
      }
      return $('<span/>').addClass(class_name).text(word);
    };
    
    // get all items for animation
    var $body = $('body'),
        $header = $('#master-header'),
        
        $header_p = $header.children('p'),
        $header_h = $header.find('hgroup').children('*'),
        
        $header_boxes = $header_p.add($header_h).not('.shadow'),
        // header text
        $header_items_left  = $header_boxes.find('span:first'),
        $header_items_right = $header_boxes.find('span:last').add($header_boxes.find('strong')),
        // layout columns
        $column_left = $header.next(),
        $column_right = $column_left.next(),
        // profession names
        $name_box = $header_boxes.eq(2),
        $name_full_left = $header_items_left.eq(2),
        $name_full_right = $header_items_right.eq(3),
        // copy
        $recent_all = $('section.works h2'),
        $recent_left = $recent_all.eq(0),
        $recent_right = $recent_all.eq(1),
        $column_left_target = $column_left.find('.inner'),
        $column_right_target = $column_right.find('.inner'),
        $copy_left = $('section.about-me'),
        $copy_right = $('section.contact');
        
    $header_items_left.addClass('first');
    $header_items_right.addClass('last');

    // create shorter versions of profession names
    var $name_left = shorten($name_full_left),
        $name_right = shorten($name_full_right);

    // append shortened profession names to header 
    $name_left.add($name_right).addClass('invisible').appendTo($name_box);
    
    // create sets of items to animate later
    var $items_left = $header_items_left.not($name_full_left).add($column_left);
    var $items_right = $header_items_right.not($name_full_right).add($column_right);

    // get works descriptions
    var $popover_articles_left = $column_left.find('article'),
        $popover_articles_right = $column_right.find('article'),
        $popover_descs = {
          'left': $popover_articles_left.find('div'),
          'right': $popover_articles_right.find('div')
        },
        $popover_descs_all = $popover_descs.left.add($popover_descs.right),
        $popover_links = {
          'left': $popover_articles_left.find('figure a'),
          'right': $popover_articles_right.find('figure a')
        };

    // animation config
    var previous_part = 'eq',
        previous_index = -1,
        columns_speed = 750,
        popover_speed = 350,
        easing = 'easeOutSine',
        popover_easing = 'easeInOutQuad';
        
    // animation (portfolio popover)    
    var toggle_popover = function(action, side, index, wait, callback) {
      var margin_value = (action === 'show') ? '-312px' : '0px',
          opacity_value = (action === 'show') ? '1.0' : '0.0',
          scale_value = opacity_value;

      // callback after animation
      var after = function() {
        if (action === 'show') {
          $popover_descs_all.not(this).removeClass('enabled');
        }
        // if callback needs to wait for the animation to complete
        if (wait) { callback(); }
      };
          
      // FIXME: awful repetition due to a strange bug in jQuery.  
      //        which prevents using variable instead of 'margin-left/right'
      
      var properties = { 'opacity': opacity_value };
      if (!$.browser.msie) {
        jQuery.extend(properties, { 'scale': scale_value });
      }
      
      if (side === 'left') {
        jQuery.extend(properties, { 'margin-left': margin_value });
        $popover_descs.left.eq(index)
          .addClass('enabled')
          .stop().animate(properties, popover_speed, popover_easing, after);
      }

      if (side === 'right') {
        jQuery.extend(properties, { 'margin-right': margin_value });
        $popover_descs.right.eq(index)
          .addClass('enabled')
          .stop().animate(properties, popover_speed, popover_easing, after);
      }
      
      if (action === 'show') {
        // if popover was just shown, save index
        previous_index = index;
      } else {
        // if popover was just hidden, reset index
        previous_index = -1;
      }
      
      // if callback doesn't need to wait for the animation to complete
      if (!wait) { callback(); }
    };
    
    // animation (layout)
    var toggle_layout = function(part, callback) {
      
      var left, right;
      switch (part) {
        case 'eq': left = '50'; right = '50'; break;
        case 'left': left = '80'; right = '20'; break;
        case 'right': left = '20'; right = '80'; break;
      }
      
      var name_full_left_opacity = (part === 'right') ? '0.0' : '1.0',
          name_full_right_opacity = (part === 'left') ? '0.0': '1.0',
          name_left_opacity = (part === 'right') ? '1.0' : '0.0',
          name_right_opacity = (part === 'left') ? '1.0' : '0.0',
          recent_left_opacity = name_full_left_opacity,
          recent_right_opacity = name_full_right_opacity,
          $copy_left_target = (part === 'right') ? $column_right_target : $column_left_target,
          $copy_right_target = (part === 'left') ? $column_left_target : $column_right_target,
          unit = '%'; // this will result in (e.g) '20%',
          
      // prepare for animation
      $body.addClass('animation');
      
      $recent_all.animate({ 'opacity': '0.0' });
      $copy_left.fadeOut();
      $copy_right.fadeOut();
      
      // animate shit
      $items_left.stop().animate({ 'right': right + unit }, columns_speed, easing);
      $items_right.stop().animate({ 'left': left + unit }, columns_speed, easing);
    
      $name_full_left.stop().animate({ 'right': right + unit, 'opacity': name_full_left_opacity }, columns_speed, easing);
      $name_left.stop().animate({ 'right': right + unit, 'opacity': name_left_opacity }, columns_speed, easing);

      $name_full_right.stop().animate({ 'left': left + unit, 'opacity': name_full_right_opacity }, columns_speed, easing);
      $name_right.stop().animate({ 'left': left + unit, 'opacity': name_right_opacity }, columns_speed, easing, function() {
        // clean up
        // manage classes for the new layout
        $body
          .removeClass('animation')
          .removeClass('part-' + previous_part)
          .addClass('part-' + part);
        // if 50/50, hide popovers
        if (part === 'eq') {
          $popover_descs_all.removeClass('enabled');
        }
        // update min-width
        $column_left.css('min-width', left + '0px');
        $column_right.css('min-width', right + '0px');
        // move copy
        
        $copy_left.appendTo($copy_left_target);
        $copy_right.appendTo($copy_right_target);
        
        $recent_left.animate({ 'opacity': recent_left_opacity });
        $recent_right.animate({ 'opacity': recent_right_opacity });
        $copy_left.fadeIn();
        $copy_right.fadeIn();
        
        
        // save current part
        previous_part = part;
        // do whatever else we need to do:
        callback();
      });
    };
    
    // handle clicks on portfolio links
    var handle_popover_link = function(part, index) {
      // console.group('part-' + part + '-index-' + index);
      
      // FIXME: use arguments[] in target functions
      var empty_callback = function() {};
      
      if (previous_part === 'eq') {
        // no popover visible, toggle layout freely
        toggle_layout(part, function() {
          toggle_popover('show', part, index, false, empty_callback);
        });
      } else {
        // popover is visible, decide what to do:
        if (previous_part === part) {
          // we're still on the same side          
          if (previous_index === index) {
            // the same portfolio work was clicked, switch layout
            toggle_popover('hide', part, index, true, function() {
              toggle_layout('eq', empty_callback);
            });
          } else {
            // other portfolio work was clicked, hide current and show another
            toggle_popover('hide', part, previous_index, false, function() {
              toggle_popover('show', part, index, false, empty_callback);
            });
          }
        } else {
          // we're switching sides, hide popover, switch layout, show popover
          toggle_popover('hide', previous_part, previous_index, true, function() {
            toggle_layout(part, function() {
              toggle_popover('show', part, index, false, empty_callback);
            });
          });
        }
      }

      // console.groupEnd('part-' + part + '-index-' + index);
    };
    
    // shift layout when links in portfolio are clicked
    $popover_links.left.each(function(index) {
      $(this).bind('click', index, function(e) {
        handle_popover_link('left', index);
        e.preventDefault();
      });
    });
    
    $popover_links.right.each(function(index) {
      $(this).bind('click', index, function(e) {
        handle_popover_link('right', index);
        e.preventDefault();
      });
    });

    // scale descriptions. apparently this can’t be called from CSS
    if (!$.browser.msie) {
      $popover_descs_all.scale(0);
    }
    
  }
};


$(function() {
  Engine.start();
});