/**********************************
* Rafina 0.1.5
* author: Mario Balibrera
*    web: mariobalibrera.com
*  email: mario.balibrera@gmail.com
**********************************/

Rafina = {};

Rafina.Stripper = function() {
    var self = this;
    var LOWER = 'abcdefghijklmnopqrstuvwxyz';
    var UPPER = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    var ALPHA = LOWER+UPPER;
    var NUMS = '0123456789';
    var ALL = ALPHA+NUMS;
    var process = function(initial, allowed, extra) {
        if (extra) {
            allowed += extra;
        }
        var s = '';
        for (var i=0;i<initial.length;i++) {
            if (allowed.indexOf(initial.charAt(i)) != -1) {
                s += initial.charAt(i);
            }
        }
        return s;
    }
    self.lower = function(s, extra) {
        return process(s, LOWER, extra);
    }
    self.upper = function(s, extra) {
        return process(s, UPPER, extra);
    }
    self.alpha = function(s, extra) {
        return process(s, ALPHA, extra);
    }
    self.numbers = function(s, extra) {
        return process(s, NUMS, extra);
    }
    self.alphanum = function(s, extra) {
        return process(s, ALL, extra);
    }
    self.strip = function(s) {
        while (s && s.charAt(0) == " ") {
            s = s.slice(1);
        }
        while (s && s.charAt(s.length-1) == " ") {
            s = s.slice(0, s.length-1);
        }
        return s;
    }
}

Rafina.TableSort = function() {
    var self = this;
    var col = 0;
    var mode = 'num';
    var higher = function(p1, p2) {
        if (mode == "num") {
            return parseInt(p1.childNodes[col].innerHTML) > parseInt(p2.childNodes[col].innerHTML);
        }
        if (mode == "alpha") {
            return [p1.childNodes[col], p2.childNodes[col]].sort()[0] != p2.childNodes[col];
        }
    }
    self.set_mode_alpha = function() {
        mode = 'alpha';
    }
    self.set_mode_num = function() {
        mode = 'num';
    }
    self.set_column = function(num) {
        col = num;
    }
    self.adjust = function(row) {
        var up = row.previousSibling;
        var down = row.nextSibling;
        var all = row.parentNode;
        if (up && higher(row, up)) {
            all.insertBefore(row, up);
        }
        else if (down && higher(down, row)) {
            all.insertBefore(down, row);
        }
        else {
            return;
        }
        self.adjust(row);
    }
}

Rafina.TabCompletion = function() {
    var self = this;
    var words = [];
    self.reset_words = function() {
        words = [];
    }
    self.set_words = function(w) {
        words = w;
    }
    self.add_words = function(w) {
        words = words.concat(w);
    }
    self.complete = function(str) {
        for (var i = 0; i < words.length; i++) {
            if (str == words[i].slice(0,str.length)) {
                return words[i];
            }
        }
        return str;
    }
}

Rafina.InputMemory = function() {
    var self = this;
    var max = 10;
    var index = 10;
    var cache = ["","","","","","","","","",""];
    var rotate = function() {
        if (index == max) {
            return "";
        }
        else {
            return cache[index];
        }
    }
    self.set_size = function(s) {
        max = s;
        index = s;
        cache = [];
        for (var i = 0; i < s; i++) {
            cache.push("");
        }
    }
    self.remember = function(s) {
        index = max;
        for (var i = 0; i < max; i++) {
            if (cache[i] == s) {
                cache = cache.slice(0,i).concat(cache.slice(i+1,max));
                break;
            }
        }
        cache.push(s);
        if (cache.length > max) {
            cache = cache.slice(1);
        }
    }
    self.up = function() {
        index -= 1;
        if (index == -1) {
            index = max;
        }
        return rotate();
    }
    self.down = function() {
        index += 1;
        if (index > max) {
            index = 0;
        }
        return rotate();
    }
}

Rafina.DelimReader = function() {
    var self = this;
    var buff = "";
    var delim = null;
    var cb = null;
    var separate_events = function() {
        var sep = buff.indexOf(delim);
        if (sep == -1) {
            return;
        }
        var frame = buff.slice(0,sep);
        buff = buff.slice(sep+delim.length);
        cb(frame);
        separate_events();
    }
    self.set_delim = function(d) {
        delim = d;
    }
    self.set_cb = function(func) {
        cb = func;
    }
    self.read = function(data) {
        buff += data;
        separate_events();
    }
}

Rafina.XMLReader = function() {
    var self = this;
    var parser = new DOMParser();
    var cb = null;
    var name = null;
    var buff = "";
    var checked = 0;
    var separate_events = function() {
        if (!name) {
            if (!buff) {
                return;
            }
            if (buff.charAt(0) != "<") {
                checked = 0;
                buff = buff.slice(1);
                return separate_events();
            }
            close_index = buff.indexOf(">");
            if (close_index == -1) {
                return;
            }
            if (buff.charAt(close_index-1) == "/") {
                var frame = parser.parseFromString(buff.slice(0,close_index+1), "text/xml").firstChild;
                buff = buff.slice(close_index+1);
                checked = 0;
                cb(frame);
                return separate_events();
            }
            name = buff.slice(1,close_index);
            var s = name.indexOf(" ");
            if (s != -1) {
                name = name.slice(0,s);
            }
            checked = close_index+1;
        }
        var i = buff.indexOf(">", checked);
        while (i != -1) {
            if (buff.slice(i-2-name.length,i+1) == "</"+name+">") {
                var frame = parser.parseFromString(buff.slice(0, i+1), "text/xml").firstChild;
                buff = buff.slice(i+1);
                checked = 0;
                name = null;
                cb(frame);
                return separate_events();
            }
            else {
                checked = i+1;
                i = buff.indexOf(">", checked);
            }
        }
    }
    self.set_cb = function(func) {
        cb = func;
    }
    self.read = function(data) {
        buff += data;
        separate_events();
    }
}

Rafina.JSONReader = function() {
    var chars = {'[':']','{':'}','"':'"'};
    var self = this;
    var cb = null;
    var unclosed = [];
    var buff = "";
    var checked = 0;
    var separate_events = function() {
        while (buff.length > checked) {
            if (unclosed.length > 0 && buff.charAt(checked) == unclosed[unclosed.length-1]) {
                unclosed.pop();
            }
            else if (buff.charAt(checked) in chars) {
                unclosed.push(chars[buff.charAt(checked)]);
            }
            checked += 1;
            if (buff && unclosed.length == 0) {
                cb(eval("("+buff.slice(0,checked)+")"));
                buff = buff.slice(checked);
                checked = 0;
            }
        }
    }
    self.set_cb = function(func) {
        cb = func;
    }
    self.read = function(data) {
        buff += data;
        separate_events();
    }
}
