// this function sets up the necessary dom nodes for the scroll-bar
// we have a custom scroll-bar to emphasize that the scroll bars appearing
// do not belong to the widget but to the operating system

function scrollbars()
{ 
  function g(e){return document.getElementById(e);} // shortcut function

  var self = this;
  
  var scale = 15; // the width and height of the scrollbars
  
  // element references
  var e_frameObject;
  var e_scroll = g('scroll');
  var e_h = g('scroll-h');
  var e_v = g('scroll-v');
  var e_left = g('scroll-left');
  var e_right = g('scroll-right');
  var e_up = g('scroll-up');
  var e_down = g('scroll-down');
  var e_hBar = g('scroll-h-bar');
  var e_vBar = g('scroll-v-bar');
  var e_corner = g('scroll-corner');
  
  var scroll_h_enabled; //bool
  var scroll_v_enabled; //bool
  
  // the size of the draggable bar
  var bar_h_size; // int
  var bar_v_size; // int
  
  // the total length of the area that the draggable bar can go
  var space_h_size; // int
  var space_v_size; // int
  
  // the number of pixels the bar is from the start
  var scroll_h_off;
  var scroll_v_off;
  
  // the ratio between scrolled to the start (0) and the end (1)
  var scroll_h_ratio; // 0 <= float <= 1
  var scroll_v_ratio; // 0 <= float <= 1
  
  // token values that store the real scroll position
  var scrollLeft;
  var scrollTop;
  
  var mouseup = null;
  
  // this is the area after subtracting the scrollbars (the area the widget displays)
  var areaWidth; //px
  var areaHeight; //px
  
  // call this whenever the screen size changes or the widget size changes to "fix" the scrollbar sizes
  this.fix = function(reset, frameWindow)
  {
    if (mouseup) mouseup(); // stop dragging events etc.
    
    e_frameObject = g('frameObject');

    if (reset)
    {
      scroll_h_off = 0;
      scroll_v_off = 0;
      scroll_h_ratio = 0; 
      scroll_v_ratio = 0;
      scrollTop = 0;
      scrollLeft = 0;
    }

    areaWidth = ui.device.screen.availWidth;
    areaHeight = ui.device.screen.availHeight;

    // if a scrollbar appears then the space for the other axis gets shortened

    scroll_h_enabled = false;
    scroll_v_enabled = false;
    
    if (ui.device.widget.opened)
    {
      
      if (areaWidth < ui.device.widget.width)
      {
        scroll_h_enabled = true;
        areaHeight -= scale;
      }
      
      if (areaHeight < ui.device.widget.height)
      {
        scroll_v_enabled = true;
        areaWidth -= scale;
      }
      // try 'h' again because 'v' might have introduced it when it shortened the space
      if (scroll_v_enabled && !scroll_h_enabled && areaWidth < ui.device.widget.width)
      {
        scroll_h_enabled = true;
        areaHeight -= scale;
      }
    }
    
    e_corner.style.display = 'block';//scroll_h_enabled && scroll_v_enabled ? 'block' : 'none';
    
    space_h_size = areaWidth - scale*2;
    space_v_size = areaHeight - scale*2;

    bar_h_size = Math.round(space_h_size * areaWidth / ui.device.widget.width);
    bar_v_size = Math.round(space_v_size * areaHeight / ui.device.widget.height);

    if (scroll_h_enabled)
    {
      e_h.style.width = areaWidth + 'px';
      scroll_h_ratio = scrollLeft / (ui.device.widget.width - areaWidth);
      scroll_h_off = scroll_h_ratio * (space_h_size-bar_h_size);
      e_h.style.display = 'block';
      e_hBar.style.width = bar_h_size + 'px';
    }
    else
    {
      e_h.style.display = 'none';
      scroll_h_off = scroll_h_ratio = 0;
    }

    if (scroll_v_enabled) // scrollbars are not needed
    {
      e_v.style.height = areaHeight+'px';
      scroll_v_ratio = scrollTop / (ui.device.widget.height - areaHeight);
      scroll_v_off = scroll_v_ratio * (space_v_size-bar_v_size);
      e_v.style.display = 'block';
      e_vBar.style.height = bar_v_size + 'px';
    }
    else
    {
      e_v.style.display = 'none';
      scroll_v_off = scroll_v_ratio = 0;
    }
    
    applyScroll(true, true);
    
  };
  
  // adjusts the variables to scroll by a certain number of pixels
  function scrollBy(x,y)
  {
    scroll_h_ratio += x / (ui.device.widget.width - areaWidth);
    scroll_v_ratio += y / (ui.device.widget.height - areaHeight);

    //scroll_h_ratio = scroll_h_ratio < 0 
    
    scroll_h_off = Math.round( scroll_h_ratio * (space_h_size-bar_h_size) );
    scroll_v_off = Math.round( scroll_v_ratio * (space_v_size-bar_v_size) );
    applyScroll(!!x, !!y);
  }
  
  // keeps scrolling by x,y until the mouseup event
  function scrollByContinually(x,y, ele)
  {    
    ele.className = 'using';
    var interval=0, timeout=setTimeout(function() // a short wait before continually scrolling
    {
      timeout=0;
      interval=setInterval(function()
      {
        scrollBy(x,y);
      }, 50);
    }, 300);
    scrollBy(x,y);
    document.onmouseup = mouseup = function()
    {
      ele.className = '';
      if (interval) clearInterval(interval);
      if (timeout) clearTimeout(timeout);
      document.onmouseup = mouseup = null;
    };
  }
  
  // adjusts the bars and margins in the dom to reflect the scroll variables (i.e. applies the scroll)
  function applyScroll(h,v) // both h & v are boolean, if true then we apply scroll on that axis
  {
    if (!e_frameObject) return;
    
    // first get variables in correct domain:
    scroll_h_off = Math.max(0, Math.min(space_h_size - bar_h_size, scroll_h_off));
    scroll_v_off = Math.max(0, Math.min(space_v_size - bar_v_size, scroll_v_off));
    scroll_h_ratio = Math.max(0, Math.min(1, scroll_h_ratio));
    scroll_v_ratio = Math.max(0, Math.min(1, scroll_v_ratio));
          
    if (h)
    {
      e_hBar.style.left = scroll_h_off + 'px';
      scrollLeft = (scroll_h_ratio * (ui.device.widget.width - areaWidth) );
      e_frameObject.style.marginLeft = '-' + Math.round(scrollLeft) + 'px';
    }
    if (v)
    {
      e_vBar.style.top = scroll_v_off + 'px';
      scrollTop = (scroll_v_ratio * (ui.device.widget.height - areaHeight) );
      e_frameObject.style.marginTop = '-' + Math.round(scrollTop) + 'px';
    }
  }
  
  e_up.onmousedown = function()
  {
    scrollByContinually(0, -20, this);
  };
  e_down.onmousedown = function()
  {
    scrollByContinually(0, +20, this);
  };
  e_left.onmousedown = function()
  {
    scrollByContinually(-20, 0, this);
  };
  e_right.onmousedown = function()
  {
    scrollByContinually(+20, 0, this);
  };
  
  document.onmousewheel = function(e)
  {
    var x = 0, y = e.detail*10;
    if (y < 0 ? (scroll_v_ratio <= 0) : (scroll_v_ratio >= 1))
    {
      x = y, y=0;
    }
    scrollBy(x,y);
    return false;
  };
    
  window.onkeypress = function(e)
  {
    switch (e.keyCode)
    {
      case 33: // page up
        scrollBy(0, -areaHeight);
        break;
      case 34: // page down
        scrollBy(0, +areaHeight);
        break;
      case 35: // end
        scrollBy(0, +areaHeight);
        break;
      case 36: // home
        scrollBy(0, -areaHeight);
        break;
      case 37: // left
        scrollBy(-10, 0);
        break;
      case 38: // up
        scrollBy(0, -10);
        break;
      case 39: // right
        scrollBy(+10, 0);
        break;
      case 40: // down
        scrollBy(0, +10);
        break;
    }
  };

  // dragging the horizontal bar
  e_hBar.onmousedown = function(e)
  {
    this.className = 'using';
    var startX = e.clientX, startOff = scroll_h_off;
    document.onmousemove = function(e)
    {
      scroll_h_off = Math.max(0, Math.min(space_h_size - bar_h_size, startOff + (e.clientX - startX)));
      scroll_h_ratio = scroll_h_off / (space_h_size-bar_h_size);
      applyScroll(true, false);
    };
    document.onmouseup = mouseup = function()
    {
      document.onmousemove = null;
      document.onmouseup = mouseup = null;
      e_hBar.className = '';
    };
  };
  
  // dragging the vertical bar
  e_vBar.onmousedown = function(e)
  {
    this.className = 'using';
    var startY = e.clientY, startOff = scroll_v_off;
    document.onmousemove = function(e)
    {
      scroll_v_off = startOff + (e.clientY - startY);
      scroll_v_ratio = scroll_v_off / (space_v_size-bar_v_size);
      applyScroll(false, true);
    };
    document.onmouseup = mouseup = function()
    {
      document.onmousemove = null;
      document.onmouseup = mouseup = null;
      e_vBar.className = '';
    };
  };  
}
