Array.prototype.compare = function(testArr) {
    if (this.length != testArr.length) return false;
    for (var i = 0; i < testArr.length; i++) {
        if (this[i].compare) {
            if (!this[i].compare(testArr[i])) return false;
        }
        if (this[i] !== testArr[i]) return false;
    }
    return true;
}

Array.prototype.real_intersection = function(arr2){
    var self_sorted = this.sort();
    var target_sorted = arr2.sort();
    var intersection = new Array();
    var jstart = 0;
    
    for(var i = 0; i < self_sorted.length ; i++)
        for(var j = jstart; j < target_sorted.length ; j++)
            if(self_sorted[i] == target_sorted[j]){
                jstart = j + 1;
                intersection.push(self_sorted[i]);                
                break;
            }
    return intersection.sort();
}

Array.prototype.include = function(v){
    for(i=0; i< this.length; i++)
        if(this[i] == v)
            return true
    return false;
}

Array.prototype.size = function(){
    return this.length;
}
Array.prototype.index = function(v){
    for(i=0; i < this.length; i++)
        if(this[i] == v)
            return i
    return -1;
}


function Gene(genes){
    this.images = new Array();
    this.Alleles = new Array('b','B','a','AT','A','A+','w','W','g','G','cr','CR','d','D','ch','CH','f','F','z','Z','rn','RN','rb','RB','st','ST','to','TO','o','O','sp','SP','lp','LP', 'lk', 'LK')
    if(!genes){
        this.genes = new Array(this.Alleles.length);
        for(var i = 0; i < this.genes.length;i++)this.genes[i] = 0;
    }
    else this.genes = genes;
    this.ale = new Array();
    this.agouti = {
        'a' : 0,
        'AT' : 1,
        'A' : 2,
        'A+' : 3
    }
    this.diluted = new Array('CR');
    this.cream = new Array('CR','CR');
    this.dun = new Array('D');
    this.chestnut = new Array('b','b');
    this.champagne = new Array('CH');
    this.flaxen = new Array('f', 'f');
    this.dapple = new Array('Z');
    this.roan = new Array('RN');
    this.rabicano = new Array('RB');
    this.sooty = new Array('ST');
    this.tobiano = new Array('TO');
    this.overo = new Array('O');
    this.splashed = new Array('SP');
    this.leopard = new Array('LP');
    this.blanket = new Array('LK');
    this.white = new Array('W');
    this.gray = new Array('G');
    this.black = new Array('B');
    //	Agouti

    this.seal_brown = this.black.concat(['AT'])
    this.bay = this.black.concat(['A'])
    this.wild_bay = this.black.concat(['A+'])

    //Roan
    this.red_roan = this.chestnut.concat(this.roan)
    this.strawberry_roan = this.chestnut.concat(this.roan)
    this.blue_roan = this.black.concat(this.roan);
    this.bay_roan = this.bay.concat(this.roan);

    //Semi Cream
    this.palomino = this.chestnut.concat(this.diluted);
    this.smoky_black = this.black.concat(this.diluted);
    this.diluted_seal_brown = this.seal_brown.concat(this.diluted);
    this.buckskin = this.bay.concat(this.diluted);
    this.wild_buckskin = this.wild_bay.concat(this.diluted);

    //Dun
    this.red_dun = this.chestnut.concat(this.dun);
    this.grulla = this.black.concat(this.dun);
    this.brown_dun = this.seal_brown.concat(this.dun);
    this.classic_dun = this.bay.concat(this.dun);
    this.wild_dun = this.wild_bay.concat(this.dun);

    //	Dun + Semi Cream
    this.dunalino = this.palomino.concat(this.dun);
    this.smoky_grulla = this.smoky_black.concat(this.dun);
    this.dunskin = this.buckskin.concat(this.dun);
    this.wild_dunskin = this.wild_buckskin.concat(this.dun);

    //Dapple
    this.silver_dapple = this.black.concat(this.dapple);
    this.silver_dapple_brown = this.seal_brown.concat(this.dapple);
    this.silver_dapple_bay = this.bay.concat(this.dapple);
    this.silver_dapple_wild_bay = this.wild_bay.concat(this.dapple);

    //Dapple + dun
    this.silver_grulla = this.grulla.concat(this.dapple);
    this.silver_dapple_dun = this.brown_dun.concat(this.dapple);

    //Dapple + semi cream
    this.silver_dapple_buckskin = this.buckskin.concat(this.dapple);

    //Dapple + semi cream + dun
    this.silver_dapple_dunskin = this.dunskin.concat(this.dapple);

    //Cream
    this.cremello = this.chestnut.concat(this.cream);
    this.smoky_cream = this.black.concat(this.cream);
    this.seal_brown_cream = this.seal_brown.concat(this.cream);
    this.perlino = this.bay.concat(this.cream);
    this.wild_perlino = this.wild_bay.concat(this.cream);

    //Dun + Cream
    this.cream_grulla = this.smoky_cream.concat(this.dun);
    this.perlino_dun = this.perlino.concat(this.dun);
    this.wild_perlino_dun = this.wild_perlino.concat(this.dun);

    //	Champagne
    this.gold_champagne = this.chestnut.concat(this.champagne);
    this.classic_champagne = this.black.concat(this.champagne);
    this.sable_champagne = this.seal_brown.concat(this.champagne);
    this.amber_champagne = this.bay.concat(this.champagne);
    this.wild_amber_champagne = this.wild_bay.concat(this.champagne);

    // Champagne + semi cream
    this.gold_cream = this.palomino.concat(this.champagne);
    this.classic_cream = this.smoky_black.concat(this.champagne);
    this.sable_cream = this.sable_champagne.concat(this.diluted);
    this.amber_cream = this.buckskin.concat(this.champagne);
    this.wild_amber_cream = this.wild_buckskin.concat(this.champagne);

    //Flaxen
    this.flaxen_chestnut = this.chestnut.concat(this.flaxen);

    this.markings = new Array(
        'Pinto', this.overo.concat(this.tobiano),
        'Pinto', this.overo.concat(this.splashed),
        'Pinto', this.tobiano.concat(this.splashed),
        'Splashed White Pinto', this.splashed,
        'Overo Pinto', this.overo,
        'Tobiano Pinto', this.tobiano,
        'Appaloosa', this.leopard,
        'Appaloosa', this.blanket
        )

    this.marking_genes = new Array('RB', 'TO', 'O', 'SP', 'LP', 'LK');

    this.colors = [
    "White" , this.white,
    "Gray" , this.gray,

    "Amber Cream", this.wild_amber_cream,
    "Amber Cream", this.amber_cream,
    "Sable Cream", this.sable_cream,
    "Classic Cream", this.classic_cream,
    "Gold Cream", this.gold_cream,


    "Bay Roan", this.bay.concat(this.roan),
    "Bay Roan", this.wild_bay.concat(this.roan),
    "Bay Roan", this.seal_brown.concat(this.roan),
    "Strawberry Roan", this.strawberry_roan,
    "Blue Roan", this.blue_roan,
    

    "Amber Champagne", this.wild_amber_champagne,
    "Amber Champagne", this.amber_champagne,
    "Sable Champagne", this.sable_champagne,
    "Classic Champagne", this.classic_champagne,
    "Gold Champagne", this.gold_champagne,

    "Perlino Dun", this.wild_perlino_dun,
    "Perlino Dun", this.perlino_dun,


    "Perlino", this.wild_perlino,
    "Perlino", this.perlino,
    "Seal Brown Cream", this.seal_brown_cream,
    "Cream Grulla", this.cream_grulla,
    "Smoky Cream", this.smoky_cream,
    "Cremello", this.cremello,

    "Silver Dapple Dunskin", this.wild_dunskin.concat(this.dapple),
    "Silver Dapple Dunskin", this.silver_dapple_dunskin,

    "Silver Dapple Buckskin", this.wild_buckskin.concat(this.dapple),
    "Silver Dapple Buckskin", this.silver_dapple_buckskin,

    "Silver Dapple Dun", this.wild_dun.concat(this.dapple),
    "Silver Dapple Dun", this.classic_dun.concat(this.dapple),
    "Silver Dapple Dun", this.silver_dapple_dun,
    "Silver Grulla", this.silver_grulla,

    "Silver Dapple Bay", this.silver_dapple_wild_bay,
    "Silver Dapple Bay", this.silver_dapple_bay,
    "Silver Dapple Brown", this.silver_dapple_brown,
    "Silver Dapple", this.silver_dapple,

    "Dunskin", this.wild_dunskin,
    "Dunskin", this.dunskin,
    "Smoky Grulla", this.smoky_grulla,
    "Dunalino", this.dunalino,

    "Classic Dun", this.wild_dun,
    "Classic Dun", this.classic_dun,
    "Classic Dun", this.brown_dun,
    "Grulla", this.grulla,
    "Red Dun", this.red_dun,

    "Buckskin", this.wild_buckskin,
    "Buckskin", this.buckskin,
    "Diluted Seal Brown", this.diluted_seal_brown,

    "Smoky Black", this.smoky_black,
    "Palomino", this.palomino,



    "Silver Dapple Wild Bay", this.silver_dapple_wild_bay,
    "Wild Bay", this.wild_bay,
    "Silver Dapple Bay", this.silver_dapple_bay,
    "Bay", this.bay ,
    "Silver Dapple Brown", this.silver_dapple_brown,
    "Seal Brown", this.seal_brown,
    "Silver Dapple", this.silver_dapple,

    'Flaxen', this.flaxen_chestnut,
    "Black", this.black,
    "Chestnut", this.chestnut,
    ]
}

