function dictget(dict, key, default_arg) {
  if(typeof(dict[key]) == 'undefined') {
    return default_arg
  }
  else {
    return dict[key]
  }
}

var Ticker23 = function(el/*, opts */) {
  this.ticker_list = $(el).find('li')
  this.index = this.ticker_list.length-1;
  
  // could use effects.core.js, but... use baseline for now
  var animation = "toggle";
  var speed = "normal";
  var cycleLength = 3000;
  if(arguments.length > 1) {
    var opts = arguments[1]
    animation = dictget(opts, 'animation', animation)
    speed = dictget(opts, 'speed', speed)
    cycleLength = dictget(opts, 'cycle', cycleLength)
  }
  
  this.animation = animation
  this.speed = speed
  this.cycleLength = cycleLength
  this.running = false
  
  this.length = function() {
    return this.ticker_list.length
  }
  
  this.selectedElement = function() {
    return $(this.ticker_list[this.index])
  }
  
  this.start(true)
}

Ticker23.prototype.start = function(do_now) {
  if(this.running) { return; }
  
  var self = this
  if(this.animation == "slide") {
    var func = function() { self.transitionSlide.call(self) }
  }
  else if(this.animation == "fade") {
    var func = function() { self.transitionFade.call(self) }
  }
  else {
    var func = function() { self.transitionNorm.call(self) }
  }
  this.interval = setInterval(func, this.cycleLength)
  this.running = true
  
  if(do_now) {
    this.delayTimeout = setTimeout(func, 500)
  }
  
  var pt = this.pauseTrigger
  if(typeof(pt) != "undefined") {
    if(pt.is('.pause')) {
      pt.toggleClass('pause')
    }
  }
}

Ticker23.prototype.stop = function() {
  if(!this.running) { return; }

  this.running = false
  try {
    clearInterval(this.interval)
  } catch(e) {}
  
  try {
    clearTimeout(this.delayTimeout)
  } catch(e) {}
  
  this.selectedElement().show()
  
  var pt = this.pauseTrigger
  if(typeof(pt) != "undefined") {
    if(!(pt.is('.pause'))) {
      pt.toggleClass('pause')
    }
  }
}

Ticker23.prototype.prev = function() {
  if(this.index == 0) {
    this.index = this.length() - 1 
  }
  else {
    this.index--;
  }
}

Ticker23.prototype.prevNow = function() {
  this.selectedElement().hide()
  this.prev()
  this.selectedElement().show()
}

Ticker23.prototype.next = function() {
  if(this.index == this.length()-1) {
    this.index = 0
  }
  else {
    this.index++;
  }
}

Ticker23.prototype.nextNow = function() {
  this.selectedElement().hide()
  this.next()
  this.selectedElement().show()
}

Ticker23.prototype.transitionFade = function() {
  var self = this
  this.selectedElement().fadeOut(this.speed,
    function() {
      if(self.running) {
        self.next()
        self.selectedElement().fadeIn(this.speed)
      }
    }
  )
}

Ticker23.prototype.transitionSlide = function() {
  var self = this
  this.selectedElement().slideUp(this.speed,
    function() {
      if(self.running) {
        self.next()
        self.selectedElement().slideDown(this.speed)
      }
    }
  )
}

Ticker23.prototype.transitionNorm = function() {
  var self = this
  this.selectedElement().hide(this.speed,
    function() {
      if(self.running) {
        self.next()
        self.selectedElement().show(this.speed)
      }
    }
  )
}

Ticker23.prototype.bindBackButton = function(el) {
  var self = this
  $(el).click(function(evt) {
    self.stop()
    self.prevNow()
    return false;
  })
}

Ticker23.prototype.bindPauseButton = function(el) {
  var self = this
  $(el).click(function(evt) {
    $(this).toggleClass('pause')
    if(self.running) {
      self.stop()
    }
    else {
      self.start(true)
    }
    return false
  })
  this.pauseTrigger = el
}

Ticker23.prototype.bindNextButton = function(el) {
  var self = this
  $(el).click(function(evt) {
    self.stop()
    self.nextNow()
    return false;
  })
}