/* ShowOff JS Logic */

var ShowOff = {};

var preso_started = false
var slidenum = 0
var slideTotal = 0
var slides
var currentSlide
var totalslides = 0
var slidesLoaded = false
var incrSteps = 0
var incrElem
var incrCurr = 0
var incrCode = false
var debugMode = false
var gotoSlidenum = 0
var shiftKeyActive = false

var loadSlidesBool
var loadSlidesPrefix

function setupPreso(load_slides, prefix) {
  if (preso_started)
  {
     alert("already started")
     return
  }
  preso_started = true

  loadSlidesBool = load_slides
  loadSlidesPrefix = prefix
  loadSlides(loadSlidesBool, loadSlidesPrefix)

  doDebugStuff()

  // bind event handlers
  document.onkeydown = keyDown
  document.onkeyup = keyUp
  /* window.onresize  = resized; */
  /* window.onscroll = scrolled; */
  /* window.onunload = unloaded; */
}

function loadSlides(load_slides, prefix) {
  //load slides offscreen, wait for images and then initialize
  if (load_slides) {
  	$("#slides").load("/slides", false, function(){
    	$("#slides img").batchImageLoad({
			loadingCompleteCallback: initializePresentation(prefix)
		})
  	})
  } else {
	$("#slides img").batchImageLoad({
		loadingCompleteCallback: initializePresentation(prefix)
	})
  }
}

function initializePresentation(prefix) {
  //center slides offscreen
  centerSlides($('#slides > .slide'))

  //copy into presentation area
  $("#preso").empty()
  $('#slides > .slide').appendTo($("#preso"))

  //populate vars
  slides = $('#preso > .slide')
  slideTotal = slides.size()

  //setup manual jquery cycle
  $('#preso').cycle({
    timeout: 0
  })

  setupMenu()
  if (slidesLoaded) {
    showSlide()
    alert('slides loaded')
  } else {
    showFirstSlide();
    slidesLoaded = true
  }
  setupSlideParamsCheck();
  sh_highlightDocument(prefix+'/js/sh_lang/', '.min.js')
}

function centerSlides(slides) {
  slides.each(function(s, slide) {
    centerSlide(slide)
  })
}

function centerSlide(slide) {
  var slide_content = $(slide).children(".content").first()
  var height = slide_content.height()
  var mar_top = (0.5 * parseFloat($(slide).height())) - (0.5 * parseFloat(height))
  if (mar_top < 0) {
    mar_top = 0
  }
  slide_content.css('margin-top', mar_top)
}

function setupMenu() {
  $('#navmenu').hide();

  var currSlide = 0
  var menu = new ListMenu()

  slides.each(function(s, elem) {
    content = $(elem).children(".content")
    shortTxt = $(content).text().substr(0, 20)
    path = $(content).attr('ref').split('/')
    currSlide += 1
    menu.addItem(path, shortTxt, currSlide)
  })

  $('#navigation').html(menu.getList())
  $('#navmenu').menu({
    content: $('#navigation').html(),
    flyOut: true
  });
}

function checkSlideParameter() {
  if (slideParam = currentSlideFromParams()) {
    slidenum = slideParam;
  }
}

