

if ( typeof(Animation) == "undefined" ) Animation = function () {};

Animation.Raster = function (container,imgsrc) {
    if ( ! container ) return;
    this.initialized = false;       // canvas size is known or not
    this.startOnLoad = false;       // start commanded received
    this.started = false;           // start flag
    this.finished = false;          // all done flag
    this.linebuf = [];              // rect lines buffer
    this.trush = [];
    this.onComplete = null;         // call back function
    this.initialize(container,imgsrc);
    return this;
};

Animation.Raster.VERSION = "0.02";
Animation.Raster.prototype.waveSpeed = 0.5;
Animation.Raster.prototype.waveHeight = 0.5;
Animation.Raster.prototype.lineHeight = 6;
Animation.Raster.prototype.downSeconds = 1.0;
Animation.Raster.prototype.fadeSeconds = 4.0;
Animation.Raster.prototype.clip = true;
Animation.Raster.prototype.background = null;



Animation.Raster.prototype.initialize = function( container,imgsrc ) {
    if ( typeof container == "string" ) {
        container = document.getElementById(container);
    }
    if ( ! container ) return;

    this.outer = document.createElement( "div" );
    this.outer.style.position = "relative";

    this.canvas = document.createElement( "div" );
    this.canvas.style.position = "absolute";
    this.outer.appendChild( this.canvas );

    if ( imgsrc ) {
        container.appendChild( this.outer );
        this.original = document.createElement( "img" );    // source image
        this.original.src = imgsrc;
        this.original.style.visibility = "hidden";
        this.outer.appendChild( this.original );
        this.getImageSize( this.original );
    } else {
        container.parentNode.insertBefore( this.outer, container );
        this.original = container;                      // original
        this.original.style.visibility = "hidden";
        this.canvasWidth  = this.original.offsetWidth;
        this.canvasHeight = this.original.offsetHeight;
        this.initialized = true;                        //
    }
};

Animation.Raster.prototype.getImageSize = function( orig ) {
    var loadmess = this.message( "Now loading..." );
    var checksize = orig.cloneNode(true);      // image for checking
    checksize.style.position = "absolute";
    var __this = this;
    var ldfunc = function(e){
        if ( ! e && window.event ) e = window.event;    // IE
        __this.canvasWidth  = checksize.offsetWidth;
        __this.canvasHeight = checksize.offsetHeight;
        __this.initialized = true;
        checksize.parentNode.removeChild( checksize );
        loadmess.parentNode.removeChild( loadmess );
        if ( __this.startOnLoad ) {
            __this.beginAnimation();
        }
    };
    this.appendEvent( checksize, "load", ldfunc );  // onload image
    this.outer.appendChild( checksize );
};

Animation.Raster.prototype.clipCanvas = function() {
    if ( ! this.canvasWidth || ! this.canvasHeight ) return;
    this.canvas.style.width  = this.canvasWidth+"px";
    this.canvas.style.height = this.canvasHeight+"px";
    if ( this.clip ) {
        this.canvas.style.clip = "rect(0px,"+(this.canvasWidth)+"px,"+(this.canvasHeight)+"px,0px)";
    }
}

Animation.Raster.prototype.clickToFinish = function() {
    var __this = this;
    var clfunc = function(e){
        if ( ! e && window.event ) e = window.event;    // IE
        if ( ! __this.initialized ) return;                  // not loaded yet
        if ( ! __this.started ) return;                 // not started yet
        if ( __this.finished ) return;                      // already done
        __this.finish();
    };
    this.appendEvent( this.canvas, "click", clfunc );        // onclick canvas
}

Animation.Raster.prototype.message = function( mess ) {
    var tload = document.createTextNode( mess );
    elem = document.createElement( "span" );
    elem.appendChild( tload );
    elem.style.color = "#FFFFFF";
    elem.style.background = "#FF3333";
    elem.style.position = "absolute";
    elem.style.fontSize = "12px";
    elem.style.fontFamily = "Helvetica";
    elem.style.fontWeight = "bold";
    elem.style.width = "14em";
    elem.style.padding = "4px";
    if ( this.outer.firstChild ) {
        this.outer.insertBefore( elem, this.outer.firstChild );
    } else {
        this.outer.appendChild( elem );
    }
    return elem;
}

Animation.Raster.prototype.appendEvent = function( elem, type, func ) {
    if ( elem.addEventListener ) {
        return elem.addEventListener( type, func, false );
    } else if ( elem.attachEvent ) {
        return elem.attachEvent( "on"+type, func );
    }
};

Animation.Raster.SinCache = [];

