/*******************************************************************
  Developed for Michael Barbano, http://www.michaelbarbano.com
--------------------------------------------------------------------

  Author:     Michael Barbano, mykl[d0t]barbano[@t]gmail[d0t].com
  Date:       Oct 15, 2009
  Copyright:  Michael Barbano, 2009

*******************************************************************/
//is this a gallery page?
  // toggle between slide show && text.
$(document).ready(function(){
  gLog = new GrouchyLogger();
  if($(".gallery_container").length > 0) gallery = new Gallery("gallery_container", 
    {
      path_to_images  : "../images/work/" + $("body").attr("id") + "/", 
      toggle_nav      : "fade",
      gallery_navigation_container : "#gallery_nav"
    });
  if($("#language_clock").length > 0) gallery = new WordClock("#language_clock");
  $(".e-mail").attr({"href" : "mailto:mykl.barbano@gmail.com"});
});

/* ------------ [ Utility funcitons ] -----------------------------*/


/*******************************************************************
  function getParam(param_hash);
  
  Checks for a key and return it's value or false if it's 
  not present
*******************************************************************/
function readParam(param_hash, key_value){
  return (typeof param_hash[key_value]) ? param_hash[key_value] : false;
}

/* ------------ [ e/o utility functions ] ------------------------*/


/*******************************************************************
  Object gallery(container class, any additional params);
  
  Description:  builds a gallery from a definition descrioption
                where each <LI> is a slide and each contained <SPAN>
                is name of a slide image file
                
  Arguments:    (container_class) string used as part of the JQuery
                Selector argument
                
                (params) a has of optional settings
*******************************************************************/
var Gallery = function (container_class, params){
  this.initialize = function(arguments){
    gLog.info("Gallery.initilize()");
    try{
      this.params = params || {};
      this.images_path = this.params.path_to_images || "../images/full_images/" + $("body").attr("id") + "/";
      this.slides = $(this.initializeSlides(container_class));
      this.current_slide = this.detectSlideFromURL() || 0; 
      this.loadFirstSlides(this.slides[this.current_slide]);
      this.initializeNavigation();
      if(this.params.image_caption) this.caption_ = this.initializeImageCaption();      
    } catch(e) {
      gLog.info(e);
    }
  };
  
  //initialize slide objects for each li 
  this.initializeSlides = function(container_class){
    gLog.info('intializeSlides()');
    var slide_containers = $("ul." + container_class +"> li");
    var that = this;
    var slides = [];
    slide_containers.each(function(){
      slides.push( new that.Slide(this, that.images_path));
      $(this).click(function(){that.next();});
    });
    return slides;
  };
  
  // Load the first slide + next slide based on the current slide value
  this.loadFirstSlides = function (current_slide){
    current_slide.loader();
    if(!this.slides[this.nextSlide()].is_loaded){this.slides[this.nextSlide()].loader()};
    current_slide.toggler();
    // this.loadSlide(this.slides[this.current_slide + 1])
  };
  
  //
  this.next = function(){
    this.slide().toggler();
    this.incrementSlide();
    if(this.slide().is_loaded){
      this.slide().toggler();
      if(!this.slides[this.nextSlide()].is_loaded){this.slides[this.nextSlide()].loader()};
    }else{
      this.slide().loader();
      this.slide().toggler();
      if(!this.slides[this.nextSlide()].is_loaded){this.slides[this.nextSlide()].loader()};
      gLog.info(next_image.src);
      this.slide()      
    }
  };
  
  this.previous = function(){
    this.slide().toggler();
    this.decrementSlide();
    if(this.slide().is_loaded){
      gLog.info("just show");
      this.slide().toggler();
    }else{
      this.slide().loader();
      this.slide().toggler();
    }
  }
  
  this.decrementSlide = function(){
    this.current_slide = (this.current_slide == 0) ? 
      this.slides.length -1 : this.current_slide - 1;
    window.location.hash = this.current_slide;
    gLog.info("decremented to: " + this.current_slide);
  };
  
  this.incrementSlide = function(){
    this.current_slide = (this.current_slide >= this.slides.length - 1) ? 
      0 : this.current_slide + 1;
    window.location.hash = this.current_slide;
    gLog.info("incremented to: " + this.current_slide);
  };
  this.nextSlide = function(){
    var next_slide = (this.current_slide >= this.slides.length - 1) ? 
      0 : this.current_slide + 1;
    return next_slide;
  }
  // look for a location.has param and start there
  this.detectSlideFromURL = function(){
    gLog.info("Gallery.detectSlideFromURL()");
    var num = (document.location.hash) ? 
      parseInt(document.location.hash.slice(1,document.location.hash.length)) : false;
    gLog.info("got: " + num);
    return num;  
  }; 
  
  this.slide = function(){
    return this.slides[this.current_slide];
  };
  
  this.initializeNavigation = function(){
    gLog.info("initiazlizeNavigation()");
    var next = $('.next'); 
    var previous = $('.previous');
    var nav = $('#gallery_nav');
    
    var that = this;
    next.focus()
    next.click(function(){ that.next(); gLog.info('next' + that.current_slide); });
    previous.click(function(){ that.previous(); gLog.info('previous'+ that.current_slide); });
    // if(this.params.toggle_nav){
    //               // this.nav_container.visible = false;
    //               var that = this;
    //               this.slides.each(function(i,slide){
    //                 slide.container.hover(
    //                   function(){
    //                     nav.show();
    //                   },
    //                   function(){
    //                     nav.hide();
    //                   }
    //                 );
    //               });
    //             }
  };
  //gets caption 
  this.initializeImageCaption = function(){
    var caption = $('#caption');
    var that = this;
    caption.click(function(){that.toggleImageCaption(caption)});
    return caption;
  }
  this.toggleImageCaption = function(target){
    var index = ( target.css("z-index") == 1000) ? 0 : 1000;
    target.css("z-index", index);
    if(index == 1000){
      target.css("cursor", "url('../images/cursor_link_close.gif'), url('../images/cursor_link_close.gif'), pointer");
    } else {
      target.css("cursor", "url('../images/cursor_link.gif'), url('../images/cursor_link.gif'), pointer");
    }
  //find captions if there is only 1 do not update to match slide index, 
  //if there are more, add the update event to the 
  //if there is a slide indicator 
  
  
  };
  /*******************************************************************
    function toggleNav()
    
	Shows and hides the previous next buttons when you hover outside
	the image in the gallery, but not when you are over the buttons
	themselves
  *******************************************************************/

  
  this.toggleNav = function(){
	//initialize som values
    var previous = this.nav_container.children().first();
    var next =  this.nav_container.children().last();
    this.nav_container.hovering = false;
    // previous.mouseenter(isHover());
    // previous.mouseleave(isNotHover());
    // next.mouseenter(isHover());
    // next.mouseleave(isNotHover());
    
	  var that = this;
    var f = function(){
      gLog.info('nav hovering now?' + that.nav_container.hovering.toString());
      if(that.nav_container.visible){
        that.nav_container.fadeOut(250, changeVisibility());
      }else{
        that.nav_container.fadeTo(250, 0.8, changeVisibility());
      }
    };
    function changeVisibility(){
      that.nav_container.visible = (that.nav_container.visible) ? false : true; 
      gLog.info("change container vis");
    }
    function isHover(){
      return function(){     
        that.nav_container.hovering = true;
        gLog.info("is hover" + that.nav_container.hovering);
      }    
    }
    function isNotHover(){
      return function(){     
        that.nav_container.hovering = false;
        gLog.info("is not hover" + that.nav_container.hovering);
      }    
    }
    return f;
  };
  
  
  /*******************************************************************
    function Slide(slide, path);
    
    Object to handle the state and contents of each slide, takes a DOM
    object to replace with img tags.
  *******************************************************************/
  this.Slide = function(slide, path){
    this.init = function(arguments){
      try{
        gLog.info("Slide.init()");
        this.is_current = false;
        this.is_loaded = false;
        this.container = $(slide);
        this._images = $(this.container).children("span");
        this.path_to = path;
      }catch(e){
        gLog.error(e);
      }
    };
    this.loader = function(){
      try{
        gLog.info("Slide.loader()");
        var images = $(this.container).children($('span'))
        this.container.children('span').remove();

        if(images.length == 1){
          this.container.append($('<img>')
              .attr({ src : [this.path_to, images.text(), ".jpg"].join(""), 
                "class" : images.attr('class')})
          );
        }else{
          gLog.info("many");
          that = this;
          images.each(function(i){
            that.container.append($('<img>')
                .attr({ src : [that.path_to, $(this).text(), ".jpg"].join(""), 
                  "class" : $(this).attr('class') })
            );
            gLog.info([that.path_to, $(this).text(), ".jpg"].join(""));
          });
        }
        this.container.toggle();
        this.is_loaded = true;
        
      }catch(e){
        gLog.error(e);
      }
    };
    this.toggler = function(){ 
      this.container.toggle() 
    };
    this.init();
  };
  
  this.initialize();  
}

