/**   1    
 * @fileoverview
 * This script defines a widget for interacting with expression data from flyatlas.
 * @author Jun Zhao
 * @version $Revision:124 $ on $Date: 2009-11-17 10:13:41 +0100 (Tue, 17 Nov 2009) $ by $Author: zhaoj $
 * @requires flykit.util
 * @requires flykit.sparql.Service
 * @requires flykit.flyatlas.Service
 * @requires YAHOO.util.Connect
 * @requires jQuery
 * @requires jQuery-ui
 * For license terms see http://code.google.com/p/open-biomed/
 */
 
flykit.namespace("flykit.flyatlas");
 
 
 
 
 

/*
 * ----------------------------------------------------------------
 *                             WIDGET
 * ----------------------------------------------------------------
 */







flykit.flyatlas.BatchWidget = function( service, renderer ) {
    var _context = "flykit.flyatlas.BatchWidget";
    try {
        
        flykit.debug("call private constructor", _context);
        this.__init__(service, renderer);
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
    
}



 
 



/** @private */
flykit.flyatlas.BatchWidget.prototype._controller = null;

/**
 * @private
 * @type flykit.mvcutils.GenericModel2
 */ 
flykit.flyatlas.BatchWidget.prototype._model = null;

/**
 * @private
 */
flykit.flyatlas.BatchWidget.prototype._renderer = null;

/**
 * @private
 */
flykit.flyatlas.BatchWidget.prototype._service = null;

/**
 * @private
 */ 
flykit.flyatlas.BatchWidget.prototype._geneSelectedEvent = null;







/**
 * @private
 */
flykit.flyatlas.BatchWidget.prototype.__init__ = function( service, renderer ) {
    var _context = "flykit.flyatlas.BatchWidget.prototype.__init__";
    try {
        
        this._service = service;
        this._renderer = renderer;
        
        this._geneSelectedEvent = new YAHOO.util.CustomEvent("GENESELECTED", this);
        
        flykit.debug("create a model", _context);
        this._model = new flykit.mvcutils.GenericModel2();
        this._model.setDefinition(flykit.flyatlas.BatchWidget.modelDefinition);
        
        flykit.debug("create a controller", _context);
        this._controller = new flykit.flyatlas.BatchWidget.Controller(this._model, service, this);
        
        flykit.debug("connect the renderer to the model", _context);
        this._renderer.connect(this._model);
        
        // instantiate a user event handler and pass to renderer
        this._renderer.setUserEventHandler(new flykit.flyatlas.UserEventHandler(this._controller));
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};


flykit.flyatlas.BatchWidget.prototype.subscribe = function(type, listener, obj) {
    var _context = "flykit.flyatlas.BatchWidget.prototype.subscribe";
    try {
        if (type == "GENESELECTED") {
            flykit.debug("widget: gene selected");
            this._geneSelectedEvent.subscribe(listener, obj);
        }
        
    } catch (e) {
        flykit.debug("caught "+e.name, ", "+e.message, _context);
        throw new flykit.UnexpectedException(_context, e);
    }    
};




/**
 * @public
 * @param {Array<String>} querynames
 * @param {Array<String>} flybaseids
 */
flykit.flyatlas.BatchWidget.prototype.getAssaysByGeneBatch = function( querynames, querygenes ) {
    var _context = "flykit.flyatlas.BatchWidget.prototype.getAssaysByGeneBatch";
    try {
        
        flykit.debug("pass ["+querynames+"], ["+querygenes+"] through to controller", _context);
        this._controller.getAssaysByGeneBatch(querynames, querygenes);
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};





flykit.flyatlas.BatchWidget.prototype.clear = function() {
    var _context = "flykit.flyatlas.BatchWidget.prototype.clear";
    try {
        
        flykit.debug("clear", _context);
        this._controller.clear();
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};

/**
 * Set the selection index, where more than one genes are available.
 * @param {Number} index the new selection index
 */
flykit.flyatlas.BatchWidget.prototype.setSelectionIndex = function( index ) {
    var _context = "flykit.flyatlas.BatchWidget.prototype.setSelectionIndex";
    try {
        flykit.debug("pass through to controller", _context);
        this._controller.setSelectionIndex(index);
    } catch (e) {
        flykit.debug("caught "+e.name, ", "+e.message, _context);
        throw new flykit.UnexpectedException(_context, e);
    }    
};



flykit.flyatlas.UserEventHandler = function( controller ) {

    /**
     * @private
     * Handle a mouse click on a result.
     * @param event the browser event
     * @param {Number} index the index of the result clicked
     */
	this._onResultClicked = function( event, index ) {
	    var _context = "flykit.flyatlas.UserEventHandler this._onResultClicked";
	    try {
            flykit.info("received click event, call the controller to set selection: "+index, _context); 
            
            if (this.checked)
                controller.setSelectionIndex(index);
            else
                controller.removeSelectionIndex(index);
            
            //controller.setSelectionIndex(index);	        
        } catch (e) {
            flykit.debug("caught "+e.name, ", "+e.message, _context);
            throw new flykit.UnexpectedException(_context, e);
        }    
	};	
	
};


/*
 * ----------------------------------------------------------------
 *                             CONTROLLER
 * ----------------------------------------------------------------
 */






/**
 * @class
 */
flykit.flyatlas.BatchWidget.Controller = function( model, service, controllee ) {
    var _context = "flykit.flyatlas.BatchWidget.Controller";
    try {
        
        this._model = null;
        this._service = null;
        this._controllee = null;
        
        this._parent = controllee;
        
        var that = this;
        
        flykit.debug("call private constructor", _context);
        this.__init__(model, service, controllee);        
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};








/**
 * @private
 */
flykit.flyatlas.BatchWidget.Controller.prototype.__init__ = function( model, service, controllee ) {
    var _context = "flykit.flyatlas.BatchWidget.Controller.prototype.__init__";
    try {
        
        this._model = model;
        this._service = service;
        this._controllee = controllee;
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};








/**
 * @public
 */
flykit.flyatlas.BatchWidget.Controller.prototype.getAssaysByGeneBatch = function( querynames, querygenes ) {
    var _context = "flykit.flyatlas.BatchWidget.Controller.prototype.findGenesByAnyNameBatch";
    try {
        
        flykit.info("getAssaysByGeneBatch: "+querynames+" || "+querygenes, _context);
        flykit.debug("pass through to private implementation", _context);
        
        this._getAssaysByGeneBatch(querynames, querygenes, this._getAssaysByGeneBatchSuccess(), this._getAssaysByGeneBatchFailure());
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};








/**
 * @private
 */
flykit.flyatlas.BatchWidget.Controller.prototype._getAssaysByGeneBatch = function( querynames, querygenes, success, failure ) {
    var _context = "flykit.flyatlas.BatchWidget.Controller.prototype._getAssaysByGeneBatch";
    try {
        
        flykit.debug("querynames: "+querynames, _context);
        flykit.debug("querygenes: "+querygenes, _context);
        
        
        flykit.debug("set state pending", _context);
        this._model.set("STATE", "PENDING");
        
        flykit.debug("set model property query", _context);
        this._model.set("QUERY", [querynames, querygenes]); //TODO
        

        flykit.debug("set result null", _context);
        this._model.set("RESULTS", null);
                
        flykit.debug("set message null", _context);
        this._model.set("MESSAGE", null);
        
        flykit.debug("set selection index null", _context);
        this._model.set("SELECTIONINDEX", null);        
                
        flykit.debug("kick off request", _context);
        
        flybaseids = [];
        
        for (var i=0;i<querynames.length;i++) {
            flybaseids[flybaseids.length] = querygenes[i].flybaseID;
        }
        
        this._service.getAssaysByFlybaseGeneIdBatch(flybaseids, success, failure);        
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};









/**
 * @private
 */
flykit.flyatlas.BatchWidget.Controller.prototype._getAssaysByGeneBatchSuccess = function() {
    var _context = "flykit.flyatlas.BatchWidget.Controller.prototype._getAssaysByGeneBatchSuccess";
    var self = this;
    /**
     * @param {Object<String,<Array<AssayGroup>>} results a map from flybaseids to arrays of AssayGroup objects
     */
    return function( results ) {
        try {
            
            flykit.info("request success", _context);
            
            flykit.debug("set model results", _context);
            self._model.set("RESULTS", results);
            
            flykit.debug("set model state", _context);
            self._model.set("STATE", "READY");
            
            var explanation = "<p>Values shown are mean mRNA signal; cell background colour indicates results of T-test comparison with whole fly, <span class=\"flyatlasChangeUp\">green</span> is <span class=\"flyatlasChangeUp\">up</span>, <span class=\"flyatlasChangeDown\">red</span> is <span class=\"flyatlasChangeDown\">down</span>, white is no change. Empty cells indicate no data are available for that gene.</p>";
            explanation += "<p>See also: Chintapalli, V. R., Wang, J. and Dow, J. A. T. (2007) Using FlyAtlas to identify better Drosophila models of human disease, <a href='http://www.nature.com/ng/journal/v39/n6/abs/ng2049.html'>Nature Genetics 39: 715-720</a>.</p>";
            self._model.set("MESSAGE", explanation);
            
            /*if (results.length == 1) {
                controller.setSelectionIndex(0);
            }*/
            
        } catch (unexpected) {
            flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
            throw unexpected;    
        }
    };
};







/**
 * @private
 */
flykit.flyatlas.BatchWidget.Controller.prototype._getAssaysByGeneBatchFailure = function() {
    var _context = "flykit.flyatlas.BatchWidget.Controller.prototype._getAssaysByGeneBatchFailure";
    var self = this;
    /**
     * @param {ResponseObject} response
     */
    return function( response ) {
        try {
            
            flykit.err("request failed: "+response.status+" "+response.statusText, _context);
            self._model.set("MESSAGE", "there was an error retrieving data from the server, see the logs for more info");
            self._model.set("STATE", "SERVERERROR");
            
        } catch (unexpected) {
            flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
            throw unexpected;    
        }
    };
};






flykit.flyatlas.BatchWidget.Controller.prototype.clear = function() {
    var _context = "flykit.flyatlas.BatchWidget.Controller.prototype.clear";
    try {
        
        flykit.debug("clear", _context);

        flykit.debug("set state ready", _context);
        this._model.set("STATE", "READY");
        
        flykit.debug("set model property query", _context);
        this._model.set("QUERY", null);

        flykit.debug("set result null", _context);
        this._model.set("RESULTS", null);
                
        flykit.debug("set message null", _context);
        this._model.set("MESSAGE", null);
        
        flykit.debug("set selection index null", _context);
        this._model.set("SELECTIONINDEX", null);
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};

flykit.flyatlas.BatchWidget.Controller.prototype.setSelectionIndex = function( obj ) {
   
    var _context = "flykit.flyatlas.BatchWidget.prototype.setSelectionIndex";
    var badIndex = false;
    try {
        var selectedFlybaseId = obj[0];
        var selectedAffyId = obj[1];
        var queryName = obj[2];
        var queryGeneObject = obj[3];
        var index = obj[4];
        
        
        flykit.debug("setSelectionIndex, index: "+index, _context);
        var results = this._model.get("RESULTS");
        var query = this._model.get("QUERY");
        
        var querynames = query[0];
        var querygenes = query[1];
        
        var count = 0;        
        for (var i=0;i<querynames.length;i++) {
            var groups = results[querygenes[i].flybaseID];
            count += groups.length;
        }
        
        if (results != null) {
            if (index >= 0 && index < count) {
                var indexArray = this._model.get("SELECTIONINDEX");
                if (indexArray != null){
                    var notIn = true;
                    for (var i =0; i < indexArray.length; i++){
                        if (indexArray[i][4]==index){
                            notIn = false;
                            break;
                        }
                    }
                    if (notIn)
                        indexArray.push (obj);
                    this._model.set("SELECTIONINDEX", indexArray);
                }else {
                    indexArray = new Array();
                    indexArray[0] = obj;
                    this._model.set("SELECTIONINDEX", indexArray);
                }
                
                var event = this._parent._geneSelectedEvent;
                
                var genes = [];
                var querynames = [];
                
                for (var i=0; i < indexArray.length; i ++) {
                    querynames[querynames.length] = indexArray[i][1];
                    genes[genes.length] = indexArray[i][3];
                    
                }
                event.fire(querynames, genes); 
            }
            else {
                badIndex = true;
            }
        }
    } catch (e) {
        flykit.debug("caught "+e.name, ", "+e.message, _context);
        throw new flykit.UnexpectedException(_context, e);
    }   
    
    if (badIndex) {
        throw new flykit.flyatlas.SelectionOutOfBounds("index "+index+" cannot apply to results length "+results.length);
    } 
};

flykit.flyatlas.BatchWidget.Controller.prototype.removeSelectionIndex = function( obj ) {
   
    var _context = "flykit.flyatlas.BatchWidget.prototype.removeSelectionIndex";
    var badIndex = false;
    try {
        var selectedFlybaseId = obj[0];
        var selectedAffyId = obj[1];
        var queryName = obj[2];
        var queryGeneObject = obj[3]
        var index = obj[4];
        
        flykit.debug("setSelectionIndex, index: "+index, _context);
        var results = this._model.get("RESULTS");
        var query = this._model.get("QUERY");
        
        var querynames = query[0];
        var querygenes = query[1];
        
        var count = 0;        
        for (var i=0;i<querynames.length;i++) {
            var groups = results[querygenes[i].flybaseID];
            count += groups.length;
        }
        
        if (results != null) {
            if (index >= 0 && index < count) {
                var indexArray = this._model.get("SELECTIONINDEX");
                if (indexArray != null){
                    var selected = false;
                    var toberemoved = 0;
                    for (var i =0; i < indexArray.length; i++){
                        if (indexArray[i][4]==index){
                            toberemoved = i;
                            selected = true;
                            break;
                        }
                    }
                    if (selected){
                        indexArray.splice(toberemoved,1);
                    }
                    this._model.set("SELECTIONINDEX", indexArray);
                }
                
                var event = this._parent._geneSelectedEvent;
                
                var genes = [];
                var querynames = [];
                
                for (var i=0; i < indexArray.length; i ++) {
                    querynames[querynames.length] = indexArray[i][1];
                    genes[genes.length] = indexArray[i][3];
                }
                event.fire(querynames, genes); 
            }
            else {
                badIndex = true;
            }
        }
    } catch (e) {
        flykit.debug("caught "+e.name, ", "+e.message, _context);
        throw new flykit.UnexpectedException(_context, e);
    }   
    
    if (badIndex) {
        throw new flykit.flyatlas.SelectionOutOfBounds("index "+index+" cannot apply to results length "+results.length);
    } 
};


/**
 * @class
 * An exception thrown if selection index is out of bounds.
 * @constructor
 * @param {String} message
 */
flykit.flyatlas.SelectionOutOfBounds = function( message ) {
	this.name = "lykit.flyatlas.SelectionOutOfBounds";
	this.message = message;
}



/*
 * ----------------------------------------------------------------
 *                             MODEL DEFINITION
 * ----------------------------------------------------------------
 */





/** 
 * @type Object
 */
flykit.flyatlas.BatchWidget.modelDefinition = {

    properties : [ "STATE", "RESULTS", "MESSAGE", "QUERY", "SELECTIONINDEX" ],
    
    values : {
        "STATE" : [ "READY", "PENDING", "SERVERERROR", "UNEXPECTEDERROR" ]
    },
    
    initialize : function( data ) {
        data["STATE"] = "READY";
        data["RESULTS"] = null;
        data["MESSAGE"] = null;
        data["QUERY"] = null;
        data["SELECTIONINDEX"] = null;
    }

};







/*
 * ----------------------------------------------------------------
 *                             DEFAULT RENDERER
 * ----------------------------------------------------------------
 */







flykit.flyatlas.BatchWidget.DefaultRenderer = function() {};


/** 
 * @private 
 * @type Element
 */
flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._canvas = null;

/**
 * @private 
 * @type Element
 */
flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._pendingPane = null;

/**
 * @private 
 * @type Element
 */
flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._resultsSummaryPane = null;

/**
 * @private 
 * @type Element
 */
flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._resultsPane = null;

/**
 * @private 
 * @type Element
 */
flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._profilePane = null;

/**
 * @private 
 * @type Element
 */
flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._pairwisePane = null;


/**
 * @private 
 * @type Element
 */
flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._messagePane = null;


flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._userEventHandler = null;


/**
 * Set the DOM element to which this renderer applies and initialise it.
 * @param {Element} canvas
 */
flykit.flyatlas.BatchWidget.DefaultRenderer.prototype.setCanvas = function( canvas ) {
    var _context = "flykit.flyatlas.BatchWidget.DefaultRenderer.prototype.setCanvas";
    try {
        
        flykit.debug("set canvas", _context);
        this._canvas = $(canvas);
        this._initCanvas();
        
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};



flykit.flyatlas.BatchWidget.DefaultRenderer.prototype.setUserEventHandler = function( handler ) {
	this._userEventHandler = handler;
};


/**
 * @private
 * @param {Element} canvas
 */
flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._initCanvas = function() {
    var _context = "flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._initCanvas";
    try {
        
        flykit.debug("begin init canvas", _context);
        
        var canvas = this._canvas;
        canvas.addClass("batchFlyatlasWidget");

        var pp = $("<p class='pendingPane'>pending (please wait, this can take up to 10 seconds) ...</p>").hide();
        canvas.append(pp);
        this._pendingPane = pp;

        var rsp = $("<p class='resultsSummaryPane'>this text should never be displayed</p>").hide();
        canvas.append(rsp);
        this._resultsSummaryPane = rsp;
        
        var rp = $("<div class='resultsPane'></div>").hide();
        canvas.append(rp);
        this._resultsPane = rp;
        
        var fp = $("<div class='profilePane' id='profilePane'></div>").hide();
        canvas.append(fp);
        this._profilePane = fp;
        
        var pw = $("<div class='pairwisePane' id='pairwisePane'></div>").hide();
        canvas.append(pw);
        this._pairwisePane = pw;
        
        var mp = $("<p class='messagePane'>this text should never be displayed</p>").hide();
        canvas.append(mp);
        this._messagePane = mp;            

        flykit.debug("init canvas done", _context);
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};





/**
 * @public
 */
flykit.flyatlas.BatchWidget.DefaultRenderer.prototype.connect = function( model ) {
    var _context = "flykit.flyatlas.BatchWidget.DefaultRenderer.prototype.connect";
    try {
        
        flykit.debug("connect to model", _context);
        model.subscribeAll(this._onModelChanged, this);
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};





/**
 * @private
 */
flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._onModelChanged = function( type, args, self ) {
    var _context = "flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._onModelChanged";
    try {
        
        var handlers = {
            "STATE":"_onStateChanged",
            "QUERY":"_onQueryChanged",
            "RESULTS":"_onResultsChanged",
            "MESSAGE":"_onMessageChanged",
            "SELECTIONINDEX":"_onSelectionIndexChanged"
        };
        var handler = handlers[type];
        flykit.debug("call model changed handler: "+handler, _context);
        self[handler](args[0], args[1], args[2]);
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};






/**
 * @private
 */
flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._onQueryChanged = function( from, to, get ) {
    var _context = "flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._onQueryChanged";
    try {
        
        // do nothing, we will access the value later
        flykit.debug("query changed from "+from+" to "+to, _context);
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};






/**
 * @private
 */
flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._onStateChanged = function( from, to, get ) {
    var _context = "flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._onStateChanged";
    try {
        
        flykit.debug("state changed from "+from+" to "+to, _context);

        if ( to == "PENDING" ) {
            this._pendingPane.show();
            this._messagePane.hide();
            this._resultsSummaryPane.hide();
            this._resultsPane.hide();
            this._profilePane.hide();
            this._pairwisePane.hide();
        }
        else if ( to == "READY" ) {
            this._pendingPane.hide();
            this._messagePane.show();
            this._resultsSummaryPane.show();
            this._resultsPane.show(); 
            this._profilePane.show();
            this._pairwisePane.show();
        } 
        else if ( to == "SERVERERROR" || to == "UNEXPECTEDERROR" ) {
            this._pendingPane.hide();
            this._messagePane.show();
            this._resultsSummaryPane.hide();
            this._resultsPane.hide();   
            this._profilePane.hide();
            this._pairwisePane.show();
        } 
        else {
            // this should never happen
            throw {message:"invalid state: "+to};
        }
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};






/**
 * @private
 */
flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._onResultsChanged = function( from, to, get ) {
    var _context = "flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._onResultsChanged";
    try {
        
        flykit.debug("results changed to: "+to, _context);
        
        if (to == null) {
            flykit.debug("empty results summary pane", _context);
            this._resultsSummaryPane.empty();
            flykit.debug("empty results pane", _context);
            this._resultsPane.empty();
            this._profilePane.empty();
            this._pairwisePane.empty();
        } 
        
        else {

            var query = get("QUERY");
            
            flykit.debug("render results summary", _context);
            this._renderResultsSummary(query, to);
    
            flykit.debug("render results", _context);
            this._renderResults(query, to);
            
            google.setOnLoadCallback(this._renderProfile(query, to));
            
            $(document).ready(function() {    
                $("#sortable-table").tablesorter({
                    /*debug: true*/
                });
            });
            
        }
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};


flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._onSelectionIndexChanged = function( from, to ) {
    var _context = "flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._onSelectionIndexChanged";
    try {
        
        flykit.debug("from:"+from+", to:"+to, _context);
        
        // get the result nodes
        /*var nodes = this._getResultNodes(); // that._resultsPane.getElementsByTagName("tr");
        var nodes = this.$("tr");
        
        if (from != null) {
        */    // remove class
        /*    for (var i =0; i < from.length; i ++){
                var fromIndex = from[i][3];
                flykit.info("remove selected class from node: "+nodes[fromIndex+1]+"debug", _context);
                YAHOO.util.Dom.removeClass(nodes[fromIndex+1], "selected");
                nodes[fromIndex+1].removeClass("selected");
            }    
        }*/
        
        if (to != null) {
            // add class
            
            for (var i =0; i < to.length; i ++){
        /*        var toIndex = to[i][3];
                flykit.info("adding selected class to node: "+nodes[toIndex+1]+"debug", _context);
                YAHOO.util.Dom.addClass(nodes[toIndex+1], "selected");
        */        
                var gene = to[i][0];
                this._renderGeneSelectionMessage(gene);
            }
        }
        
    } catch (e) {
        flykit.debug("caught "+e.name, ", "+e.message, _context);
        throw new flykit.UnexpectedException(_context, e);
    }   
};


flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._getResultNodes = function() {
	return $("tr");
};

/**
 * @private
 */
flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._onMessageChanged = function( from, to, get ) {
    var _context = "flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._onMessageChanged";
    try {
        
        flykit.debug("message changed to: "+to, _context);
        
        if (to == null) {
            flykit.debug("empty messsage pane", _context);
            this._messagePane.empty();
        } 
        
        else {

            this._messagePane.html(to);
            
        }
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};




/**
 * @private
 * Render a message for the given selection.
 * @param {flyui.flybase.Gene} gene the selected gene (may be null for no selection)
 */
flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._renderGeneSelectionMessage = function( gene ) {
    var _context = "flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._renderGeneSelectionMessage";
    try {
        
        if (gene == null) {
            this._messagePane.innerHTML = "selected gene: <strong>please select one of the genes from the list above, or try another query</strong>";
        }
        else {
            this._messagePane.innerHTML = "selected gene: <strong>"+gene + "</strong>)";
        }  
              
    } catch (e) {
        flyui.debug("caught "+e.name, ", "+e.message, _context);
        throw new flykit.UnexpectedException(_context, e);
    }   
};





/**
 * @private
 * @param {Object<String,<Array<AssayGroup>>} results a map from flybaseids to arrays of assay group objects
 */
flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._renderResultsSummary = function( query, results ) {
    var _context = "flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._renderResultsSummary";
    try {
        
        flykit.debug("render results summary", _context);

        var querynames = query[0];
       
        var content = "";
        var count = 0;        
        for (var i=0;i<querynames.length;i++) {
            var flybaseid = query[1][i].flybaseID;
            var groups = results[flybaseid];
            count += groups.length;
        }
        
        var content = "found ";
        content += count;
        content += " matching probe";
        content += (count == 0 || count > 1) ? "s " : " ";
        content += "from <a href='http://flyatlas.org'>flyatlas.org</a> ("+flykit.flyatlas.provenance+") .";
        content += "Click on the check boxes for expression images of selected genes. The expression data can be sorted by clicking on the header of each column..."
        
        this._resultsSummaryPane.html(content);
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};



/**
 * @private
 * @param {Object<String,<Array<Gene>>} results a map from names in the query to arrays of gene objects
 */
 
 flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._renderProfile = function( query, results ) {
     var _context = "flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._renderProfile";
     
     try{
        flykit.debug("render result profile", _context);
        
        var data = new google.visualization.DataTable();
        data.addColumn('string', 'Gene');
        data.addColumn('number', 'Ratio');
        var querygenes = query[1];
        var querynames = query[0];
        data.addRows(querygenes.length);
        
        for (var i =0; i < querynames.length; i ++) {
            data.setValue(i, 0, querynames[i]);
            var id = querygenes[i].flybaseID;
            var groups = results[id];
            
            if (groups.length > 0) {
                var pairwise = 0; 
                for (var k=0; k<groups.length; k++){
                    var group = groups[k];
                    pairwise += parseInt(group["whole"].pairwise);
                }     
                
                data.setValue(i, 1, pairwise/groups.length);
                
            }
            
        }
        
        var chart = new google.visualization.LineChart(document.getElementById('profilePane'));
        chart.draw(data, {width: 1100, height: 240, title: 'Expression ratio of expression in testis v.s. mean expression of non-testis tissues (i.e. excluding testis and larval fat body)'});
        
        
        /**
        ***
        ***  Rendering the second chart
        ***
        **/
        
        
        /*var pairwise = new google.visualization.DataTable();
        pairwise.addColumn('string', 'Gene');
        
        for (var k=0;k<flykit.flyatlas.tissues.length;k++) {
            var tissue = flykit.flyatlas.tissues[k];
            if (tissue!="whole")
                pairwise.addColumn('number', tissue);
        }
        var querygenes = query[1];
        var querynames = query[0];
        pairwise.addRows(querygenes.length);
        
        for (var i =0; i < querynames.length; i ++) {
            pairwise.setValue(i, 0, querynames[i]);
            var id = querygenes[i].flybaseID;
            var groups = results[id];
            
            if (groups.length > 0) {
                for (var k=0;k<flykit.flyatlas.tissues.length;k++) {
                    var tissue = flykit.flyatlas.tissues[k];
                    
                    if (tissue!="whole"){
                        var group = groups[0];
                        var testis_ratio = parseInt(group[tissue].testis_ratio);
                        flykit.debug("render tissue: " + tissue + testis_ratio, "_context");
                        pairwise.setValue(i, k, testis_ratio);
                    }
                }
                
                
            }
            
        }
        
        var pairwisechart = new google.visualization.LineChart(document.getElementById('pairwisePane'));
        pairwisechart.draw(pairwise, {width: 1100, height: 1240, title: 'Expression ratio of expression in testis v.s. another tissue'});*/
        
        /**
        ***
        ***  Rendering in separate chart
        ***
        **/
        
        for (var i =0; i < querynames.length; i ++) {
            var pair = new google.visualization.DataTable();
            var id = querygenes[i].flybaseID;
            var groups = results[id];
            
            pair.addColumn('string', "Tissue");
            
            pair.addRows(flykit.flyatlas.tissues.length);
            
            if (groups.length==1){
                for (var k=1;k<flykit.flyatlas.tissues.length;k++) {
                    var tissue = flykit.flyatlas.tissues[k];
                    pair.addColumn('number', tissue);
                    var group = groups[0];
                    var testis_ratio = parseInt(group[tissue].testis_ratio);
                    pair.setValue(k, k, testis_ratio);
                }
            }else{
                for (var m=0; m<groups.length; m++){
                    var group = groups[m];
                    pair.addColumn('number', group.affy_id);
                    for (var k=1;k<flykit.flyatlas.tissues.length;k++) {
                        var tissue = flykit.flyatlas.tissues[k];
                        var testis_ratio = parseInt(group[tissue].testis_ratio);
                        pair.setValue(k, m+1, testis_ratio);
                    }    
                }
            }
             
            /*for (var k=1;k<flykit.flyatlas.tissues.length;k++) {
                var tissue = flykit.flyatlas.tissues[k];   
                
                //pair.setValue(k, 0, tissue);
                if (groups.length==1){
                    pair.addColumn('number', tissue);
                    var group = groups[0];
                    var testis_ratio = parseInt(group[tissue].testis_ratio);
                    pair.setValue(k, k, testis_ratio);
                }else{
                    //TODO
                     
                    for (var m=0; m<groups.length; m++){
                        var group = groups[m];
                        pair.addColumn('number', group.affy_id);
                        var testis_ratio = parseInt(group[tissue].testis_ratio);
                        pair.setValue(m, k, testis_ratio);
                    }
                    
                }
            }*/
            
            var panelet = $("<div>");
            panelet.attr("id", "pairwisePane-"+i);
            panelet.attr("class", "pairwisePanelet");
            this._pairwisePane.append(panelet);
                    
            var pairchart = new google.visualization.LineChart(document.getElementById('pairwisePane-'+i));
            pairchart.draw(pair, {width: 500, height: 140, pointSize: 5, legendFontSize: 7, title: 'Expression ratio of "' + querynames[i] + '-' + id + '" in testis v.s. another tissue'});
            
        }
         
     }catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
 };



/**
 * @private
 * @param {Object<String,<Array<Gene>>} results a map from names in the query to arrays of gene objects
 */
flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._renderResults = function( query, results ) {
    var _context = "flykit.flyatlas.BatchWidget.DefaultRenderer.prototype._renderResults";
    try {
        flykit.debug("render results", _context);

        var querynames = query[0];
        var querygenes = query[1];        
        
        var table = $("<table id=\"sortable-table\"></table>");
        var thead = $("<thead>");
        table.append(thead);
        var tr = $("<tr>");
        thead.append(tr);
        tr.append($("<th>").append("gene"));
        tr.append($("<th>").append("FlyBase ID"));
        tr.append($("<th>").append("probe"));
        tr.append($("<th>").append("user select"));
        for (var i=0;i<flykit.flyatlas.tissues.length;i++) {
            var tissue = flykit.flyatlas.tissues[i];
            tr.append($("<th>").append(tissue));
        }
        
        var tbody = $("<tbody>");
        table.append(tbody);
        
        var result_index = 0;
        
        for (var i=0;i<querynames.length;i++) {
            var queryname = querynames[i];
            //var id = flybaseids[i];
            var querygene = querygenes[i];
            var id = querygene.flybaseID;
            // results are indexed by flybase ids
            // one flybase gene could be mapped to multiple flyatlas assays
            // results[id] is an array
            
            var groups = results[id];
            
            if (groups.length > 0) {
                for (var j=0; j<groups.length;j++) {
                    var tr = $("<tr>");
                    tbody.append(tr);
                    
                    // 1st col: query gene name 
                    tr.append($("<td>").append(queryname));
                   
                    var group = groups[j];
                    
                    // 2nd col: flybase id for the gene
                    
                    tr.append($("<td>").append(id));
                    
                    // 3rd col: mapping flyatlas affyid
                    tr.append($("<td>").append("<a href='http://flyatlas.org/probeset.cgi?name="+group.affy_id+"'>"+group.affy_id+"</a>"));
                    
                    // 4th col: user selection
                    var td = $("<td>");
                    
                    var inputbox = $("<input>");
                    inputbox.attr("type", "checkbox");
                    inputbox.attr("name", group.affy_id);
                    inputbox.attr("value", id);
                    inputbox.attr("id", "default-"+result_index)

                    td.append(inputbox);
                 
                    
                    tr.append(td);
                    
                    // other cols: tissue expression
                    for (var k=0;k<flykit.flyatlas.tissues.length;k++) {
                        var tissue = flykit.flyatlas.tissues[k];
                        flykit.debug("render tissue: " + tissue, "_context");
                        var change = group[tissue].change;
                        var mean = group[tissue].mean;
                        //var sem = group[tissue].sem;
                        
                        var clsname = "flyatlasChangeNone";
                        if (change == "Up") {
                            clsname = "flyatlasChangeUp";
                        }
                        else if (change == "Down") {
                            clsname = "flyatlasChangeDown";
                        }
                        
                        var trCls = "";
                        if (tissue == "testis"){
                            var pairwise = group["whole"].pairwise;
                            if (pairwise > 20) {
                                trCls = "testisSpecific";
                            }
                        }
                        
                        tr.addClass(trCls);
                                                                        
                        tr.append($("<td>")
                            .addClass(clsname)
                            .append("<span>"+Math.round(mean) + "</span>")
                        );
                    }
                    
                    // subscribe to onclick event
                    flykit.debug("subscribe to the event",_context);
                    YAHOO.util.Event.addListener(inputbox, "click", this._userEventHandler._onResultClicked, [id,group.affy_id,queryname,querygene,result_index]); //TODO, pass the genes in
                    result_index = result_index + 1;
                    
                    
                }
            }
        }
        
        this._resultsPane.append(table);
        //this._resultsPane.html(content);
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};















