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;
            }
        }
    };
	
    /*
     * expects inputdata to contain following properties
     * action
     * data (list of items)
     * 		data list of raw values for each experiment
     * 		dbid
     * 		id (from input data)
     * datanames : name of each experiment
     * max : max value mapped to this pathway
     * min : min value mapped to this pathway
     */
    this.expressionCallback = function(inputdata) {     
    	
        var spectrumLength = this.colourSpectrum.length;
        //var expressionData = eval('(' + inputdata + ')');
        var expressionData = getJsonFromRawText(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.datanames && expressionData.datanames.length > 0){
        	//this.columnNames = eval(expressionData.datanames);
        	this.columnNames = getJsonFromRawText(expressionData.datanames);
        	this.columnCount = this.columnNames.length;
        }
        /*
         * Map each data point to a point in the colour spectrum. Store in dataColours
         */
        if(expressionData.data.length>0){
        	this.dataColours = expressionData.data;
        	this.maxValue 	= parseFloat(expressionData.max);
        	this.minValue 	= parseFloat(expressionData.min);
        	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 max value found, set the index to 0. This is necessary because where the data value is eqaul to the maximum
        			 * the index evaluates to between -1 and 0. The index is used to map data values to points in the colour spectrum -
        			 * the raw data value is not affected.
        			 */
        			if(parseFloat(expressionData.data[i].data[j]).toFixed(2) == this.maxValue.toFixed(2)){
        				this.dataColours[i].data[j] = 0;
        			}else if(parseFloat(expressionData.data[i].data[j]).toFixed(2) == this.minValue.toFixed(2)){
	        			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')
            	}
            }
    };
    /*
     * Display colour spectrum mapping values to colours
     */
    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;
            /* Calculate max/min values */
     /*       $("experimentmaxvalue").innerHTML=this.maxValue
            $("experimentmidvalue").innerHTML=this.midValue;
            $("experimentminvalue").innerHTML=this.minValue;*/
            /* End calculate max/min values */
            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";

    };
};