//add previous and next markup to the page if there there is more than one slide
//add a behavior to the gallery to show and hide these elements on hover



/*******************************************************************
  Word Clock  (container class, params);
  
  REQUIRES JAML ++++++++++++++++++++++++++++++++++++++++++++++++++++
  http://github.com/edspencer/jaml
  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  
  Description:  adds the markup to the page to create a plain word 
                clock. updates the clock every second. Takes a URL 
                for custom styles or applies default styles
                
  Arguments:    (container_class) string used as part of the JQuery 
                Selector argument
          
                (params)
                styles: {} { classname : {css styles} }
*******************************************************************/
var WordClock = function (container_class, params){
    var init = function(parameters){
      this.params = params;
      // this.styles = (typeof this.params != 'undefined' && typeof this.params.styles != 'undefined') ? 
      //           this.mergeR(defaultStyles(), this.params.styles) :
      //           defaultStyles();
      gLog.info("container class: " + container_class);
      // = $(container_class);
      this.clock = buildClock(container_class);
      this.startTime = initilizeTime();
      this.timer = startClock();
    };
  
  /*******************************************************************
    buildClock();
    
    params:   container => string
    
    Adds elements to the DOM for the clock, returns a var for access to
    the clock elements
  *******************************************************************/  
  function buildClock(container){    
    try{
      //add main clock sections to the markup
      var clock = $(container)
      clock.append(
        $("<div>").attr({id : "clock_elements_container"})
        );
      clock.container = $("#clock_elements_container");
      clock.container.append(
        $("<div>").attr({id : "minutes"}),
        $("<div>").addClass("hours").attr({id : "hours"}),
        $("<div>").addClass("clock-face")
      );
      clock.minutes  = $("#minutes");
      clock.hours    = $("#hours");
      
      //add minutes ------------------------------------------------------------
      var count = 1;
      clock.mins = [];
      
      while(count <= 19){
        if(count != 15){ // don't add a 15 minute div
          clock.minutes.append(
            $("<div>").addClass("minute").attr({id : "m" + count}));
        }
        count++;
      };
      var count = 2;
      while(count <= 5){
        clock.minutes.append(
          $("<div>").addClass("minute").attr({id : "m-tens" + count}));
        count++;
      };
      //add hours --------------------------------------------------------------
      count = 1;
      while(count <= 12){
        clock.hours.append(
          $("<div>").addClass("hour").attr({id : "hour" + count})
        );
        count++;
      }
      clock.hours.append(
        $("<div>").addClass("hour").attr({id : "half"}),
        $("<div>").addClass("hour").attr({id : "quarter"}),
        $("<div>").addClass("hour").attr({id : "to"}),
        $("<div>").addClass("hour").attr({id : "past"}),
        $("<div>").addClass("hour always-on").attr({id : "it-is"}),
        $("<div>").addClass("hour").attr({id : "am"}),
        $("<div>").addClass("hour").attr({id : "pm"})
      );
      return clock;
    }catch(e){
      gLog.error("buildClock: " + e);
    }
  };
  
  /*******************************************************************
    startClock();
    
    Starts and interval to check the time now every 10th of a second
    then calls a function to update the styles accordingly

  *******************************************************************/
  function startClock(){
    try{
      gLog.info('start clock');
      var t_then = timeNow();
      var timer = setInterval(function(){
      var t_now = timeNow();
      updateHours(t_now);
      updateMinutes(t_now);
          if(t_now.hours > t_then.hours || (t_now.hours == 12 & t_then.hours != 12)){
            updateHours(t_now);  
          };
          if(t_now.minutes > t_then.minutes || (t_now.minutes == 0 && t_then.minutes != 0)){
            updateMinutes(t_then.minutes);
          }
          if(t_now.seconds > t_then.seconds || (t_now.seconds == 0 && t_then.seconds != 0)){
          }
          t_then = timeNow();
      }, 200);
      return timer;
    }catch(e){
      gLog.error("startClock: " + e);
    }
  };
  
  function initilizeTime(){};
  
  this.stopClock = function(){
    clearInterval(this.timer);
  }
  
  /*******************************************************************
    timeNow();
    
    gets the current time and returns a object with:
    hours (int)
    minutes (int)
    seconds (int)

  *******************************************************************/
  function timeNow(){
    try{
      var the_time = new Date();
      t = {
        hours     : meridiemHour(the_time.getHours()),
        minutes   : the_time.getMinutes(),
        seconds   : the_time.getSeconds(),
        meridiem  : meridiem(the_time.getHours())
      };
      time = t;
      return t;
    }catch(e){
      gLog.error("timeNow(): " + e);
    }
  };
  
  /*******************************************************************
    updateMinutes(); / updateHours();
    
    updates the classes of the mintues or hours elements
  *******************************************************************/
  
  function updateMinutes(time){
    clearCurrentHighlights("minutes", "current");
    //if less than 20 min just highlinght the current minute
    if(time.minutes < 20){
      if(time.minutes == 15){updateHours(time)}
      this.clock.minutes.children("#m" + time.minutes).addClass("current");
    }else{ //else highlight a factor of 10 
      if(time.minutes == 30 || time.minutes == 45 ){
        updateHours(time)
      }else{  
        this.clock.minutes.children("#m-tens" + Math.floor(time.minutes/10)).
          addClass("current");
        //if it's not exacty a factor of ten highlight a number
        if( (time.minutes / 10) != Math.floor(time.minutes / 10)){ 
          this.clock.minutes.children("#m" + (time.minutes - (Math.floor(time.minutes/10)*10))).
          addClass("current");
        }
      }
    }
    var past_to = (time.minutes == 45) ? "#to" : "#past";
    past_to = (time.minutes == 0) ? "#exactly" : past_to;
    this.clock.hours.children(past_to).addClass("current");
  }
  
  function updateHours(time){
    clearCurrentHighlights("hours", "current");
    this.clock.hours.find("#hour" + time.hours + ", #" + time.meridiem).addClass("current");
    switch(time.minutes){
      case 15 : this.clock.hours.find("#quarter").addClass("current");
      break;
      case 30 : this.clock.hours.find("#half").addClass("current");
      break;
      case 45 : this.clock.hours.find("#quarter").addClass("current");
      break;
    }
    //convience method sets "past" or "to" to active depending on minutes
  }
  
  function clearCurrentHighlights(unit_of_time, highlight_class){  
    this.clock[unit_of_time].find("." + highlight_class).removeClass(highlight_class);
  }
  /*******************************************************************
    meridiem();
    
    returns "am or pm"
  *******************************************************************/
  function meridiem(hours){
    return (hours > 12) ? "pm" : "am";
  }
  
  
  /*******************************************************************
    meridiem();
    
    converts 24 hour time to 12 hour time
  *******************************************************************/
  
  function meridiemHour(hours){
    return (hours > 12) ? hours - 12 : hours;
  }

  init(); // initialize WordClock
};


