var FeatureBrowser = Class.create();
FeatureBrowser.prototype = {
    initialize: function(feature_id, element) {
        this.begin_index = 0;
        this.end_index = 0;
        this.gene_length = 0;
        this.ratio = 0;
        this.initialStartPosition = 0;
        this.initialEndPosition = 0;
        this.feature_id = feature_id
        this.feature_start=0;
        this.feature_end=0;
        

        var options = Object.extend({
            showAll: false,
            maxZoom: 125
        }, arguments[2] || {});

        var _browser = this;
        this.select_region = new SelectRegion(element, {
            onDrag: function(region){
                _browser.handleDrag(region)
                },
            onComplete:function(region){
                _browser.loadSelectedRegion(region)
                }
        });
        this.offset = Position.cumulativeOffset($('gene'));
        this.maxZoom = options.maxZoom;
        this.showAll = options.showAll;

        //private methods
        this.featuresInRange = function(begin,end) {
            return this.features.select(function(feature) { 
                return feature.inRange(begin,end)
            })
        }
    },

    clear: function (node) {
        node.update('');
    },

    canIncrement: function() {
        return this.end_index < this.initialEndPosition;
    },

    canDecrement: function() {
        return this.begin_index > this.initialStartPosition;
    },

    canZoom: function() {
        return this.begin_index > this.initialStartPosition ||
        this.end_index < this.initialEndPosition;
    },

    redraw: function() {
        this.backgroundTask(function(_browser) {
            _browser.render(_browser.begin_index, _browser.end_index);
        });
    },

    increment: function() {
        this.backgroundTask(function(_browser) {
            var diff = _browser.end_index-_browser.begin_index
            _browser.render(_browser.begin_index+diff, _browser.end_index+diff);
        });
    },

    decrement: function() {
        this.backgroundTask(function(_browser) {
            var diff = _browser.end_index-_browser.begin_index;
            _browser.render(_browser.begin_index-diff, _browser.end_index-diff);
        });
    },

    zoomOut: function() {
        this.backgroundTask(function(_browser) {
            var diff = _browser.end_index-_browser.begin_index;
            _browser.render(
                Math.max(_browser.begin_index-diff, _browser.initialStartPosition),
                Math.min(_browser.end_index+diff, _browser.initialEndPosition)
                );
        });
    },

    loadSelectedRegion: function(region)
    {
        var r = Object.clone(region);
        this.backgroundTask(function(_browser) {
            var points = _browser.translate(r);
            _browser.render(points[0], points[1]);
        });
    },

    backgroundTask: function(task) {
        Element.show('loading');
        setTimeout(function() {
            task(this);
            Element.hide('loading');
        }.bind(this), 100);
    },

    load: function(begin,end) {
       
        
        var uri =this.warName()+'/gene/data/' + this.feature_id + "?all=" + this.showAll;

        new Ajax.ULRequest(uri, {
            method: 'get',
            onSuccess: this.process.bind(this)
        });
    },

    warName: function(){
        var path=location.pathname;
        var a=path.split("/");
        return '/'+a[1];
    },
    
    createRow: function(feature, featureDisplayGroups) {
        var row = Builder.node('tr', {
            id:feature.feature_id,
            className:'features'
        });

        var column = Builder.node('td');

        if(feature.feature_type == 'polymorphism' && feature.object_id != this.object_id) {
            var link = Builder.node('a', {
                href:'#',
                className:'showInfo'
            }, '+');
            column.appendChild(link);
            feature.handleClick(link);      
        }
        else {
            column.innerHTML = '';  
        }
        row.appendChild(column);    

        //build the gutter for the 'n' display groups    
        for(var i=0; i<this.displayGroups.length; i++) {
            var displayGroup = this.displayGroups[i];
            if(displayGroup.group != 'polymorphism') {
                var gutter = Builder.node('td', {
                    className:'gutter',
                    title:displayGroup.group
                    }, "");
                if(featureDisplayGroups.indexOf(displayGroup.group) >= 0) {
                    gutter.style.backgroundImage = 'url('+this.warName()+'/images/'+feature.color()+'_horizontal.gif)';  
                   
                }
                if(feature.parent) {
                    for(var j=0; j<feature.parent.length; j++) {
                        var x = feature.parent[j];
                        var a_feature = x[0];
                        var a_groups = x[1]
                        if(a_groups.indexOf(displayGroup.group) >= 0) {
                            gutter.style.backgroundImage = 'url('+this.warName()+'/images/'+a_feature.color()+'_horizontal.gif)';
                        }
                    }
                }
                row.appendChild(gutter);
            }
        }

        var dnd_indicator = Builder.node('img', {
            id: "ball_"+feature.feature_id,
            className: 'ball',
            src:this.warName()+'/images/ball.gif',
            alt:"Drag this to the cart",
            title:"Drag this to the cart"
        });
        dnd_indicator.style.display='none'
        row.appendChild(Builder.node('td', [dnd_indicator] ));

        row.appendChild(Builder.node('td', feature.feature_type ));
        //isPoint
        if(feature.feature_type=='polymorphism') {
            row.appendChild(Builder.node('td', feature.start_position + 1));
            row.appendChild(Builder.node('td', feature.alleles));
            if(feature.genotypCnt > 0) {
                row.appendChild(Builder.node('td', [Builder.node('a', {
                    href:this.warName()+'/genotype/genotypes/'+feature.object_id,
                    className:"genotypCnt",
                    target:"_blank"
                }, feature.genotypCnt)]));
            }
            else {
                row.appendChild(Builder.node('td', feature.genotypCnt));
            }
        }
        else {
            row.appendChild(Builder.node('td', feature.start_position + " -> " + feature.end_position));
            row.appendChild(Builder.node('td', ""));
            row.appendChild(Builder.node('td', ""));
        }

        row.appendChild(Builder.node('td', feature.feature_id));
        row.appendChild(Builder.node('td', feature.object_id));
        //isPoint
        if(feature.feature_type=='polymorphism'){
            if(!feature.polymorphism_alias){
                row.appendChild(Builder.node('td', ""));                          
            }else{         
                row.appendChild(Builder.node('td',feature.polymorphism_alias));  
            }
            row.appendChild(Builder.node('td', feature.orientation));
        
        }else{
            row.appendChild(Builder.node('td', ""));
            row.appendChild(Builder.node('td', ""));
        }
    
        return row;
    },

    process: function(transport) {
        var data = eval("(" + transport.responseText + ")");
        this.initialStartPosition = data.begin;
        this.initialEndPosition = data.end;
        this.features = new Array();

        this.feature_start=data.feature_start;
        this.feature_end=data.feature_end;
        
        this.orientation = data.orientation
        this.reference_name = data.reference_name
        this.reference_id = data.reference_id
        this.reference_type = data.reference_type
        this.object_id = data.object_id
        this.feature_type = data.feature_type
        this.flip = this.orientation == 'r'
        this.session_id=data.session_id
    
        var sorted_features = data.features.sort(function(a,b) {
            return a.start_position-b.start_position
            })

        //get the unique display groups
        //todo, can this be cleaned up?  We use uniqueDisplayGroups to determine if and where on the list
        this.uniqueDisplayGroups = new Array();
        this.displayGroups = new Array();
        for( var i=0; i<sorted_features.length; i++) {
            var feature = sorted_features[i];
            if(feature.displayGroup && this.uniqueDisplayGroups.indexOf(feature.displayGroup) == -1) {
                this.displayGroups.push({
                    version:feature.version,
                    group:feature.displayGroup,
                    offset:i,
                    geneSymbol:feature.geneSymbol,
                    orientation:feature.orientation
                    });
                this.uniqueDisplayGroups.push(feature.displayGroup);
            }
            feature.offset = this.uniqueDisplayGroups.indexOf(feature.displayGroup);
        }

        //build all the features
        for( var i=0; i<sorted_features.length; i++) {
            var feature = new Feature(this.object_id, this.flip, sorted_features[i])
            this.features.push(feature);

            //draw the minor allele frequencies
            //if(feature.object_id == this.object_id && this.feature_type=='polymorphism' && feature.genotypCnt > 0) {
            if(feature.object_id == this.object_id && this.feature_type=='polymorphism') {
            this.polymorphism = feature
                new Ajax.ULRequest(this.warName()+'/gene/polymorphism/' + this.object_id, {
                    method: 'get',
                    onLoading: function() {},
                    onComplete: function() {},
                    onSuccess: this.renderPolymorphismInfo.bind(this)
                });
            }
        }

        if(this.feature_type=='polymorphism'){
            this.sequence = new Sequence(this.object_id, this.feature_id, this.feature_type, this.flip, this.initialStartPosition, this.initialEndPosition)
        }
    
        var coordinates = window.location.hash
        if(coordinates.match(/#(\d+),(\d+)$/)) {
            this.render(RegExp.$1, RegExp.$2);
        } else {
            this.render(this.initialStartPosition, this.initialEndPosition);
        }
    },

    renderCartoonSequences: function(transport) {
        var sequences = eval("(" + transport.responseText + ")");
        var sequenceContainer = $('sequence');

        //TODO: one too many on the front (alignment was off)?
        for( var i=1; i<sequences.length; i++) {
            var sequence = sequences[i];
            if(sequence.length == 1) {
                this.renderSequence(sequenceContainer, sequence, 0, i);
            }
            else {
                if(sequence.x!=undefined){
                    for(var j=0; j<sequence.x.length; j++) {
                        this.renderSequence(sequenceContainer, sequence.x[j], j*10, i);
                    }
                }
                else{
                    for(var j=0; j<sequence.primary.length; j++) {
                        this.renderSequence(sequenceContainer, sequence.primary[j], j*10, i);
                    }
                }
            }
        }
    },

    renderSequence:function(sequenceContainer, sequence, height, index) {
        var newNode = Builder.node('div', {
            className:'cartoonSequence'
        }, sequence);
        newNode.style.top = ((-20) - height) + 'px';
        newNode.style.left=(this.ratio * (index-1))  + 'px';
        newNode.style.width=this.ratio + 'px';
        sequenceContainer.appendChild(newNode);
    },

    render: function(begin,end) {
        var list = $('data');
        var list_head = $('data_head');
        var gene = $('gene');
        var drawCartoonSequences = false;
        this.clear(list); this.clear(list_head); this.clear(gene); this.clear($('sequence')); Element.hide('pointer');

        //Expand the container to fit all the display groups
        var scaffold_height=40;
        var offset = 40
        $('gene_line_container').style.height = (offset + scaffold_height * this.displayGroups.length) + 'px';
        $('container').style.height = (offset + scaffold_height * this.displayGroups.length) + 'px';

        var width=$('gene_line_container').getWidth() - 30;
    
        for(var j=0; j<6; j++) {
            var image_name = (this.orientation == 'f') ? 'sqn_arrow_right.gif' : 'sqn_arrow_left.gif'
            var arrow = Builder.node('img', {
                className:'arrow',
                src:this.warName()+'/images/'+image_name
                });
            arrow.style.top='10px';
            arrow.style.left=((j * (width/6)) + (width/(11*6))) + 20  + 'px';
            gene.appendChild(arrow);
            var text = Builder.node('span', {
                className:'reference_name'
            }, this.reference_name)
            text.style.top='-5px';
            text.style.left=((j * (width/6)) + (width/(11*6)))  + 'px';  
            gene.appendChild(text);
        }

        if(Math.round(end)-Math.round(begin) <= this.maxZoom ) {
            var delta = (this.maxZoom - (end-begin))/2;
            this.begin_index = Math.round(begin) - Math.round(delta)
            this.end_index = Math.round(end) + Math.round(delta)
            drawCartoonSequences = true
        }
        else {
            this.begin_index = Math.round(begin)
            this.end_index = Math.round(end)
        }

        this.gene_length = this.end_index - this.begin_index;
        this.ratio = width/this.gene_length;
    
        var parameters;
        var servletType;
        if(this.warName()=='/FeatureBrowser'){
            servletType='Public';
        }else{
            servletType='Private';
        }
        if(this.object_id>0)
            parameters='http://cgemm-test.louisville.edu/DragDropServlet'+servletType+'/NeighboringFeatures?feature_id='+this.feature_id+'&window_start='+Math.round(begin)+'&window_end='+Math.round(end)+'&session_id='+this.session_id;
        else
            parameters='http://cgemm-test.louisville.edu/DragDropServlet'+servletType+'/NeighboringFeatures?feature_start='+Math.round(this.feature_start)+'&feature_end='+Math.round(this.feature_end)+'&reference_id='+this.reference_id+'&orientation='+this.orientation+'&session_id='+this.session_id+'&window_start='+Math.round(begin)+'&window_end='+Math.round(end);
        var element=document.getElementById("neighboring_features");
        element.setAttribute('href',parameters);
        element.setAttribute('target','_blank');
        
        
        //add the gene 'scaffold'
        for(var i=0; i<this.displayGroups.length; i++) {
            var displayGroup = this.displayGroups[i];
      
            var image = Builder.node('img', {
                src:this.warName()+'/images/black.gif',
                className:'scaffold'
            });
            image.style.top=((i * scaffold_height + offset)) + 'px';
            gene.appendChild(image);

            //place 'arrow_count' arrows along the scaffold denoting orientation
            if(displayGroup.group != 'polymorphism') {
                var arrow_count=10;
                for(var j=0; j<arrow_count; j++) {
                    var image_name = (displayGroup.orientation == this.orientation) ? 'arrow_right.gif' : 'arrow_left.gif'
                    var arrow = Builder.node('img', {
                        className:'arrow',
                        src:this.warName()+'/images/'+image_name
                        });
                    arrow.style.top=((i * scaffold_height + offset)-3) + 'px';
                    arrow.style.left=((j * (width/arrow_count)) + (width/(arrow_count*2)))  + 'px';
                    gene.appendChild(arrow);
                }
            }

            
            if((displayGroup.geneSymbol)||(displayGroup.group=='Region of Interest')) {
                var create_amplicons = Builder.node('div', {
                    className: 'amplicons'
                })
                create_amplicons.style.position = 'absolute'
                create_amplicons.style.top=((i * scaffold_height + offset)+15) + 'px';
                create_amplicons.style.left="10px"
                displayGroup.index = i
                var img = Builder.node('img', {
                    id: "amplicons_"+displayGroup.group,
                    src:this.warName()+'/images/triangle.gif',
                    alt:"Create amplicons for " + displayGroup.geneSymbol,
                    title:"Create amplicons for " + displayGroup.geneSymbol
                    });
                var ul = Builder.node('ul')

                var set_design_parameters = Builder.node('a', {
                    href: '#'
                })
                set_design_parameters.innerHTML = '&#187; Set Design Parameters'
                var display_amplicons_link = Builder.node('a', {
                    href: '#'
                })
                display_amplicons_link.innerHTML = '&#187; Generate Amplicons'
                var design_all_link = Builder.node('a', {
                    href: '#'
                })
                design_all_link.innerHTML = '&#187; Design Assays'
                var export_assays = Builder.node('a', {
                    href: '#'
                })
                //export_assays.innerHTML = '&#187; Export Assays'
                var persist_assays = Builder.node('a', {
                    href: '#'
                })
                //persist_assays.innerHTML = '&#187; Save Assays'

                ul.appendChild(Builder.node('li', {}, [set_design_parameters]))
                ul.appendChild(Builder.node('li', {}, [display_amplicons_link]))
                ul.appendChild(Builder.node('li', {}, [design_all_link]))
                ul.appendChild(Builder.node('li', {}, [export_assays]))
                ul.appendChild(Builder.node('li', {}, [persist_assays]))
                create_amplicons.appendChild(img) //remove this line to make generate amplicon go away **********
                create_amplicons.appendChild(ul)
                $('container').appendChild(create_amplicons);
                Event.observe(img, "click", function(event) {
                    $$("div.sfhover").each(function(element) {
                        Element.removeClassName(element, "sfhover")
                        });
                    Element.addClassName(this, "sfhover")
                    Event.observe(this, 'mouseout',function(event){
                        if(!Position.within(this,Event.pointerX(event),Event.pointerY(event))) {
                            Element.removeClassName(this, "sfhover")
                            }
                        }.bind(this))
                }.bind(create_amplicons))

                Event.observe(set_design_parameters,
                    "click",
                    this.set_design_parameters.bindAsEventListener(this, create_amplicons, displayGroup))

                Event.observe(design_all_link,
                    "click",
                    this.design_all.bindAsEventListener(this, create_amplicons, displayGroup))

                Event.observe(display_amplicons_link,
                    "click",
                    this.amplicons.bindAsEventListener(this, create_amplicons, displayGroup))

                Event.observe(export_assays,
                    "click",
                    this.export_assays.bindAsEventListener(this, create_amplicons, displayGroup))

                Event.observe(persist_assays,
                    "click",
                    this.persist_assays.bindAsEventListener(this, create_amplicons, displayGroup))
            }
             
     
            var dnd_indicator = Builder.node('img', {
                id: "ball_"+displayGroup.group,
                className: 'features ball',
                src:this.warName()+'/images/ball.gif',
                alt:"Drag this to the cart",
                title:"Drag this to the cart"
            });
            dnd_indicator.style.display = 'none'
            dnd_indicator.style.position = 'absolute'
            dnd_indicator.style.top=((i * scaffold_height + offset)+15) + 'px';
            dnd_indicator.style.right="10px"
            $('container').appendChild(dnd_indicator);
      
            var labelString = displayGroup.geneSymbol ? displayGroup.geneSymbol +":" + displayGroup.group +"_"+displayGroup.version : displayGroup.group;
            var label = Builder.node('span', {
                className:'group_label'
            }, labelString);
            label.style.top=((i * scaffold_height + offset)+10) + 'px';
            gene.appendChild(label);
        }

        var sequences = new Array();

        //set the hash so this view can be bookmarked
        window.location.hash=this.begin_index + "," + this.end_index

        Element[this.canZoom() ? 'show' : 'hide']($('zoom'));
        Element[this.canIncrement() ? 'show' : 'hide']($('increment'));
        Element[this.canDecrement() ? 'show' : 'hide']($('decrement'));

        var features = this.featuresInRange(this.begin_index, this.end_index);
    
        $('begin').value = this.begin_index;
        $('end').value = this.end_index;
        $('info').innerHTML = 'Mouse over a feature...';
        $('count').innerHTML = features.length + " features in " + (this.end_index-this.begin_index) + " sequences in [" + this.begin_index + "," + this.end_index + "]";

        if(drawCartoonSequences) {
            new Ajax.ULRequest(this.warName()+'/gene/sequence/'+this.feature_id+'?begin=' + this.begin_index + "&end=" + this.end_index, {
                method: 'get',
                onSuccess: this.renderCartoonSequences.bind(this)
            });
        }

        list_head.appendChild(Builder.node('th', " "));
        for(var i=0; i<this.displayGroups.length; i++) {
            if(this.displayGroups[i].group != 'polymorphism') {
                list_head.appendChild(Builder.node('th', {
                    className:'gutter'
                }, ""));
            }
        }
        
        //red ball to denote you can drag and drop
        list_head.appendChild(Builder.node('th', " "));
        list_head.appendChild(Builder.node('th', "Feature Type"));
        list_head.appendChild(Builder.node('th', "Position"));
        list_head.appendChild(Builder.node('th', "Alleles"));
        list_head.appendChild(Builder.node('th', "Genotype Count"));
        list_head.appendChild(Builder.node('th', "Feature Id"));
        list_head.appendChild(Builder.node('th', "Object Id"));
        list_head.appendChild(Builder.node('th', "Alias"));
        list_head.appendChild(Builder.node('th', "Orientation"));


        //draw the cartoon
        features.each(function(feature) {
            feature.draw(gene, this.ratio, this.begin_index, this.end_index)
        }.bind(this))

        //collapse the table
        var collapsed = new Array();
        var index = new Array();
        for( var i=0; i<features.length; i++) {
            var feature = features[i];
            var key = feature.start_position + "," + feature.end_position + "," + feature.feature_type
            var unique_feature = collapsed[key];
            if(unique_feature == undefined) {
                unique_feature = collapsed[key] = new Array()
                unique_feature.push(feature)
                index.push(key)
            }
            unique_feature.push(feature.displayGroup)
        }

        var rows = new Array();
        for( var i=0; i<index.length; i++) {
            var feature = collapsed[index[i]][0]

            var groups = collapsed[index[i]].slice(1)

            //if a polymorphism, set display groups based on the parent
            //isPoint
            if(feature.feature_type=='polymorphism') {
                Object.extend(feature,{
                    parent: new Array()
                    });
                for( var j=0; j<index.length; j++) {
                    var test_feature = collapsed[index[j]][0]
                    var test_groups = collapsed[index[j]].slice(1)
                    if(test_feature != feature && !test_feature.isPoint() && feature.inRange(test_feature.start_position, test_feature.end_position)) {
                        feature.parent.push([test_feature, test_groups])
                    }
                }
            }

            var row = this.createRow(feature, groups);
            rows.push(row);
        }

        if(this.flip) { 
            rows.reverse();
        }
    
        rows.each(function(row){ 
            list.appendChild(row)
            })
        var newHeight = rows.length * 12;
        if(newHeight < 350)
        {
            $('data').style.overflow = 'visible';
            $('data').style.height = newHeight + "px";
        }
        ZebraTable.stripe('data_table');
    
    },

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

    handleDrag: function(region) {
        var points = this.translate(region);
        var begin = Math.round(points[0]);
        var end = Math.round(points[1]);

        $('begin').value = begin;
        $('end').value = end;

        var features = this.featuresInRange(this.begin_index,this.end_index);
        for( var i=0; i<features.length; i++) {
            var feature = features[i];
            if(feature.inRange(begin,end)) {
                if (navigator.appVersion.match(/\bMSIE\b/)) {
                    $(''+feature.feature_id).disabled = false;
                } else {
                    Element.removeClassName(''+feature.feature_id,"transparent");
                }
            }
            else {
                if (navigator.appVersion.match(/\bMSIE\b/)) {
                    $(''+feature.feature_id).disabled = true;
                } else {
                    Element.addClassName(''+feature.feature_id,"transparent");
                }
            }
        }
    },

    find_feature: function(feature_id) {
        var feature_id_in = Number(feature_id)
        return this.features.find(function(feature){
            return feature.feature_id == feature_id_in
            })
    },
  
    translate: function(region) {
        var relative_start = region.left() - this.offset[0];
        var relative_end = region.right() - this.offset[0];
        //back to real word coordinates
        var x1 = Math.round(this.begin_index) + (relative_start/this.ratio)
        var x2 = Math.round(this.begin_index) + (relative_end/this.ratio)
        if(this.flip) {
            var from_end = this.end_index-x1
            x1 = this.begin_index + from_end
            from_end = this.end_index-x2
            x2 = this.begin_index + from_end
            return [x2,x1]
        }
        else {
            return [x1,x2]
        }
    },

    buildPolymporphismQueryString: function() {
        return this.sequence.getQueryString()
    },

    /*  TODO: eventually this will return the feature ids that match the vendor and product */
    enablePurchase: function(data) {
        //clear the old selections
        $$('.ball').each(function(ele) {
            ele.style.display='none'      
        })
        Draggables.drags.each(function(d) {
            d.destroy()
            })

        if($('products').selectedIndex == 4 && this.feature_type=='polymorphism') {    //Assay Designxxx, Sequence is draggable
            $("ball_sequence").style.display=''
            new Draggable("ball_sequence", {
                revert:true,
                tag:'img',
                ghosting:true
            });
        } else if ($('products').selectedIndex == 3) {                                 //GT Assays, Highlight polymorphisms in the table
            this.featuresInRange(this.begin_index, this.end_index).select(function(feature) {
                return feature.feature_type == 'polymorphism'
                }).each(function(feature) {
                if(parseInt(feature.object_id) % 2 == 0) {
                    var row_id = ''+feature.feature_id
                    $("ball_"+feature.feature_id).style.display=''
                    new Draggable(row_id, {
                        revert:true,
                        tag:'tr',
                        ghosting:true
                    });
                }
            }.bind(this))
        } else {                                                                       //All others, highlight non-polymorphism transcript
            for(var j=0; j<this.displayGroups.length; j++) {
                var displayGroup = this.displayGroups[j];
                if(displayGroup.group != 'polymorphism') {
                    $("ball_"+displayGroup.group).style.display=''
                    new Draggable("ball_"+displayGroup.group, {
                        revert:true,
                        tag:'img',
                        ghosting:true
                    });
                }
            }
        }
    },

    set_design_parameters: function(e, _parent, displayGroup) {       
        Amplicons.set_design_parameters_popup()
    },

    amplicons: function(e, _parent, displayGroup) {
        if(Amplicons.primerSettings() != null) {
            Element.removeClassName(_parent, "sfhover")

            var amplicons = new Amplicons({
                displayGroup: displayGroup,
                flip: this.flip,
                feature_id: this.feature_id,
                feature_begin: this.initialStartPosition,
                feature_end: this.initialStartPosition,
                object_id: this.object_id,
                reference_id: this.reference_id,
                reference_type: this.reference_type,
                reference_name: this.reference_name,
                orientation: this.orientation,
                features: this.features.select(function(feature) { 
                    return feature.displayGroup == displayGroup.group
                })
            })
            amplicons.build()
            amplicons.draw($('gene'), this.ratio, this.begin_index, this.end_index)
            this.current_amplicons = amplicons
            return amplicons
        }
        else {
            alert('You must "Set Design Parameters" first')
        }
    },

    design_all: function(e, _parent, displayGroup) {
        if(Amplicons.primerSettings() != null) {
            var amplicons = this.amplicons(e, _parent, displayGroup)
            amplicons.design_all()
        }
        else {
            alert('You must "Set Design Parameters" first')
        }
      
      
    },

    //TODO: I think to handle multiple transcripts we will need to hold the current amplicons in a hash instead of globally
    export_assays: function(e, _parent, displayGroup) {
        if(this.current_amplicons) {
            this.current_amplicons.export_assays()
        }
        else {
            alert('You must "Generate Amplicons" or "Design Assays" first')
        }
    },

    persist_assays: function(e, _parent, displayGroup) {
        if(this.current_amplicons) {
            this.current_amplicons.persist()
        }
        else {
            alert('You must "Generate Amplicons" or "Design Assays" first')
        }      
    },

    enable_zoom:  function(enable) {
        this.select_region.enable_zoom(enable)
    }
}