ExpressionPainter = function() {
    this.colourSpectrum = new Array();
    this.index = 0;
    this.columnNames = null;
    this.data = null;
   
    this.maxValue = null;
    this.midValue = null;
    this.minValue = null;
    this.columnCount = null;
    this.refIdMapping = null;
    
	// colourInc determines gradients across the RGB spectrum i.e. start with 255,0,0
    // then 255,15,0 then 255,30,0 etc
    this.init = function(colourInc) {
        var red = 255;
        var green = 0;
        var blue = 0;
        var colorInc = 15;
        this.colourSpectrum = new Array();
        for ( var i = 0; i < 500; i++) {
            this.colourSpectrum[i] = {
                "rgb" : [ red, green, blue ]
            };
            if (red <= 0 && green <= 0 && blue >= 255) {
                break;
            }
            if (red >= 255 && green < 255) {
                green += colorInc;
            }
            if (green >= 255 && red > 0) {
                red -= colorInc;
            }
            if (blue >= 255 && green > 0) {
                green -= colorInc;
            }
            if (red <= 0 && blue < 255) {
                blue += colorInc;
            }
        }
    };
	
    this.expressionCallback = function(inputdata) {     
    	
        var spectrumLength = this.colourSpectrum.length;
        var expressionData = eval('(' + inputdata + ')');
        // Mark this for memory deallocation
        inputdata = null;
        this.refIdMapping = new Object();
        this.data = new Array();
        for(var t=0; t<expressionData.data.length; t++){
        	var row = new Object();
        	row.data = expressionData.data[t].data.slice();
        	row.id = expressionData.data[t].id;
        	row.dbid = expressionData.data[t].dbid;
        	this.data[t] = row;
        	
        	// Set this up so we can check for a match based on id instead of
        	// iterating through list.
        	this.refIdMapping[row.dbid] = row;
            //this.data[t] = expressionData.data[t].row.slice();
        }       
        if(expressionData.data.length>0){
        this.columnCount = expressionData.data[0].data.length;
        this.dataColours = expressionData.data;
        this.maxValue = parseFloat(expressionData.max);
        this.minValue = parseFloat(expressionData.min);
        this.columnNames = eval(expressionData.datanames);
        var maxmindiff = this.maxValue - this.minValue;        
        for ( var i = 0; i < expressionData.data.length; i++) {
            for ( var j = 0; j < expressionData.data[i].data.length; j++) {
		if(expressionData.data[i].data[j] == this.maxValue){
			this.dataColours[i].data[j] = 0;

		}else if(expressionData.data[i].data[j] == this.minValue){
			this.dataColours[i].data[j] = spectrumLength-1;
		}else  {
                	this.dataColours[i].data[j] = parseInt((spectrumLength-1) - (((expressionData.data[i].data[j]-this.minValue)/(this.maxValue-this.minValue)) * spectrumLength));
		}

                this.refIdMapping[expressionData.data[i].dbid].dataColours = 
                	this.dataColours[i];
            }
        }
        
        if(this.minValue != null && this.maxValue != null){
            this.midValue = ((this.maxValue - this.minValue)/2)+this.minValue;
            this.minValue = this.minValue.toFixed(2);
            this.maxValue = this.maxValue.toFixed(2);
            this.midValue = this.midValue.toFixed(2);
        }
        }
    };
    this.expressionCallback.bind(this);
    this.iterate =  function(){
        var colour = this.colourSpectrum[this.index];
        this.index = (this.index++)%this.colourSpectrum.length;
        return colour;
    };

    this.clearSpectrum = function(){
        $("experimentkey").getElementsBySelector('div.keyspectrumtip').invoke('remove');
    };
    this.setExpressionVisibility = function(visibility){
            $("experimentbrowser").style.visibility=visibility;
            $("experimentkey").style.visibility=visibility;
            $("experimentmaxvalue").style.visibility=visibility;
            $("experimentmidvalue").style.visibility=visibility;
            $("experimentminvalue").style.visibility=visibility;
            
            // If hiding the expression painter, remove the complex popup.
            if(visibility == "hidden"){
            	var canvasoverlay = $("canvasoverlay");
            	var cplxcompstip = 0;
            	if(canvasoverlay){
            		cplxcompstip = canvasoverlay.getElementsBySelector( 'div.cplxcompstip');
            	}
            	if(cplxcompstip != 0){
            	cplxcompstip.invoke('remove')
            	}
            }
    };
    this.displayKey = function(scale){
        $("experimentkey").style.visibility="visible";

        var browser = navigator.appName;
		var version = navigator.appVersion;

        var expressionspectrumtip =
        $("experimentkey").getElementsBySelector('div.keyspectrumtip');
        //$("experimentmaxvalue").innerHTML= "44";
        var array = $A(expressionspectrumtip);
        if(array.length == 0){
            var length = this.colourSpectrum.length;
            var availableheight = (YAHOO.util.Dom.getViewportHeight() * 0.6)
                - (0.05 * YAHOO.util.Dom.getViewportHeight());
            // Do some scaling to accommodate range of different display resolutions.
            var cellheight = availableheight/length;
 
            $("experimentmaxvalue").innerHTML=this.maxValue
            $("experimentmidvalue").innerHTML=this.midValue;
            $("experimentminvalue").innerHTML=this.minValue;
            for(var i=0; i<length;i++){
                //var cellwrapper = Element.extend(document.createElement('div'));
                expressionspectrumtip = Element.extend(document
                    .createElement('div'));
                expressionspectrumtip.className = 'keyspectrumtip';
                expressionspectrumtip.id="expspectip"+i;
		var spectipheight = Math.round(cellheight*scale);
		if(scale < 1) height = 3;
		else height = 5;
                expressionspectrumtip.setStyle({
                    height: (height) + "px",
                    width: 36 + "px",
                    background: 'rgb('
                    + this.colourSpectrum[i].rgb[0]
                    + ',' + this.colourSpectrum[i].rgb[1]
                    + ',' + this.colourSpectrum[i].rgb[2] + ')'
                });
        		// Set to workaround IE problem which sets empty div elements to minimum size
        		if(browser == "Microsoft Internet Explorer"){
        		expressionspectrumtip.setStyle({
        			fontSize : "1px",
        			lineheight:0
        			}
        			);
        		expressionspectrumtip.innerHTML = "&nbsp";

        		}

                $("experimentkey").appendChild(expressionspectrumtip);   
		
            }

   var midtip = Math.round((length/2)-1);
   var tipname = "expspectip" + midtip;
   var t = $(tipname).offsetTop;
   $("experimentmidvalue").style.top = t+"px";
   var bottomtip = length-1;
   tipname = "expspectip" + bottomtip;
	$("experimentminvalue").style.top = ($(tipname).offsetTop-10)+"px";


        }
        $("experimentmaxvalue").style.visibility="visible";
        $("experimentmidvalue").style.visibility="visible";
        $("experimentminvalue").style.visibility="visible";

    };
};
