// scroll clients logo

Function.prototype.bind = function(object) {
    var method = this;
    return function() {
        return method.apply(object, arguments);
    };
};

function logoScroller() {
  var img_template = null;
  var div_template = null;
  var logoIframe = null;
  var logoContainer = null;
  var offsetMargin = 0;
  var counter = 0;
  var status = ''; // current state of mouse handler
  var state = 0; // current state of statemachine
  var default_speed = 10; // speed
  var speed_factor = 30;
  var worker_semaphore = false;
  var worker_timer = null;
  var heap = new Object; // is heap for statemachine
  this.setIframe = function(iframe) {
    logoIframe = iframe;
  };
  this.setContainer = function(container) {
    logoContainer = container;
  };
  this.getWidth = function(object) {
    if( !object ) {
      return 0;
    }
    var value = object.offsetWidth;
    value = parseInt(value);
    return ( isNaN(value) ? 0 : value );
  };
  this.getMarginLeft = function(object) {
    if( !object ) {
      return 0;
    }
    var value = object.style.marginLeft;
    value = parseInt(value);
    return ( isNaN(value) ? 0 : value );
  };
  this.setMarginLeft = function(object, value) {
    if( !object ) {
      return false;
    }
    if( isNaN( value ) ) {
      return false;
    }
    object.style.marginLeft = value + 'px';
  };
  this.setOffset = function(offset) {
    offsetMargin = offset;
  };
  this.getFirstWidth = function() {
    var object = null;
    if( !logoContainer ) {
      alert('something wrong: undefined logoContainer');
      return 0;
    }
    var width = 0;
    var count = 0;
    for( var i = 0; i < logoContainer.childNodes.length; i++ ) {
      var node = logoContainer.childNodes[i];
      if( node.nodeType == 1 ) {
        object = node;
        width += this.getWidth( object );
        count++;
      }
      if( count == 2 ) {
        break;
      }
    }
    return width;
  };
  this.shiftLogo = function() {
    var logo = null;
    var delimiter = null;
    var count = 0;
    for( var i = 0; i < logoContainer.childNodes.length; i++ ) {
      var node = logoContainer.childNodes[i];
      if( node.nodeType && node.nodeType == 1 ) {
        count++;
        if( count == 1 ) {
          logo = node;
        }
        if( count == 2 ) {
          delimiter = node;
          break;
        }
      }
    }
    if( count == 2 ) {
      var new_logo = logo.cloneNode(true);
      var new_delimiter = delimiter.cloneNode(true);
      logoContainer.appendChild(new_logo);
      logoContainer.appendChild(new_delimiter);
      logoContainer.removeChild(logo);
      logoContainer.removeChild(delimiter);
    } else {
      alarm('delimiter not found');
    }
  };
  this.getLastWidth = function() {
    var object = null;
    if( !logoContainer ) {
      alert('something wrong: undefined logoContainer');
      return 0;
    }
    var width = 0;
    var count = 0;
    for( var i = logoContainer.childNodes.length - 1; i > 0; i-- ) {
      var node = logoContainer.childNodes[i];
      if( node.nodeType && node.nodeType == 1 ) {
        object = node;
        width += this.getWidth( object );
        count++;
      }
      if( count == 2 ) {
        break;
      }
    }
    return width;
  };
  this.pushLogo = function() {
    var logo = null;
    var delimiter = null;
    var count = 0;
    for( var i = logoContainer.childNodes.length - 1; i > 0; i-- ) {
      var node = logoContainer.childNodes[i];
      if( node.nodeType == 1 ) {
        count++;
        if( count == 1 ) {
          delimiter = node;
        }
        if( count == 2 ) {
          logo = node;
          break;
        }
      }
    }
    if( count == 2 ) {
      var new_logo = logo.cloneNode(true);
      var new_delimiter = delimiter.cloneNode(true);
      logoContainer.insertBefore(new_delimiter, logoContainer.firstChild);
      logoContainer.insertBefore(new_logo, logoContainer.firstChild);
      logoContainer.removeChild(logo);
      logoContainer.removeChild(delimiter);
    } else {
      alarm('delimiter not found');
    }
  };
  this.LeftScrollPress = function() {
    if ( !logoContainer ) {
      return;
    }
    status = 'L'; // Left scroll press
    if( !worker_semaphore ) {
      this.worker();
    }
    return false;
  };
  this.LeftScrollRelease = function() {
    if( !logoContainer ) {
      return;
    }
    status = ''; // release scroll status
    return false;
  };
  this.RightScrollPress = function() {
    if( !logoContainer ) {
      return;
    }
    status = 'R'; // Right scroll press
    if( !worker_semaphore ) {
      this.worker();
    }
    return false;
  };
  this.RightScrollRelease = function() {
    if( !logoContainer ) {
      return;
    }
    status = ''; // release scroll status
    return false;
  };
  this.worker = function() {
    worker_semaphore = true;
    if( !heap.curr_shift ) { heap.curr_shift = 0; }
    if( !heap.need_shift ) { heap.need_shift = 0; }
    if( !heap.speed ) { heap.speed = default_speed; }
    if( !logoContainer ) {
      return null;
    }
    if( status == 'L' ) {
      if( !state ) {
        heap.need_shift = -1 * this.getFirstWidth();
        state = 1;
      }
    }
    if( status == 'R' ) {
      if( !state ) {
        heap.need_shift = 1 * this.getLastWidth();
        state = 5;
      }
    }
    switch( state ) {
    case 6:
      // moving is end
      // need to remove first logo to last logo
      this.pushLogo();
      this.setMarginLeft(logoContainer, offsetMargin);
      // to default state
      heap.curr_shift = 0;
      state = 0;
      this.set_handler( heap.speed );
      break;
    case 5:
      // right scroll
      // check: need to move
      if( !heap.curr_shift ) {
        heap.curr_shift = 0;
      }
      if( heap.curr_shift < heap.need_shift ) {
        heap.curr_shift++;
        if( !status ) {
          //heap.speed = Math.round( speed_factor * ( Math.abs(heap.curr_shift) / Math.abs(heap.need_shift) ) );
          heap.speed = Math.round( Math.abs(heap.curr_shift) / ( Math.abs(heap.need_shift) - Math.abs(heap.curr_shift) + 1 ) );
        } else {
          heap.speed = default_speed;
        }
        this.setMarginLeft(logoContainer, heap.curr_shift + offsetMargin );
      } else {
        state++;
      }
      this.set_handler( heap.speed );
      break;
    case 2:
      // moving is end
      // need to remove first logo to last logo
      this.shiftLogo();
      this.setMarginLeft(logoContainer, offsetMargin);
      // to default state
      heap.curr_shift = 0;
      state = 0;
      this.set_handler( heap.speed );
      break;
    case 1: // initial move to left
      // check: need to move
      if( !heap.curr_shift ) {
        heap.curr_shift = 0;
      }
      if( heap.curr_shift > heap.need_shift ) {
        heap.curr_shift--;
        if( !status ) {
          //heap.speed = Math.round( speed_factor * ( Math.abs(heap.curr_shift) / Math.abs(heap.need_shift) ) );
          heap.speed = Math.round( Math.abs(heap.curr_shift) / ( Math.abs(heap.need_shift) - Math.abs(heap.curr_shift) + 1 ) );
        } else {
          heap.speed = default_speed;
        }
        this.setMarginLeft(logoContainer, heap.curr_shift + offsetMargin );
      } else {
        state++;
      }
      this.set_handler( heap.speed );
      break;
    default:
      // clear all mutex and other actions
      if( worker_timer ) {
        clearInterval(worker_timer);
        worker_timer = null;
      };
      worker_semaphore = false;
    }
  };
  this.set_handler = function(speed) {
    if( !speed ) {
      speed = 1;
    }
    setTimeout( function() { this.worker() }.bind(this), speed);
    if( !worker_timer ) {
      //worker_timer = setInterval( function() { this.worker() }.bind(this), speed);
    }
  };
};