/*******************************************************************
  Grouchy logger(container class, any additional params);
  
  Description:  Basically replaces the native console.log in webkit
                and makes logging to console available in firebug 
                also suppresses logs in IE.
                
  Arguments:    (message) var, or string to be printed to console
                (type) error, info, debug
                
  Notekey:      Eventually I'll add a functionality to render
                messages to HTML elements in IE
*******************************************************************/

// jquery logger to console or black bird on call
var GrouchyLogger = function(message, type){
  this.initialize = function(arguments){
    this.logs = [];    
    this.logIt("Welcome to OI Logger!", "info");
  };
  
  this.logIt = function(message, type, dump){
    if(typeof log != "undefined"){
      log[type](message);
      this.addToLogsDump({ "type" : type , "message" : message }, dump);
    }else if(typeof console != "undefined"){
      console.log('-------------------------------------');
      console[type](message);
      this.addToLogsDump({ "type" : type , "message" : message }, dump);
      return;
    }
  };
  
  /**
  Adds a message to the logs array unless dump = false
  **/
  this.addToLogsDump = function(message, dump){
    if(dump != false) this.logs.push(message);
  };
  this.dumpLogs = function(){
    for(var i = 0, log; log = this.logs[i]; i++){
      this.logIt(log.message, log.type, false);
    }
    return 'xxxxxxxxxx [ end of log ] xxxxxxxxxxx';
  };
  this.addBlackBird = function(){//not functional
    var head = document.getElementsByTagName('head')[0];
    var bb_js = document.createElement('script');
    var bb_css = document.createElement('link');
    
    bb_css.setAttribute('type', 'text/css');
    bb_css.setAttribute('rel', 'stylesheet');
    bb_css.setAttribute('src', 'logging/blackbird.css');
    
    bb_js.setAttribute('type', 'text/javascript');
    bb_js.setAttribute('src', 'logging/blackbird_OI.js');
    
    head.appendChild(bb_js);
    head.appendChild(bb_css);
    
    //need to tring
  };
  
  this.info     = function(message){ this.logIt(message, "info")   };
  this.warn     = function(message){ this.logIt(message, "warn")   };
  this.error    = function(message){ this.logIt(message, "error")  };
  this.debug    = function(message){ this.logIt(message, "debug")  };
  
  this.initialize();

};


