// need lib JSON.parse
(function(){
window.animateWinningRightNow = function(args) {
    return new win.init(args)
};
var win = {
init: function(args) {
    this.div_id = '';
    this.data_url = '';
    this.err_msg = 'no data ';
    this.min_reqs_interval = 5000; // the min time between two requests to server
    this.num = 5; // number of containers
    this.interval = 25; // time between each clips of anime
    this.damping_ratio = .9; // the larger the lesser vibration, with .9 and up no vibr at all
    this.freq = .02; // the smaller natural frequency the longer time
    this.showedIndex = -1;
    this.numConn = 1;
    this.data = [];
    this.objs = [];
    this.loggerInfo = '';
    this.status = {data: 'ready'};
    if (window.XMLHttpRequest) { // Mozilla
        this.request = new XMLHttpRequest();
    } else if (window.ActiveXObject) { // IE
        try {
            this.request = new ActiveXObject("MSXML2.XMLHTTP");
        }
        catch (e) {
            try {
                this.request = new ActiveXObject("Microsoft.XMLHTTP");
            }
            catch (e) {}
        }
    }
    for(var key in args) // use values from args
        if(this[key] != undefined)
            this[key] = args[key];
    this.winning = document.getElementById(this.div_id);
    for(var i=0; i<this.num; i++) {
        this.winning.appendChild(this.newContainer(i));
    }
    if(this.data.length < 1) { // show error message
        var container = document.createElement('div');
        container.id = this.div_id + 'ErrMessage';
        container.className = 'container';
        container.style.top = '0';
        container.style.textAlign = 'center';
        var txt = document.createElement('span');
        txt.style.position = 'relative';
        txt.style.top = '6px';
        txt.innerHTML = this.err_msg;
        container.appendChild(txt);
        this.err_msg = container;
        this.winning.appendChild(container);
    } else
        this.err_msg = undefined;
    var self = this;
    setTimeout(function(){self.roll();}, this.data.length < 1 ? 3000 : 6000);
    if(this.request) setTimeout(function(){self.getData();}, this.data.length < 1 ? 1000 : 6000);
},
newItem: function(no, str) {
    var outer = document.createElement('div');
    outer.className = 'item '+str[0];

    var flag = document.createElement('span');
    flag.className = 'flag '+str[1];
    var flagInner = document.createElement('span');
    flagInner.className = str[2];
    var image = document.createElement('img');
    image.src = '/common/images/empty.gif';
    flagInner.appendChild(image);
    flag.appendChild(flagInner);
    outer.appendChild(flag);

    var name = document.createElement('span');
    name.className = 'name '+str[1];
    var nameInner = document.createElement('span');
    nameInner.className = str[2];
    name.appendChild(nameInner);
    outer.appendChild(name);

    var amount = document.createElement('span');
    amount.className = 'amount '+str[1];
    var amountInner = document.createElement('span');
    amountInner.className = str[2];
    amount.appendChild(amountInner);
    outer.appendChild(amount);
    return {'outer':outer, 'inner':[image, nameInner, amountInner]};
},
newContainer: function(no) {
    var container = document.createElement('div');
    container.className = 'container';
    container.style.top = 28*no + 'px';
    var pod = document.createElement('div');// movable part
    pod.className = 'content';
    pod.style.visibility = 'hidden';
    container.appendChild(pod);
    var pod_items = [];
    var obj;
    obj = this.newItem(no, ['', 'movable', '']);
    pod.appendChild(obj.outer);
    pod_items = pod_items.concat([obj.inner]);
    obj = document.createElement('div');
    obj.className = 'item_space';// some vertical space
    pod.appendChild(obj);
    obj = this.newItem(no, ['', 'movable', '']);
    pod.appendChild(obj.outer);
    pod_items = pod_items.concat([obj.inner]);
    var pot = document.createElement('div');// static part
    pot.className = 'content'; pot.style.top = '6px';
    var pot_item = this.newItem(no, ['', 'movable', '']);// in future, should use ['vertical_middle_outer', 'vertical_middle_middle', 'vertical_middle_inner']); for better positioning. now compromised for performance...
    if(no < this.data.length)// show data directly if available
        this.applyNewData(no, pot_item.inner);
    pot.appendChild(pot_item.outer);
    container.appendChild(pot);
    this.objs[no] = {'pod': pod, 'pod_items': pod_items, 'pot': pot, 'pot_item': pot_item.inner};
    return container;
},
showPod: function(no) {
    if(this.objs[no] == undefined) return;
    this.objs[no].pod.style.visibility = 'visible';
    this.objs[no].pot.style.visibility = 'hidden';
},
showPot: function(no) {
    if(this.objs[no] == undefined) return;
    this.objs[no].pod.style.visibility = 'hidden';
    this.objs[no].pot.style.top = '6px';// mimic vertical_middle
    this.objs[no].pot.style.visibility = 'visible';
},
applyNewData: function(no, obj) {
    if(no>=this.data.length) return;
    var nShow = this.data.length > this.num ? this.num : this.data.length;
    nShow -= (no+1);
    if(nShow < 0) return;
    obj[0].src = this.data[nShow][0];// new flag
    obj[1].innerHTML = this.data[nShow][1];// new flag
    obj[2].innerHTML = '€'+this.data[nShow][2];// new amount
    this.showedIndex = this.showedIndex > no ? this.showedIndex : no;
},
setPod: function(no) {
    if(no>=this.objs.length) return;
    o = this.objs[no].pod_items;
    t = this.objs[no].pot_item;
    o[1][0].src = t[0].src;
    o[1][1].innerHTML = t[1].innerHTML;
    o[1][2].innerHTML = t[2].innerHTML;
    this.applyNewData(no, o[0]);
},
setPot: function(no) {
    o = this.objs[no].pod_items[0];
    t = this.objs[no].pot_item;
    t[0].src = o[0].src;
    t[1].innerHTML = o[1].innerHTML;
    t[2].innerHTML = o[2].innerHTML;
},
doRolling: function() {
    var no = this.status.no;
    var k = this.damping_ratio;
    var f = this.freq;
    if(this.status.isFirst) {
        this.status.isFirst = false;
        if(no >= this.objs.length) {// stop the anime
            clearInterval(this.status.handler);
            this.status.handler = undefined;
            this.status.data = 'ready';
            var self = this;
            setTimeout(function(){self.roll();}, 6000);
            return;
        }
        this.status.t = -10;// start time, should < 0
    } else {
        var t = this.status.t ++;
        if(t == 0) {
            this.objs[no].pod.style.top = '-28px';
            this.showPod(no);
        } else if(t > 0) {
            var tmp = 2*Math.PI*f*t;
            var A = -(28+6)*Math.pow(Math.E, -k*tmp);
            if(Math.abs(A) < 1) {// stop when no movement needed
                this.status.no++;
                this.status.isFirst = true;
                this.setPot(no);
                this.showPot(no);
            } else {
                var pos = A*Math.cos(Math.sqrt(1-k*k)*tmp);
                pos += 6; // to mimic vertical_middle with this offset
                this.objs[no].pod.style.top = Math.round(pos) + 'px';
            }
        }
    }
},
startRolling: function() {
    if(this.status.handler != undefined) return;
    this.status.data = 'using';
    this.status.no = 0; this.status.isFirst = true;
    var self = this;
    this.status.handler = setInterval(function(){self.doRolling();}, this.interval);
},
roll: function() {
    var self = this;
    if(this.status.data != 'ready') {
        setTimeout(function(){self.roll();}, 1000);
        return;
    }
    var numToShow = this.data.length > this.num ? this.num : this.data.length;
    if(this.showedIndex > this.num-2 && this.data.length > this.num) {
        this.data.shift();
    } else if(this.showedIndex > this.data.length-2)
        numToShow = 0;
    if(numToShow > 0) {
        for(var i=0; i<numToShow; ++i) {
            this.setPod(i);
        }
        this.startRolling();
    }
    else
        setTimeout(function(){self.roll();}, 3000);
},
getData: function() {
    var self = this;
    self.clearGetting();
    var n = self.data.length - self.num;
    n = n < 1 ? 1 : n;
    n *= 6000;
    n = n < self.min_reqs_interval ? self.min_reqs_interval : n;
    self.status.getting = setTimeout(function(){self.doGetting();}, n);
},
doGetting: function() {
    var self = this;
    if(this.status.data != 'ready') {
        this.status.getting = setTimeout(function(){self.getData();}, 2000);
        return;
    }
    this.clearGetting();
    this.status.data = 'getting';
    this.request.open("GET", this.data_url, true);
    this.request.onreadystatechange = function() {
        if(self.request.readyState == 4) {
            if(self.status.getting_timeout) {
                clearTimeout(self.status.getting_timeout);
                self.status.getting_timeout = undefined;
            }
            if(self.request.status == 200) {
                var resp = JSON.parse(self.request.responseText);
                self.setData(resp);
            }
            self.getData();
            self.status.data = 'ready';
        }
    }
    this.request.send(null);
    this.status.getting_timeout = setTimeout(function() {
        self.request.abort();
        self.status.getting_timeout = undefined;
        self.getData();
        self.status.data = 'ready';
    }, 20000);// abort the request with timeout 20s
},
clearGetting: function() {
    if(this.status.getting) {
        clearTimeout(this.status.getting);
        this.status.getting = undefined;
    }
},
setData: function(l) {
    while(l.length>0) {
        var found = false;
        for(i=0; i<this.data.length; ++i) {
            if(l[0][1] == this.data[i][1] && l[0][2] == this.data[i][2]) {
                found = true;
                break;
            }
        }
        if(found) l.shift();
        else break;
    }
    if(l.length>0) this.data = this.data.concat(l).slice(0,100);
    // remove error message
    if(this.err_msg && this.data.length>0) {
        this.err_msg.parentNode.removeChild(this.err_msg);
        this.err_msg = undefined;
    }
},
__place_holder: undefined
};
win.init.prototype = win;
})();

