var SliderRegistry = {

  sliders: [],

  register: function(slider)
  {
    var next_id = this.sliders.length;
    this.sliders[next_id] = slider;
    return next_id;
  },

  get: function(slider_id)
  {
    return this.sliders[slider_id];
  }
};

function Slider(options)
{
  this.slider_id = SliderRegistry.register(this);
  this.num_slide_steps = options.num_slide_steps;
  this.slide_time_msec = options.slide_time_msec;
  this.slide_timeout_id = 0;
  this.current_block = 1;
  this.container_name = options.container_name;
  this.block_prefix = options.block_prefix;
  this.direction = (options.direction ? options.direction : "horizontal");
  this.auto = (options.auto ? options.auto : false);
  this.loop = (options.loop ? options.loop : false);
  this.pause_msec = (options.pause_msec ? options.pause_msec : 2000);
  this.debug_window = (options.debug_window ? options.debug_window : null);

  this._init = function()
  {
    // count blocks
    this.num_blocks = 0;
    while (true) {
      if ($("" + this.block_prefix + (this.num_blocks + 1)) == null) {
        break;
      }
      else {
        this.num_blocks++;
      }
    }
  
    // start auto-sliding
    if (this.auto) {
      this._auto_slide();
    }
  };

  this._get_block_x_pos = function(block_num)
  {
    return $(this.block_prefix + block_num).offsetLeft;
  };

  this._get_block_y_pos = function(block_num)
  {
    return $(this.block_prefix + block_num).offsetTop;
  };

  this._get_container_x_pos = function()
  {
    var el = $(this.container_name);
    var x_pos = el.style.left;
    if (x_pos.match(/(-?\d+)px/)) {
      return parseInt(RegExp.$1);
    }
    else {
      return 0;
    }
  }

  this._get_container_y_pos = function()
  {
    var el = $(this.container_name);
    var y_pos = el.style.top;
    if (y_pos.match(/(-?\d+)px/)) {
      return parseInt(RegExp.$1);
    }
    else {
      return 0;
    }
  }

  this.first = function()
  {
    if (this.current_block == 1 || this.slide_timeout_id != 0) {
      return;
    }
    this.slide_to(this.current_block = 1);
  };
    
  this.goto = function(page_num)
  {
    if (page_num < 1 || page_num > this.num_blocks) {
      return;
    }
    this.slide_to(this.current_block = page_num);
  };
  
  this.last = function()
  {
    if (this.current_block == this.num_blocks || this.slide_timeout_id != 0) {
      return;
    }
    this.slide_to(this.current_block = this.num_blocks);
  };
  
  this.prev = function()
  {
    if (this.slide_timeout_id != 0) {
      return;
    }
    else if (this.current_block == 1 && !this.loop) {
      return;
    }
    --this.current_block;
    if (this.current_block < 1) {
      this.current_block = this.num_blocks;
    }
    this.slide_to(this.current_block);
  };
  
  this.next = function()
  {
    if (this.slide_timeout_id != 0) {
      return;
    }
    else if (this.current_block == this.num_blocks && !this.loop) {
      return;
    }
    this._log_debug('called next()');
    ++this.current_block;
    if (this.current_block > this.num_blocks) {
      this.current_block = 1;
    }
    this.slide_to(this.current_block);
  };
  
  this.slide_to = function(end_block_num)
  {
    this._log_debug('sliding to block #' + end_block_num);
    var x_start = this._get_container_x_pos();
    var y_start = this._get_container_y_pos();
    var x_end = x_start;
    var y_end = y_start;
    if (this.direction == 'horizontal') {
      x_end = -(this._get_block_x_pos(end_block_num));
    }
    else {
      y_end = -(this._get_block_y_pos(end_block_num));
    }
    this.slide(x_start, x_end, y_start, y_end, 1);
  };
  
  this.slide = function(x_start, x_end, y_start, y_end, step)
  {
    this._log_debug('slide: x_start=' + x_start + ', x_end=' + x_end + ', y_start=' + y_start + ', y_end=' + y_end + ', step=' + step);
    var el = $(this.container_name);
    if (step == this.num_slide_steps) {
      el.style.left = x_end;
      el.style.top = y_end;
      this._log_debug('slide complete');
      if (this.auto) {
        this._auto_slide();
      }
    }
    else {
      var next_left = x_start + ((x_end - x_start) * (Math.sin(Math.PI / 2 * step / this.num_slide_steps)));
      el.style.left = next_left;
      var next_top = y_start + ((y_end - y_start) * (Math.sin(Math.PI / 2 * step / this.num_slide_steps)));
      el.style.top = next_top;
      this._log_debug('new position: top=' + next_top + ', left=' + next_left);
    }
    step++;
    if (step <= this.num_slide_steps) {
      var timeout_msec = Math.floor(this.slide_time_msec / this.num_slide_steps);
      _slider = this;
      var js_code =
        'SliderRegistry.get(' + this.slider_id + ').slide(' +
        x_start + ', ' + x_end + ', ' +
        y_start + ', ' + y_end + ', ' +
        step + ')';
      this.slide_timeout_id = window.setTimeout(js_code, timeout_msec);
    }
    else {
      this.slide_timeout_id = 0;
    }
  };

  this._auto_slide = function()
  {
    var js_code = 'SliderRegistry.get(' + this.slider_id + ').next()';
    window.setTimeout(js_code, this.pause_msec);
  }

  this._log_debug = function(msg)
  {
    if (this.debug_window != null) {
      $(this.debug_window).innerHTML += '<b>' + this.container_name + '</b>: ' + msg + '<br>';
    }
  }

  this._init();
}

