var Sequence = Class.create();
Sequence.prototype = {
    
    

    initialize: function(object_id, feature_id, feature_type, flip, begin, end, post_work_func) {
        this.object_id = object_id
        this.feature_id = feature_id
        this.feature_type = feature_type
        this.flip = flip
        this.begin = begin
        this.end = end
        this.colors = {
            'N': '#CCCCCC',
            'A': '#00FF00',
            'C': '#0000FF',
            'G': '#FFA500',
            'T': '#FF0000'
        }
        this.post_work_func = post_work_func || function() {}
        this.loadSequences()
    },

    warName: function(){
        var path=location.pathname;
        var a=path.split("/");
        return '/'+a[1];
    },

    loadSequences: function() {
        new Ajax.ULRequest(this.warName()+'/gene/sequence/'+this.feature_id+'?includerepeats&begin=' + this.begin + "&end=" + this.end, {
            method: 'get',
            onLoading:function(request){Element.show('sequence_loading')},
            onComplete:function(request){window.setTimeout('Element.hide("sequence_loading");', 100);},
            onSuccess: this.renderSequences.bind(this)
        });
    },

    renderSequences: function(transport) {
        var sequences_with_repeats = eval("(" + transport.responseText + ")");
        var sequences = sequences_with_repeats[0]
        var repeats = sequences_with_repeats[1]
        var primary_feature_index = Math.floor(sequences.length/2)
        var runner = 0;
        var nucleotides = "";
        var current_span = 0
        var targetNode = Builder.node("span",{className:'interstitial unmasked'})
        var begin_by_end = new Hash()
        var default_pad_size = 200;
        var postpadding_start = sequences.length - default_pad_size;

        for( var i=0; i<sequences.length; i++) {
            var building_repeat_node = false
            runner++;
            var sequence = sequences[i]

            if(repeats[i]!=undefined) {
                nucleotides = this.dump_nucleotides(targetNode, nucleotides)
                current_span = this.dump_node(current_span, targetNode)
                targetNode = Builder.node("span",{className:'repeatSequenceBegin unmasked'})
                begin_by_end.set(repeats[i], targetNode)
                building_repeat_node = true
            }
      	    
            if(i==postpadding_start || i==default_pad_size)
            {
              if(!building_repeat_node)
              {
                nucleotides = this.dump_nucleotides(targetNode, nucleotides)
                current_span = this.dump_node(current_span, targetNode)
                targetNode = Builder.node("span",{className:'interstitial unmasked'})
              }
            }

            if(begin_by_end.get(i)!=undefined) {
                nucleotides = this.dump_nucleotides(targetNode, nucleotides)
                current_span = this.dump_node(current_span, targetNode)
                targetNode = Builder.node("span",{className:'repeatSequenceEnd unmasked'})
                var begin_node = begin_by_end.unset(i)
                Event.observe(targetNode, "click", this.onRepeatClick.bindAsEventListener(this, begin_node, targetNode));
                Event.observe(begin_node, "click", this.onRepeatClick.bindAsEventListener(this, begin_node, targetNode));
                building_repeat_node = true
            }
            var newNode
            if(sequence.primary!=undefined && this.feature_type=='polymorphism') { //FIX THIS
                nucleotides = this.dump_nucleotides(targetNode, nucleotides)
                newNode = Builder.node('span', {className:'primarySequence', title:sequence.primary.join('/')}, "[" + sequence.primary.join('/') + "]");
                targetNode.appendChild(Builder.node('br'));
                targetNode.appendChild(newNode);
                targetNode.appendChild(Builder.node('br'));
                runner = 0;
            }
            else if(sequence.length == 1) {
                nucleotides += sequence
            }
            else {
                nucleotides = this.dump_nucleotides(targetNode, nucleotides)
                var id;
                if(this.flip) {
                    id = 'sequence_'+(this.end-i)+'_'+sequence.x.join(',')
                }
                else {
                    id = 'sequence_'+(this.begin+i)+'_'+sequence.x.join(',')
                }

                newNode = Builder.node('span', {id:id, className:'aSequence_masked', title:sequence.x.sort().join('/')}, 'N');
                Event.observe(newNode, "click", this.onClick.bindAsEventListener(this, newNode, sequence.x, sequence.object_id));

                targetNode.appendChild(newNode);
            }

            if(i < default_pad_size)
            {  
              Element.addClassName(targetNode, 'prepadding')
            }
	
            if(i >= postpadding_start)
            {
            	Element.addClassName(targetNode, 'postpadding')
            }

            if(building_repeat_node) {
                nucleotides = this.dump_nucleotides(targetNode, nucleotides)
                current_span = this.dump_node(current_span, targetNode)
                targetNode = Builder.node("span",{className:'interstitial unmasked'})
            }

            if(runner % 10 == 0) {
                nucleotides += " "
            }
        }
	
        nucleotides = this.dump_nucleotides(targetNode, nucleotides)
        this.dump_node(current_span, targetNode)
    
        $$('#masked_sequences SPAN.aSequence_masked').each(function(f){this.changeTextColor(f)}.bind(this))

        if(this.feature_type=='polymorphism'){
            new Effect.Appear('sequence_container')
        }
        this.post_work_func()
    },

    onClick: function(event, node, sequence, polymorphism_id ) {
        var container = $('mask_popup')
        $('mask_popup_data').update('')

        container.style.left =(Event.pointerX(event) + 5) + 'px'
        container.style.top = (Event.pointerY(event) + 5) + 'px'
        container.style.zIndex = '2000'
        var masks = Builder.node('ul', {className:'polymorphism_alleles'})
        masks.appendChild(this.buildMaskHTML(node, 'Masked', 'N'))

        sequence.each(function(sequence){masks.appendChild(this.buildMaskHTML(node, sequence, sequence))}.bind(this));

        $('mask_popup_data').appendChild(masks)

        new Ajax.Request(this.warName()+'/gene/polymorphism/' + polymorphism_id, {
            method: 'get',
            onLoading: function(){},
            onComplete: function(){},
            onSuccess: this.renderPolymorphismInfo.bind(this)
        });

        new Effect.Appear(container)
        return false;
    },

    onRepeatClick: function(event, begin_Node, end_Node) {
        var start = this.getRepeatingSpanNumber(begin_Node.up().id)
        var end = this.getRepeatingSpanNumber(end_Node.up().id)
        for(var i = start; i<=end; i++) {
            var span_id = "repeatSpan_"+i
            $$('span#'+span_id).each(function(span){
                children = span.childElements()
                unmasked = children[0];
                masked = children[1];
                masked.innerHTML = unmasked.innerHTML.stripTags().gsub(/\w/,'N')
                span.className='repeatSpan masked'
            })
        }
    },

    onMaskedClick: function(event) {
        $$('span.repeatSpan.masked').each(function(span){
            children = span.childElements()
            unmasked = children[0];
            masked = children[1];
            masked.innerHTML = "";
            span.className='repeatSpan unmasked'
        })
    },

    getRepeatingSpanNumber: function(id) {
        return parseInt(id.match(/repeatSpan_(\d+)/)[1])
    },
    
    dump_node: function(current_span, unmasked_node) {
        if(!unmasked_node.innerHTML.blank()) {
            current_span += 1
            repeatSpan = Builder.node('span',{className: 'repeatSpan unmasked', id: 'repeatSpan_'+current_span})
            repeatSpan.appendChild(unmasked_node)
            masked_node = Builder.node('span',{className: 'masked'})
            Event.observe(masked_node, "click", this.onMaskedClick.bindAsEventListener(this));
            repeatSpan.appendChild(masked_node)

            $('masked_sequences').appendChild(repeatSpan)
        }
        return current_span
    },

    dump_nucleotides: function(node, nucleotides) {
        if(nucleotides.length > 0) {
            node.appendChild(document.createTextNode(nucleotides))
            nucleotides = ""
        }
        return nucleotides
    },

    changeTextColor: function(node) {
        var val = node.innerHTML
        node.style.backgroundColor = this.colors[val]
    },

    buildMaskHTML: function(node, mask_text, value) {
        var context = Builder.node('li', {}, [Builder.node('a', {href:'#'}, mask_text)]);
        context.firstChild.onclick = function(){
            this.setMask(node, value)
            return false
        }.bind(this)
        return context;
    },

    setMask: function(node, value) {
        node.innerHTML = value
        this.changeTextColor(node)
    },

    renderPolymorphismInfo: function(transport) {
        var data = eval("(" + transport.responseText + ")");
        this.polymorphism = new Polymorphism(data, null);
        this.polymorphism.render($('mask_popup_data'));
    },

    getQueryString: function() {
        var repeat_spans = $$('span.repeatSpan');
        return repeat_spans.inject("",function(memo, repeat_span) {
            var displayed_inner_span = repeat_span.childElements()[repeat_span.hasClassName('masked') ? 1 : 0];
            return memo + displayed_inner_span.innerHTML.stripTags();//.gsub(/\s/,'')
        });
    }
}