(function($) {
     var o          = null;
     var $data      = null;
     var $this      = null;
     var $framePosX = 0;
     var $currFrame = -1;
     
     $.fn.snogMenu = function(options) {
          
          var opts = $.extend({}, $.fn.snogMenu.defaults, options);

          return this.each(function() {
               $this = $(this);
               // build element specific options
               o = $.meta ? $.extend({}, opts, $this.data()) : opts;
               var $xml = $.get(o.xml_path+$this.attr('rel')+'.xml?random=' + (new Date()).getTime(), function(data) {
                    $data = data;
                    buildInterface(o);
               })
          });
     };

     function debug($obj) {
          if (window.console && window.console.log){
               window.console.log($obj);
          }
     };

     /**
      *   @name     buildInterface
      *   @desc     calls various methods to build the interface for the menu
      *   @param    object    data      Object retruend from the XML call
      *   @param    object    o         The plugins options
      */
     function buildInterface(o){
          var opts = o;
          buildFrames(opts);
          $($data).find('snog_nav_buttons btn').each(function(i){
               addMenuButton(this,opts,i);
          });
          showFirstPerson(opts);
     }
          
     /**
      *   @name     buildInterface
      *   @desc     builds the menu buttons and appends them to the menu board
      *   @param    object    btnNode   The XML node for the button
      *   @param    object    o         The plugins options   
      */
     function addMenuButton(btnNode,o,i){ 
          
          var active_class = i == 0 ? ' active' : '';
          var button = $('<li class="button'+active_class+'"><a href="'+$(btnNode).attr('id')+'">'+$(btnNode).text()+'</a></li>');
          button.css({
               left: $(btnNode).attr('left')+'px',
               top: $(btnNode).attr('top')+'px'
          });
          $($this).find(o.menu_pane).append(button);
          button.find('a').click(function(e){
               e.preventDefault();
               doMenuButtonClick(this);               
          })
          return $this;
     }  
     /**
      *   @name     doMenuButtonClick
      *   @desc     controls the button click action
      *   @param    object    clicked_link   The link that was clicked
      *   @param    object    o              The plugins options   
      */
     function doMenuButtonClick(clicked_link,o){        
          if($(clicked_link).parent('li').hasClass('active')){
               return false;
          }else{
               slideToFrame(clicked_link, o);
          }
          return $this;
     } 
     /**
      *   @name     buildFirstFrame
      *   @desc     builds the first frame of the menu
      *   @param    object    o    The plugins options   
      */
     function buildFrames(o){ 
          var opts = o;
          var frame = '';
          var section = '';
          
          $($data).find('section').each(function(){
               
               section = this;
               frame = $('<li class="frame"></li>');
               
               if($(opts.frame_pane).append(frame)){    
                    switch($(section).attr('type')){
                         case 'html':
                              loadHtmlContent(frame, $(this),opts);
                         break;
                         case 'hybrid':
                              loadHybridContent(frame, $(this),opts);
                         break;                         
                         default:
                              preLoadImage(frame, $(this).attr('bk_image'),opts);                         
                         break;
                    }
               }
          });
          return $this;
     }   
     /**
      *   @name     buildFirstFrame
      *   @desc     builds the first frame of the menu
      *   @param    int       id    The target id   
      *   @param    object    o    The plugins options   
      */
     function slideToFrame(clicked_link){
          $(this).stop();
          
          $(o.menu_pane+' li').removeClass('active');
          $(clicked_link).parent('li').addClass('active');
          var the_id     = parseInt($(clicked_link).attr('href'));
          var index      = parseInt(the_id)-1;
          
          var dir        = index < $currFrame ? -1 : -1;
          var left       = index * o.frame_width * dir;
          
          hidePerson(index,o);
          
          $(o.frame_pane).stop().animate({
               left : left
          },o.speed,o.easing, function(){
               
               $currFrame = the_id-1;
               $framePosX = $currFrame * o.frame_width;
          })          
          
          return $this;
     }        
     /**
      *   @name     showPerson
      *   @desc     Builds the slides with the people
      *   @param    object    o              The plugins options   
      */
     function showFirstPerson(o){        
          $('.person').css({
               'opacity':0
          });
          $('.person').eq(0).animate({
               right : 0,
               opacity: 1
          },o.characterAnimationSpeed,'swing', function(){
               //alert('slide complete')
          }).addClass('shown');
          return $this;
     }
     /**
      *   @name     showPerson
      *   @desc     Builds the slides with the people
      *   @param    object    o              The plugins options   
      */
     function showPerson(index,o){        
          
          $('.person').eq(index).animate({
               right : 0,
               opacity: 1
          },o.characterAnimationSpeed,'swing', function(){
               //alert('slide complete')
          }).addClass('shown');
          return $this;
     }     
     /**
      *   @name     showPerson
      *   @desc     Builds the slides with the people
      *   @param    object    o              The plugins options   
      */
     function hidePerson(index,o){        
          
          $('.person.shown').animate({               
               opacity: 0
          },o.characterAnimationSpeed,'swing', function(){               
              showPerson(index,o);
              $(this).css({
               right : '-380px'
          })
          }).removeClass('shown');
          return $this;
     }     



     /**
      *   @name     preLoadImage
      *   @desc     "preloads" an image by showing a spinner
      *   @param    string    img_src   URL of image to load
      *   @param    object    o              The plugins options   
      */
     function preLoadImage(target_elem, img_src,o){
          $(target_elem).css({
               'background-image' : 'url('+o.spinner_image_path+')'
          })

          var frame_image = img_src;

          $('<img />')
          .attr('src', frame_image+ '?random=' + (new Date()).getTime())
          .load(function(){

               $(target_elem).fadeOut(250, function(){

                    $(target_elem).css({
                         'background-image' : 'url('+frame_image+')'
                    })
               }).fadeIn(250)
          }); 
          return $this;
     }
     /**
      *   @name     loadHybridContent
      *   @desc     loads in the html and image for the frame by parsing all the xml nodes
      *             Currently only a header node from the XML + 1 image is supported
      *   @param    object    elem   The target dom object in which to load the content
      *   @param    object    data   The data to parse
      *   @param    object    o      The plugins options   
      */     
     function loadHybridContent(target_elem, data,o){
          
          var heading    = '<h3>'+$(data).find('heading').text()+'</h3>';

          var img_src    = $(data).attr('bk_image');
          
          var frame_html = $(heading).text();
          $(target_elem).html(heading).addClass('hybrid');
          preLoadImage(target_elem, img_src,o);
          
          return $this;

     }   

     /**
      *   @name     loadHtmlContent
      *   @desc     loads in the html for the frame by parsing all the xml nodes
      *   @param    object    elem   The target dom object in which to load the content
      *   @param    object    data   The data to parse
      *   @param    object    o      The plugins options   
      */     
     function loadHtmlContent(target_elem, data,o){
          $(target_elem).addClass('html');
          var index = data.attr('id')-1;
          // We need to convert the full XML data object to a json object
          var all_data =  $.xml2json($data, true);
          // and then re-rselect the item
          var section = all_data.sections[0].section[index];
          //var section = $($data).find('section[id='+data.attr('id')+']');

          if($('#'+section.template_id).length){
               if($('#'+section.template_id).tmpl(section).appendTo($(target_elem))){
                    console.log(section)
                    $('.tabs .button a').simpleTabs();    
               }

          }
          
          return $this;   
     }
     
     $.fn.snogMenu.defaults = {
          speed:                   800,
          characterAnimationSpeed: 200,
          background:              '#ff9900',
          xml_path:                '/xml/menus/regions/',
          spinner_image_path:      '/img/common/loader.gif',
          menu_pane:               '#menuboard-nav ul',
          frame_pane:              '#menuboard-window ul#frames',
          frame_width:              350,
          easing:                  'easeOutElastic'
          
     };

//
// end of closure
//
})(jQuery);
