﻿/**
 * 롤링 스크롤 스크립트
 *
 * @author hooriza
 */
 
var Rolling = $Class({
    
    _area : null,
    _options : null,
    _reserved_options : null,
    
    _waiter : null,
    _mover : null,
    
    _percent : 0,
    _fromTo : null,
    _paused : true,

    $init : function() {
        
    },
    
    touch : function(oArea, oOptions) {
        
        this._area = $(oArea); // 스크롤해야 하는 영역 저장

        // 옵션 저장
        this._options = {};
        /* JINDO extend */(function(s,a){for(var x in a){s[x]=a[x];}return s;})(this._options, oOptions || {});
        
        this.scrollTo(0);
        
        if (!this._options.suspend)
            this.resume();
    },
    
    scrollTo : function(nPx) {
        
        nPx = nPx % this._options.size;
        if (nPx < 0) nPx = this._options.size + nPx;
        
        this._setScrollPos(nPx);
        
    },
    
    scrollBy : function(nPx) {

        this.scrollTo(this._getScrollPos() + nPx);
        
    },
    
    _setScrollPos : function(nPx) {
        
        this._area[this._options.direction == Rolling.VERTICAL ? "scrollTop" : "scrollLeft" ] = nPx;
    },
    
    _getScrollPos : function() {
        
        return this._area[this._options.direction == Rolling.VERTICAL ? "scrollTop" : "scrollLeft" ];
    },
    
    _applyReservedOptions : function() {
        
        if (this._reserved_options) { // 예약된 옵션이 있으면 적용
            /* JINDO extend */(function(s,a){for(var x in a){s[x]=a[x];}return s;})(this._options, this._reserved_options || {});
            this._reserved_options = null;
        }
        
    },
    
    _startWaiting : function() {
        
        this._applyReservedOptions();
        
        this._stopWaiting();
        this._stopMoving();

        if (this._paused) return;
        
        this._waiter = window.setTimeout($Fn(this._startMoving, this).bind(), this._options.freeze);
    },
    
    _stopWaiting : function() {
        if (this._waiter) window.clearTimeout(this._waiter);
        this._waiter = null;    
    },
    
    _startMoving : function() {
        
        this._applyReservedOptions();
        
        this._percent = 0;
        
        this._fromTo = [];
        
        this._fromTo[0] = this._getScrollPos();
        this._fromTo[1] = this._options.moveSize;
        
        this._stopWaiting();
        this._stopMoving();
        this._mover = window.setInterval($Fn(this._doMoving, this).bind(), this._options.moveInterval);
    },
    
    _stopMoving : function() {
        if (this._mover) window.clearInterval(this._mover);
        this._mover = null; 
    },
    
    _doMoving : function() {
        
        // 아직 움직일 횟수가 남았는지로 '기다리기' 를 시작할건지 판단
        if (this._percent >= 1) {
            this._startWaiting();
            return;
        }
        
        this._percent += this._options.moveStep;
        this._percent = Math.round(this._percent * 10000) / 10000;

        if (this._percent >= 1) this._percent = 1;
        this.scrollTo(this._fromTo[0] + this._fromTo[1] * this._options.effect(this._percent));
        
    },

    resume : function() {
        this._paused = false;
        if (!this._mover) this._startWaiting();
    },
    
    pause : function() {
        this._stopWaiting();
        this._paused = true;
    },
    
    getIndex : function() {
        var nPos = this._getScrollPos();
        return Math.round(nPos / this._options.moveSize);
    },
    
    movePrev : function() {
        
        var nIndex = this.getIndex();
        var nPos = (nIndex - 1) * this._options.moveSize;
        
        this.scrollTo(nPos);
        this._startWaiting();
    },

    moveNext : function() {

        var nIndex = this.getIndex();
        var nPos = (nIndex + 1) * this._options.moveSize;
        
        this.scrollTo(nPos);
        this._startWaiting();
    },
    
    setOptions : function(oOptions) {
        
        this._reserved_options = {}
        this._reserved_options = /* JINDO extend */(function(s,a){for(var x in a){s[x]=a[x];}return s;})(this._reserved_options, oOptions || {});
        
        if (this._mover == null) {
            this._startMoving();
        }
        
        /*      
        effect : Effect.slower, // 점점 느리게 움직이는 효과 사용
        move : { // 움직일때는 100픽셀씩 움직이고 10msec 마다 1% 씩 진행해라
            size : 100,
            step : 0.01,
            interval : 10
        },
        freeze : 1500, // 멈춰있을때는 1.5초동안 멈춰있어라
        */
        
    }

});

Rolling.VERTICAL = 1;
Rolling.HORIZONTAL = 2;

var Effect = {
    linear : function(v) { return v; },
    faster : function(v) { return v * v * v * v; },
    slower : function(v) { var v = Math.sin(v * (Math.PI / 2)); return v * v * v * v; }
};