function currentSlideFromParams() {
  var result;
  if (result = window.location.hash.match(/#([0-9]+)/)) {
    return result[result.length - 1] - 1;
  }
}

function setupSlideParamsCheck() {
  var check = function() {
    var currentSlide = currentSlideFromParams();
    if (slidenum != currentSlide) {
      slidenum = currentSlide;
      showSlide();
    }
    setTimeout(check, 100);
  }
  setTimeout(check, 100);
}

function gotoSlide(slideNum) {
  slidenum = parseInt(slideNum)
  if (!isNaN(slidenum)) {
    showSlide()
  }
}

function showFirstSlide() {
  slidenum = 0
  checkSlideParameter();
  showSlide()
}

function showSlide(back_step) {

  if(slidenum < 0) {
    slidenum = 0
    return
  }

  if(slidenum > (slideTotal - 1)) {
    slidenum = slideTotal - 1
    return
  }

  currentSlide = slides.eq(slidenum)

  var transition = currentSlide.attr('data-transition')
  var fullPage = currentSlide.find(".content").is('.full-page');

  if (back_step || fullPage) {
    transition = 'none'
  }

  $('#preso').cycle(slidenum, transition)

  if (fullPage) {
    $('#preso').css({'width' : '100%', 'overflow' : 'visible'});
    currentSlide.css({'width' : '100%', 'text-align' : 'center', 'overflow' : 'visible'});
  } else {
    $('#preso').css({'width' : '1020px', 'overflow' : 'hidden'});
  }

  percent = getSlidePercent()
  $("#slideInfo").text((slidenum + 1) + '/' + slideTotal + '  - ' + percent + '%')

  if(!back_step) {
    // determine if there are incremental bullets to show
    // unless we are moving backward
    determineIncremental()
  } else {
    incrCurr = 0
    incrSteps = 0
  }
  location.hash = slidenum + 1;
  $('body').addSwipeEvents().
    bind('swipeleft',  swipeLeft).
    bind('swiperight', swipeRight)
  removeResults()

  return getCurrentNotes()
}

function getSlideProgress()
{
  return (slidenum + 1) + '/' + slideTotal
}

function getCurrentNotes()
{
  return currentSlide.find("p.notes").text()
}

function getSlidePercent()
{
  return Math.ceil(((slidenum + 1) / slideTotal) * 100)
}

function determineIncremental()
{
  incrCurr = 0
  incrCode = false
  incrElem = currentSlide.find(".incremental > ul > li")
  incrSteps = incrElem.size()
  if(incrSteps == 0) {
    // also look for commandline
    incrElem = currentSlide.find(".incremental > pre > code > code")
    incrSteps = incrElem.size()
    incrCode = true
  }
  incrElem.each(function(s, elem) {
    $(elem).hide()
  })
}

function prevStep()
{
  slidenum--
  return showSlide(true) // We show the slide fully loaded
}

function nextStep()
{
  if (incrCurr >= incrSteps) {
    slidenum++
    return showSlide()
  } else {
    elem = incrElem.eq(incrCurr)
    if (incrCode && elem.hasClass('command')) {
      incrElem.eq(incrCurr).show().jTypeWriter({duration:1.0})
    } else {
      incrElem.eq(incrCurr).show()
    }
    incrCurr++
  }
}

function prevStep() {
  slidenum--
  return showSlide(true) // We show the slide fully loaded
}

function doDebugStuff()
{
  if (debugMode) {
    $('#debugInfo').show()
    debug('debug mode on')
  } else {
    $('#debugInfo').hide()
  }
}

function debug(data)
{
  $('#debugInfo').text(data)
}
//  See e.g. http://www.quirksmode.org/js/events/keys.html for keycodes
function keyDown(event)
{
    var key = event.keyCode;

    if (event.ctrlKey || event.altKey || event.metaKey)
       return true;

    debug('keyDown: ' + key)

    if (key >= 48 && key <= 57) // 0 - 9
    {
      gotoSlidenum = gotoSlidenum * 10 + (key - 48);
      return true;
    }

    if (key == 13){
        if (gotoSlidenum > 0) {
            debug('go to ' + gotoSlidenum);
            slidenum = gotoSlidenum - 1;
            showSlide(true);
            gotoSlidenum = 0;
        } else {
            debug('executeCode');
            executeCode.call($('.sh_javaScript code:visible'));
        }

    }


    if (key == 16) // shift key
    {
      shiftKeyActive = true;
    }
    if (key == 32) // space bar
    {
      if (shiftKeyActive) { prevStep() }
      else                { nextStep() }
    }
    else if (key == 68) // 'd' for debug
    {
      debugMode = !debugMode
      doDebugStuff()
    }
    else if (key == 37 || key == 33) // Left arrow or page up
    {
      prevStep()
    }
    else if (key == 39 || key == 34) // Right arrow or page down
    {
      nextStep()
    }
    else if (key == 82) // R for reload
    {
      if (confirm('really reload slides?')) {
        loadSlides(loadSlidesBool, loadSlidesPrefix)
        showSlide()
      }
    }
    else if (key == 84 || key == 67)  // T or C for table of contents
    {
      $('#navmenu').toggle().trigger('click')
    }
    else if (key == 90) // z for help
    {
      $('#help').toggle()
    }
    else if (key == 66 || key == 70) // f for footer (also "b" which is what kensington remote "stop" button sends
    {
      toggleFooter()
    }
	else if (key == 27) // esc
	{
		removeResults();
	}
    return true
}

function toggleFooter()
{
  $('#footer').toggle()
}

function keyUp(event) {
  var key = event.keyCode;
  debug('keyUp: ' + key);
  if (key == 16) // shift key
  {
    shiftKeyActive = false;
  }
}


function swipeLeft() {
  nextStep()
}

function swipeRight() {
  prevStep()
}

function ListMenu(s)
{
  this.slide = s
  this.typeName = 'ListMenu'
  this.itemLength = 0;
  this.items = new Array();
  this.addItem = function (key, text, slide) {
    if (key.length > 1) {
      thisKey = key.shift()
      if (!this.items[thisKey]) {
        this.items[thisKey] = new ListMenu(slide)
      }
      this.items[thisKey].addItem(key, text, slide)
    } else {
      thisKey = key.shift()
      this.items[thisKey] = new ListMenuItem(text, slide)
    }
  }
  this.getList = function() {
    var newMenu = $("<ul>")
    for(var i in this.items) {
      var item = this.items[i]
      var domItem = $("<li>")
      if (item.typeName == 'ListMenu') {
        choice = $("<a rel=\"" + (item.slide - 1) + "\" href=\"#\">" + i + "</a>")
        domItem.append(choice)
        domItem.append(item.getList())
      }
      if (item.typeName == 'ListMenuItem') {
        choice = $("<a rel=\"" + (item.slide - 1) + "\" href=\"#\">" + item.slide + '. ' + item.textName + "</a>")
        domItem.append(choice)
      }
      newMenu.append(domItem)
    }
    return newMenu
  }
}

function ListMenuItem(t, s)
{
  this.typeName = "ListMenuItem"
  this.slide = s
  this.textName = t
}

var removeResults = function() {
  $('.results').remove();
};

var print = function(text) {
  removeResults();
  var _results = $('<div>').addClass('results').html($.print(text, {max_string:500}));
  $('body').append(_results);
  _results.click(removeResults);
};

function executeCode () {
    result = null;
    var codeDiv = $(this);
    codeDiv.addClass("executing");
    eval(codeDiv.text());
    setTimeout(function() { codeDiv.removeClass("executing");}, 250 );
    if (result != null) print(result);
}
$('.sh_javaScript code').live("click", executeCode);

