/**
 * @fileoverview
 * This script defines a widget for interacting with image data from BDGP.
 * @author <a href="http://purl.org/net/aliman">Alistair Miles</a>
 * @version $Revision:538 $ on $Date: 2008-08-27 09:08:41 +0100 (Wed, 27 Aug 2008) $ by $Author: aliman $
 * @requires flykit.util
 * @requires flykit.sparql.Service
 * @requires flykit.bdgp.Service
 * @requires YAHOO.util.Connect
 * @requires jQuery
 * For license terms see http://flykit.googlecode.com
 */
 
flykit.namespace("flykit.bdgp");







 
 
 

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







flykit.bdgp.BatchWidget = function( service, renderer ) {
    var _context = "flykit.bdgp.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.bdgp.BatchWidget.prototype._controller = null;

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

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

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










/**
 * @private
 */
flykit.bdgp.BatchWidget.prototype.__init__ = function( service, renderer ) {
    var _context = "flykit.bdgp.BatchWidget.prototype.__init__";
    try {
        
        this._service = service;
        this._renderer = renderer;
        
        flykit.debug("create a model", _context);
        this._model = new flykit.mvcutils.GenericModel2();
        this._model.setDefinition(flykit.bdgp.BatchWidget.modelDefinition);
        
        flykit.debug("create a controller", _context);
        this._controller = new flykit.bdgp.BatchWidget.Controller(this._model, service, this);
        
        flykit.debug("connect the renderer to the model", _context);
        this._renderer.connect(this._model);
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};







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




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






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






/**
 * @class
 */
flykit.bdgp.BatchWidget.Controller = function( model, service, controllee ) {
    var _context = "flykit.bdgp.BatchWidget.Controller";
    try {
        
        this._model = null;
        this._service = null;
        this._controllee = null;
        
        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.bdgp.BatchWidget.Controller.prototype.__init__ = function( model, service, controllee ) {
    var _context = "flykit.bdgp.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.bdgp.BatchWidget.Controller.prototype.findImagesByGeneBatch = function( querynames, genes ) {
    var _context = "flykit.bdgp.BatchWidget.Controller.prototype.findGenesByAnyNameBatch";
    try {
        
        flykit.info("findImagesByGeneBatch: "+querynames+" || "+genes, _context);
        flykit.debug("pass through to private implementation", _context);
        this._findImagesByGeneBatch(querynames, genes, this._findImagesByGeneBatchSuccess(), this._findImagesByGeneBatchFailure());
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};






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

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









/**
 * @private
 */
flykit.bdgp.BatchWidget.Controller.prototype._findImagesByGeneBatchSuccess = function() {
    var _context = "flykit.bdgp.BatchWidget.Controller.prototype._findImagesByGeneBatchSuccess";
    var self = this;
    /**
     */
    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 = "Images depict patterns of gene expression during embryogenesis for Drosophila genes represented in non-redundant sets of Drosophila ESTs DGC1 and DGC2. Empty table cells indicate that no images are available from BDGP for that gene/stage. See also <a href='http://dx.doi.org/10.1186/gb-2002-3-12-research0088'>Tomancak et al. 2002</a> and <a href='http://dx.doi.org/10.1186/gb-2007-8-7-r145'>Tomancak et al. 2007</a>.";
            self._model.set("MESSAGE", explanation);
            
        } catch (unexpected) {
            flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
            throw unexpected;    
        }
    };
};







/**
 * @private
 */
flykit.bdgp.BatchWidget.Controller.prototype._findImagesByGeneBatchFailure = function() {
    var _context = "flykit.bdgp.BatchWidget.Controller.prototype._findImagesByGeneBatchFailure";
    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.bdgp.BatchWidget.Controller.prototype.clear = function() {
    var _context = "flykit.bdgp.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);
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
}









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





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

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

};







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







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


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

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

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

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

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





/**
 * Set the DOM element to which this renderer applies and initialise it.
 * @param {Element} canvas
 */
flykit.bdgp.BatchWidget.DefaultRenderer.prototype.setCanvas = function( canvas ) {
    var _context = "flykit.bdgp.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;    
    }
};






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

        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 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.bdgp.BatchWidget.DefaultRenderer.prototype.connect = function( model ) {
    var _context = "flykit.bdgp.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.bdgp.BatchWidget.DefaultRenderer.prototype._onModelChanged = function( type, args, self ) {
    var _context = "flykit.bdgp.BatchWidget.DefaultRenderer.prototype._onModelChanged";
    try {
        
        var handlers = {
            "STATE":"_onStateChanged",
            "QUERY":"_onQueryChanged",
            "RESULTS":"_onResultsChanged",
            "MESSAGE":"_onMessageChanged"
        };
        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.bdgp.BatchWidget.DefaultRenderer.prototype._onQueryChanged = function( from, to, get ) {
    var _context = "flykit.bdgp.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.bdgp.BatchWidget.DefaultRenderer.prototype._onStateChanged = function( from, to, get ) {
    var _context = "flykit.bdgp.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();
        }
        else if ( to == "READY" ) {
            this._pendingPane.hide();
            this._messagePane.show();
            this._resultsSummaryPane.show();
            this._resultsPane.show();         
        } 
        else if ( to == "SERVERERROR" || to == "UNEXPECTEDERROR" ) {
            this._pendingPane.hide();
            this._messagePane.show();
            this._resultsSummaryPane.hide();
            this._resultsPane.hide();         
        } 
        else {
            // this should never happen
            throw {message:"invalid state: "+to};
        }
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};






/**
 * @private
 */
flykit.bdgp.BatchWidget.DefaultRenderer.prototype._onResultsChanged = function( from, to, get ) {
    var _context = "flykit.bdgp.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();
        } 
        
        else {

            var query = get("QUERY");
            
            flykit.debug("render results summary", _context);
            this._renderResultsSummary(query, to);
    
            flykit.debug("render results", _context);
            this._renderResults(query, to);        
            
        }
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};







/**
 * @private
 */
flykit.bdgp.BatchWidget.DefaultRenderer.prototype._onMessageChanged = function( from, to, get ) {
    var _context = "flykit.bdgp.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
 */
flykit.bdgp.BatchWidget.DefaultRenderer.prototype._renderResultsSummary = function( query, results ) {
    var _context = "flykit.bdgp.BatchWidget.DefaultRenderer.prototype._renderResultsSummary";
    try {
        
        flykit.debug("render results summary", _context);

        var querynames = query[0];
        var genes = query[1];
        
        var count = 0;
        
        for (genename in results) {
            for (stagename in results[genename]) {
                flykit.debug("counting images for "+genename+" "+stagename, _context);
                count += results[genename][stagename].images.length;               
            }
        }
        
        var content = "found "+count+" images from <a href='http://fruitfly.org'>fruitfly.org</a> ("+flykit.bdgp.provenance+") ...";

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








/**
 * @private
 */
flykit.bdgp.BatchWidget.DefaultRenderer.prototype._renderResults = function( query, results ) {
    var _context = "flykit.bdgp.BatchWidget.DefaultRenderer.prototype._renderResults";
    try {
        flykit.debug("render results", _context);

        var querynames = query[0];
        var genes = query[1];
        
        var stagenames = ["stage1-3", "stage4-6", "stage7-8", "stage9-10", "stage11-12", "stage13-16"];
        
        var content = "<table>";

        content += "<thead><tr><th>gene</th>";
        for (var i=0;i<stagenames.length;i++) {
            content += "<th>"+stagenames[i].replace(/stage(.*)/, "stage $1")+"</th>";
        }                        
        content += "</tr></thead><tbody>";
        
        for (var i=0; i<querynames.length; i++) {
            var n = querynames[i];
            var gene = genes[i];
            if (gene.flybaseID != null){
                var c = genes[i].annotationSymbols[0];
                var id = genes[i].flybaseID;
                content += "<tr><td><a href='http://www.fruitfly.org/cgi-bin/ex/bquery.pl?qtype=report&amp;find="+c+"&amp;searchfield=CG'>"+n+"</a></td>";
            }
            else {
                content += "<tr><td>"+gene +"</td>";   
            }
            for (var j=0;j<stagenames.length;j++) {
                var s = stagenames[j];
                var r = results[id];
                flykit.debug("looking for results for gene "+id+" "+r, _context);
                content += "<td>";
                for (var k in r) {
                    flykit.debug("found stage "+k+" in result for gene "+id, _context);
                    if (k == s) {
                        var rs = r[k];
                        flykit.debug("found match to stage "+s, _context);
                        content += "<p class='terms'>";
                        for (var l=0;l<rs.terms.length;l++) {
                            var term = rs.terms[l];
                            content += term + "; ";
                        }
                        content += "</p>";
                        for (var l=0;l<rs.images.length;l++) {
                            var alttext = "thumbnail image depicting expression of "+n+" in "+s+" embryo"
                            
                            var image = rs.images[l];
                            content +=   "<div class=\"result\">";
                            content +=   "<a href=\"" + image.fullImageURL + "\">";
                            content +=   "<img src=\"" + image.thumbnailURL + "\" alt=\""+alttext+"\">";
                            content +=   "</img></a>"; 
                            content +=   "</div>";                                                        
                        }
                    }
                }
                content += "</td>";
            }
            content += "</tr>";
        }

        content += "</tbody></table>";
        
        flykit.debug("results pane content: "+content, _context);
        this._resultsPane.html(content);
        
    } catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }
};





























