lclass("ImagePreloader", [LEventHandling], {
    cons: function(imgs) {
        this.loadingTimer = new LTimer(100, this, this.checkLoaded);
        
        this.images = [];
        this.addImages(imgs);
    },
    
    start: function() {
        this.checkLoaded();
    },
    
    addImages: function(imgs) {
        var i, img;
        for (i = 0; i < imgs.length; i++) {
            img = imgs[i];
            if (img.node)
                img = img.node();
                
            if (img.nodeName && img.nodeName.toLowerCase() == "img")
                this.images.push(img);
        }
    },
    
    checkLoaded: function() {
        var i;
        for (i = 0; i < this.images.length; i++) {
            if (this.images[i].loading) {
                this.loadingTimer.start();
                return;
            }
        }
        
        this.fireEvent("load");
    }
});

lclass("CircularScroller", {
    cons: function(el, conf) {
        $PM(this, conf, {
            
        });
        
        this.el = $(el);
        this.elItems = $S("ul", this.el);
        this.items = $C("li", this.elItems);
        
        if (this.items.length == 0)
            return;
            
        this.itemWidth = this.items[0].offsetWidth();
        this.numItems = this.items.length;
        this.maxX = this.itemWidth * this.numItems;
        this.x = 0;
        this.tx = 0;
        this.areaWidth = this.elItems.offsetWidth();
        
        while (this.items.length * this.itemWidth <= this.areaWidth * 2 + 1) {
            var i, item;
            for (i = 0; i < this.numItems; i++) {
                var cn = this.items[i].node().cloneNode(true);
                cn.__lutilObj = null;
                item = $(cn);
                this.items.push(item);
                this.elItems.append(item);
            }
        }
        
        this.el.attachEvent("mouseover", this, this.mouseOver);
        this.el.attachEvent("mouseout", this, this.mouseOut);
        
        var t = $S(".CircularScrollerLeft", this.el);
        if (t) {
            t.attachEvent("click", this, function() { return this.scrollRight(2); });
        }
        
        t = $S(".CircularScrollerRight", this.el);
        if (t) {
            t.attachEvent("click", this, function() { return this.scrollLeft(2); });
        }
        
        this.autoScrollTimer = new LTimer(10000, this, this.autoScroll);
        this.animTimer = new LTimer(50, this, this.tick);
        
        var preloader = new ImagePreloader($C("img", this.elItems));
        preloader.attachEvent("load", this, this.start);
        preloader.start();
    },
    
    start: function() {
        this.updatePositions();
        this.autoScrollTimer.start();
        
        new LAnimation([
            [this.el,
                [0, "opacity: 0.0; visibility: visible"],
                [2000, "opacity> 1.0"]
            ]
        ]).start();
    },
    
    autoScroll: function() {
        this.scrollLeft(0.4);
        
        this.autoScrollTimer.start();
    },
    
    scrollLeft: function(vel) {
        this.tx += this.itemWidth;
        this.vel = vel;
        this.animTimer.start();
        
        return false;
    },
    
    scrollRight: function(vel) {
        this.tx -= this.itemWidth;
        this.vel = -vel;
        this.animTimer.start();
        
        return false;
    },
    
    tick: function() {
        var sign = Math.sgn(this.tx - this.x);
        
        this.x += sign * Math.max(1, Math.sqrt(Math.abs(this.tx - this.x)) * Math.abs(this.vel));
        
        sign = Math.sgn(this.tx - this.x);
        
        if (sign != Math.sgn(this.vel)) {
            while (this.tx < 0)
                this.tx += this.maxX;
            this.tx %= this.maxX;
            this.x = this.tx;
        } else {
            this.animTimer.start();
        }
        
        this.updatePositions();
    },
    
    updatePositions: function() {
        var pos = this.x, index;
        while (pos < 0)
            pos += this.maxX;
        pos %= this.maxX;
        pos = -pos;
        
        for (index = 0; index < this.items.length; index++, pos += this.itemWidth) {
            if (pos >= -this.itemWidth && pos < this.areaWidth + this.itemWidth)
                this.items[index].style({left: Math.floor(pos) + "px", display: "block"});
            else
                this.items[index].style({display: "none"});
            
            notFirst = true;
        }
    },
    
    mouseOver: function() {
        this.autoScrollTimer.stop();
    },
    
    mouseOut: function() {
        this.autoScrollTimer.start();
    }
});