Gene.prototype.set = function(v){
    if(!v) v = 'Bb';
    
    this.ale = new Array();
    //v = parse_int(v) if v.is_a?(Numeric)

    

    var genes = v.indexOf(' ') != -1 ? v.split(' ') : this.split(v);
    
    for(var i = 0; i < parseInt(genes.length/2);i++){

        var start_char = genes[i*2].slice(0,1).toLowerCase();
        var start =  this.Alleles.index(genes[i*2].toLowerCase());
        if(start < 0)
            start = this.Alleles.index(start_char);
        
        if(start != 2){            
            if(start_char == genes[i*2].slice(0,1)){
                this.genes[start] = (genes[i*2].slice(0,1) == start_char) ? 0 : 1;
                this.genes[start + 1] = genes[i*2 + 1].slice(0,1) == start_char ? 0 : 1;                
            }
            else{
                
                this.genes[start + 1] = (genes[i*2].slice(0,1) == start_char) ? 0 : 1;
                this.genes[start ] = genes[i*2 + 1].slice(0,1) == start_char ? 0 : 1;
            }
        }
        else{
            var agouti_genes = genes.slice(i*2,i*2 + 2)
            
            
            var ind = 0
            this.genes[ind*2 + 3] = parseInt(this.agouti[agouti_genes[ind]]/2);
            this.genes[ind*2 + 2] = parseInt(this.agouti[agouti_genes[ind]]%2);
            ind = 1;
            this.genes[ind*2 + 3] = parseInt(this.agouti[agouti_genes[ind]]/2);
            this.genes[ind*2 + 2] = parseInt(this.agouti[agouti_genes[ind]]%2);

        }

    }
}