Animation.Raster.prototype.get_sin_table = function(intrv) {
    if ( Animation.Raster.SinCache[intrv] ) return Animation.Raster.SinCache[intrv];
    var sintable = [];
    for( var i=0; i<intrv; i++ ) {
        sintable[i] = Math.sin(2.0 * Math.PI * i / intrv);
    }
    Animation.Raster.SinCache[intrv] = sintable;
    return sintable;
};

Animation.Raster.prototype.beginAnimation = function() {
    if ( this.background ) this.canvas.style.background = this.background;
    var sinsize = Math.floor( this.canvasHeight / this.lineHeight );
    this.sinTable = this.get_sin_table(sinsize);
    this.clipCanvas();
    this.clickToFinish();

    var lines = Math.floor(this.canvasHeight/this.lineHeight);
    for( var i=lines; i>=0; i-- ) {
        this.cloneLine(i,this.lineHeight)
    }

    this.timer = new Animation.Raster.Timer(this);                  // timer object
    this.timer.start();
};

Animation.Raster.prototype.scroll = function() {
    this.started = true;
    if ( this.initialized ) {
        this.beginAnimation();
    } else {
        this.startOnLoad = true;  // wait until image loaded
    }
};

Animation.Raster.prototype.cloneLine = function(top,lines) {
    if ( this.linebuf[top] ) return this.linebuf[top];
    var newline = this.original.cloneNode(true);
    newline.style.position = "absolute";
    newline.style.visibility = "hidden";
    newline.style.clip = "rect("+(top*lines)+"px,"+(this.canvasWidth)+"px,"+((top+1)*lines)+"px,0px)";
    this.canvas.appendChild( newline );
    this.linebuf[top] = newline;
    return newline;
};

Animation.Raster.prototype.loop = function(secs,count) {
    var lines = Math.floor(this.canvasHeight/this.lineHeight);
    secs *= 0.001;  // millisec to second

    var wavy = this.canvasHeight*this.waveHeight;
    var y = 0;
    var top = 0;
    if ( secs < this.downSeconds ) {
        var prog1 = secs/this.downSeconds;
        y = Math.floor(prog1*this.canvasHeight) - this.canvasHeight;
        y -= y % this.lineHeight;
        top = Math.floor( lines*(1.0-prog1) );
    } else if ( secs < this.downSeconds + this.fadeSeconds ) {
        var prog3 = (secs-this.downSeconds)/this.fadeSeconds;
        wavy *= (1.0-prog3);
    } else {
        this.finish();
        return false;
    }

    var wavecnt = Math.floor(secs*this.sinTable.length*this.waveSpeed);
    for( var i=top; i<=lines; i++ ) {
        var x = Math.floor( wavy * this.sinTable[(i-top+wavecnt)%this.sinTable.length] );
        this.linebuf[i].style.left = x+"px";
        this.linebuf[i].style.top = y+"px";
        this.linebuf[i].style.visibility = "visible";
    }
    return true;
};

Animation.Raster.prototype.finish = function() {
    if ( this.timer ) {
        if ( this.timer.is_running() ) this.timer.stop();
        this.timer = null;
    }
    if ( this.finished ) return;
    this.original.style.visibility = "visible";
    this.canvas.style.background = "";
    for( var i=0; i<this.linebuf.length; i++ ) {
        if ( ! this.linebuf[i] ) continue;
        if ( ! this.linebuf[i].parentNode ) continue;
        this.linebuf[i].parentNode.removeChild( this.linebuf[i] );
        this.linebuf[i] = null;
    }
    for( var i=0; i<this.trush.length; i++ ) {
        if ( ! this.trush[i] ) continue;
        if ( ! this.trush[i].parentNode ) continue;
        this.trush[i].parentNode.removeChild( this.trush[i] );
        this.trush[i] = null;
    }
    this.finished = true;
    if ( this.onComplete ) this.onComplete( this.original );
};

//  Animation.Raster.Timer class

Animation.Raster.Timer = function (target) {
    this.target = target;
    this.started = false;
    this.stoped = false;
    this.count = 0;
    var __this = this;
    this.next = function(){
        if ( __this.stoped ) return;
        var now_time = (new Date()).getTime();
        if ( ! __this.begin_time ) __this.begin_time = now_time;
        var spent_time = now_time-__this.begin_time;
        var flag = __this.target.loop(spent_time,__this.count++);
        if ( flag ) {
            setTimeout( __this.next, 1 );
        } else {
            __this.stop();
        }
    };
    return this;
};
Animation.Raster.Timer.prototype.start = function () {
    this.started = true;
    this.stoped = false;
    this.next();
};
Animation.Raster.Timer.prototype.stop = function () {
    this.stoped = true;
};
Animation.Raster.Timer.prototype.is_running = function () {
    return ( this.started && ! this.stoped );
};