Gene.prototype.split = function(str){
    
    var ret = new Array();
    var tmp = '';
    
    var chars = ""
    if(str.join)
        chars = str.join('')
    else
        chars = str;
    
    var skip = false;
    
    for(var i=0;i < chars.length;i++){
        
        if(skip == true){
            skip = false;
            
        }else {
            //alert(chars.constructor)
            var c = chars.charAt(i);
            tmp+= c;
            
            if(this.Alleles.include(tmp)){
                if(c != 'A'){                    
                    ret.push(tmp);
                    tmp = ''
                }
                else{                    
                    if(chars.charAt(i+1) && ['T', '+'].include(chars.charAt(i+1).toUpperCase())){
                        ret.push(c + chars.charAt(i+1));
                        tmp = '';
                        skip = true;
                    }
                    else{
                        ret.push(tmp)
                        tmp = ''
                    }
                }
            }
        }
        
    }
 
    return	ret;
}

Gene.prototype.alleles = function(){

    if(this.ale.length > 0)
        return this.ale;
    for(var index = 0; index < parseInt(this.Alleles.length/2); index++){
        if(index == 1 || index == 2){
            var add = (index == 1 ? 2 : -2);
            
            switch(this.genes[index*2+1 + add]*2 + this.genes[index*2 + add]){
                case 0: this.ale.push('a');break
                case 1: this.ale.push('AT');break;
                case 2: this.ale.push('A');break;
                case 3: this.ale.push('A+');break;
            }
        }
        else {            
            this.ale.push((this.genes[index*2+1] == 0 ? this.Alleles[index*2] : this.Alleles[index*2 + 1]));            
            this.ale.push((this.genes[index*2] == 0 ? this.Alleles[index*2] : this.Alleles[index*2 + 1]));            
        }
    }
    return this.ale;
}

Gene.prototype.color = function(){
    this.alleles();
    var ale = new Array();
    for(var i = 0;i < this.ale.length;i++)
        ale.push(this.marking_genes.include(this.ale[i]) ? this.ale[i].toLowerCase() : this.ale[i])

    for(var i = 0; i < parseInt(this.colors.length/2); i++){
        var sl = this.colors.slice(i*2, i*2 + 2);
        
        var a = this.split(sl[1]);


        if(a.sort().compare(ale.real_intersection(a))){
            return sl[0]
        }
    }
    return "Chestnut"
}

Gene.prototype.init_display = function(alleles_div, image, color, output){
    this.image = document.getElementById(image);
    this.alleles_div = document.getElementById(alleles_div);
    this.color_holder = document.getElementById(color);
    this.alleles_output = document.getElementById(output)
    for(var i=0;i< this.Alleles.length/2 - 7; i++){
        if(i != 2)
            this.alleles_div.innerHTML+=('<div><a href="#" onclick="g.change(this);blur();return false">' + this.Alleles[i*2] + '</a> <a href="#" onclick="g.change(this);blur();return false">' + this.Alleles[i*2] + '</a></div>')
    }
}


Gene.prototype.show_image = function(){
    var c = this.color();
    this.alleles_output.innerHTML = "<b>Alleles</b>: " +  this.ale.slice(0,20).join(" ");
    var src = "/images/colors/" + c.toLowerCase() + "0.jpg";    
    this.color_holder.innerHTML = c;
    if(this.image.src != src){
        this.image.src = src;
    }
    
}

Gene.prototype.change = function(a){
    var text = new String(a.innerHTML);    
    if(text.toLowerCase().charAt(0) != 'a')
        a.innerHTML = (text.charAt(0) == text.toUpperCase().charAt(0) ? text.toLowerCase() : text.toUpperCase());
    else{
       a.innerHTML =  this.Alleles[2 + ((this.agouti[text]+1) % 4)]
    }
    var as = a.parentNode.getElementsByTagName("A")
    this.set(as[0].innerHTML + as[1].innerHTML);
    this.show_image();
}

fs_loadCSS("/v01/plugins/genetics_tool/css/genetics.css");

    var g = new Gene();    
    g.init_display("alleles", "image", "color", "alleles_output")
    g.show_image();  
