
// create a namespace if not already defined
flykit.namespace("flykit.flyted");




flykit.flyted.provenance = "retrieved on 2011-02-11";




/**
 * TODO doc me
 */
flykit.flyted.Service = function (endpointURL) {
	/**
	 * @private
	 */
	this._endpoint = endpointURL;
};


// extend
flykit.flyted.Service.prototype = new flykit.sparql.Service();


/**
 * TODO doc me
 */
flykit.flyted.Service.prototype.findImagesByFlytedProbeName = function( probeName, success, failure ) {
    var _context = "flykit.flyted.Service.prototype.findImagesByFlytedProbeName";
	try {
		flykit.info("probeName: "+probeName, _context);
//		var successAdapter = flykit.flyted.Service._buildSuccessAdapterForFindImagesByFlytedProbeName(success);
        var successChain = flykit.chain(flykit.flyted.Service.responseToImages, success);	
		var query = flykit.flyted.Service._buildQueryForFindImagesByFlytedProbeName(probeName);
		this.postQuery(query, successChain, failure);
	}catch (error) {
        throw new flykit.UnexpectedException(_context, error);
    }
};


/**
 * Find images in the FlyTED database for the given flybase gene ID.
 * @param {String} flybaseGeneID the flybase gene ID e.g. FBgn012345
 * @param {Function} success the success case callback function, which must accept an array of 
 * flykit.flyted.Image objects
 * @param {Function} failure the failure case callback function, which must accept a YUI HTTP response object
 */
flykit.flyted.Service.prototype.findImagesByFlybaseGeneID = function( flybaseGeneID, success, failure) {
    var _context = "flykit.flyted.Service.prototype.findImagesByFlybaseGeneID";
	try {
		flykit.info("flybaseGeneID: "+flybaseGeneID, _context);
//		var successAdapter = flykit.flyted.Service._buildSuccessAdapterForFindImagesByFlybaseGeneID(success);
        var successChain = flykit.chain(flykit.flyted.Service.responseToImages, success); 
		var query = flykit.flyted.Service._buildQueryForFindImagesByFlybaseGeneID(flybaseGeneID);	
		this.query(query, successChain, failure);
	}catch (error) {
        throw new flykit.UnexpectedException(_context, error);
    }
	
};

flykit.flyted.Service.prototype.findImagesByFlybaseGeneIDBatch = function( flybaseGeneIDs, success, failure) {
    var _context = "flykit.flyted.Service.prototype.findImagesByFlybaseGeneIDBatch";
	try {
		flykit.info("flybaseGeneIDs: "+flybaseGeneIDs, _context);
		if (flybaseGeneIDs.length == 0) {
            success({});
        }
        else {
            var chain = flykit.chain(flykit.flyted.Service.transformResponseForFindImagesByFlybaseGeneIDBatch, success);
            var query = this._buildQueryForFindImagesByFlybaseGeneIDBatch(flybaseGeneIDs);
            flykit.debug("query: "+query, _context);
            this.postQuery(query, chain, failure);        
        }		
	}catch (error) {
        throw new flykit.UnexpectedException(_context, error);
    }
	
};

flykit.flyted.Service.prototype._buildQueryForFindImagesByFlybaseGeneIDBatch = function( flybaseIDs ) {
    var _context = "flykit.flyted.Service.prototype._buildQueryForFindImagesByFlybaseGeneIDBatch";
    try {
        /*
        # query to select data on multiple genes
        
        PREFIX flyted: <http://purl.org/net/flyted/schema/>  
                
        SELECT DISTINCT ?fbgn ?flytedURL ?fullImageURL ?thumbnailURL ?probe ?caption ?probeLabel WHERE 
        {
          {
            {
              LET (?fbgn := <http://openflydata.org/id/flybase/feature/FBgn0004903> )
            }
            UNION
            {
              LET (?fbgn := <http://openflydata.org/id/flybase/feature/FBgn0033960> )
            }
          }
          {
            ?probe flyted:hybridisesTranscriptOf ?fbgn ;
              		rdfs:label ?probeLabel .
            ?fullImageURL flyted:probe ?probe ;
              			  flyted:thumbnail ?thumbnailURL;
              			  rdfs:seeAlso ?flytedURL;
              			  rdfs:label ?caption .
            
          }
        }
        */
    	
    	var query = 	"PREFIX flyted: <http://purl.org/net/flyted/schema/> " +
						"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> " +
						"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> ";
						                            
        query +=            "SELECT DISTINCT ?fbgn ?flytedURL ?recordURL ?thumbnailURL ?probe ?caption ?probeLabel\n" +
                            //"FROM <http://purl.org/net/dataset/flyted-latest>\n" +
                            "WHERE {\n ";
                            //"{\n" +
                            //"  {\n" +
                            //"    { LET (?fbgn := <http://openflydata.org/id/flybase/feature/"+flybaseGeneIDs[0]+"> ) }\n";
                            
        if (flybaseIDs.length==1) {
            var body_union = "{\n" +
                                  "?probe flyted:hybridisesTranscriptOf " + 
                                      "<http://purl.org/net/open-biomed/id/flybase/feature/Drosophila_melanogaster/SO_0000704/"+flybaseIDs[0]+">; \n" +
                                      "rdfs:label ?probeLabel ; flyted:hybridisesTranscriptOf ?fbgn.\n" +
							      "?recordURL " +
								      "flyted:probe ?probe ; \n" +
								      "flyted:thumbnail ?thumbnailURL; \n" +
								      "rdfs:seeAlso ?flytedURL; \n" +
								      "rdfs:label ?caption .\n" +
						       "}}\n";                                                                                             
        }else {
            
            var body_union = "{\n" +
                                  "?probe flyted:hybridisesTranscriptOf " + 
                                     "<http://purl.org/net/open-biomed/id/flybase/feature/Drosophila_melanogaster/SO_0000704/"+flybaseIDs[0]+">; \n" +
                                     "rdfs:label ?probeLabel ; flyted:hybridisesTranscriptOf ?fbgn.\n" +
    						      "?recordURL " +
    							      "flyted:probe ?probe ; \n" +
    							      "flyted:thumbnail ?thumbnailURL; \n" +
    							      "rdfs:seeAlso ?flytedURL; \n" +
    							      "rdfs:label ?caption .\n" +
                                    "}\n";
             for (var i = 1; i < flybaseIDs.length; i ++) {
                 body_union += "union \n"+
                                 "{\n" +
                                      "?probe flyted:hybridisesTranscriptOf " + 
                                         "<http://purl.org/net/open-biomed/id/flybase/feature/Drosophila_melanogaster/SO_0000704/"+flybaseIDs[i]+">; \n" +
                                         "rdfs:label ?probeLabel ; flyted:hybridisesTranscriptOf ?fbgn.\n" +
    							      "?recordURL " +
    								      "flyted:probe ?probe ; \n" +
    								      "flyted:thumbnail ?thumbnailURL; \n" +
    								      "rdfs:seeAlso ?flytedURL; \n" +
    								      "rdfs:label ?caption .\n" +
                                        "}\n";
             }                           
             body_union += "}\n";
            
        }
        
        query += body_union;
                            
        flykit.debug("the raw query: "+query, _context);
        
        return query;
    } 
    catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }    
};


flykit.flyted.Service.responseToImages = function( response ) {
    var _context = "flykit.flyted.Service.responseToImages";
    try {
        flykit.debug("response status: "+response.status, _context);
        flykit.debug("try parsing response text as json", _context);
        flykit.debug("response text: "+response.responseText, _context);
        var resultSet = YAHOO.lang.JSON.parse(response.responseText);
        flykit.debug("convert result set to an array of genes", _context);
        var images = flykit.flyted.Image.newInstancesFromSPARQLResults(resultSet);
        return images;
    } catch (e) {
        flykit.debug("caught "+e.name+", "+e.message, _context);
        throw new flykit.UnexpectedException(_context, e);
    }
};



/**
 * Build a SPARQL query to retrieve images by flyted probe name.
 * @param {String} anyName the probe name to search by
 * @return a SPARQL query
 * @type String
 * @private
 * @static
 */
flykit.flyted.Service._buildQueryForFindImagesByFlytedProbeName = function( probeName ) {

	try {
		var prefixes = 	"PREFIX flyted: <http://purl.org/net/flyted/schema/> " +
						"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> " +
						"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> ";
						
		var body = 		"SELECT DISTINCT *\n" +  
		                //"FROM <http://purl.org/net/dataset/flyted-latest>\n" + 
		                "WHERE { " +
							"?recordURL " +
								"flyted:probe ?probe ; " +
								//"flyted:associatesToGene ?gene ; " +
								"flyted:thumbnail ?thumbnailURL; " +
								"rdfs:seeAlso ?flytedURL; " +
								"rdfs:label ?caption ." +
							"?probe rdfs:label '" + probeName + "' ." +
						"}";
							
		var query = prefixes + body;
	
		return query;
	}catch (error) {
        throw new flykit.UnexpectedException("flykit.flyted.Service._buildQueryForFindImagesByFlytedProbeName", error);
    }
};

flykit.flyted.Service._buildQueryForFindImagesByFlybaseGeneID = function( flybaseGeneID ) {
	try {
		var prefixes = 	"PREFIX flyted: <http://purl.org/net/flyted/schema/> " +
						"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> " +
						"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> ";
						"PREFIX so: <http://purl.org/obo/owl/SO#> ";
						
		var body = 		"SELECT DISTINCT ?recordURL ?thumbnailURL ?flytedURL ?caption ?probe ?probeLabel\n" + 
		                //"FROM <http://purl.org/net/dataset/flyted-latest>\n" + 
		                "WHERE { " +
							"?probe flyted:hybridisesTranscriptOf <http://purl.org/net/open-biomed/id/flybase/feature/Drosophila_melanogaster/SO_0000704/" + flybaseGeneID + "> ;" +
								"rdfs:label ?probeLabel ." +
							"?recordURL " +
								"flyted:probe ?probe ; " +
								"flyted:thumbnail ?thumbnailURL; " +
								"rdfs:seeAlso ?flytedURL; " +
								"rdfs:label ?caption ." +
						"}";
							
		var query = prefixes + body;
		
		
	
		return query;
	}catch (error) {
        throw new flykit.UnexpectedException("flykit.flyted.Service._buildQueryForFindImagesByFlybaseGeneID", error);
    }
};



/**
 * Map a string to a list of strings via a supplied mapping table,
 * returnimng an empty list if the supplied key is not present. 
 * @param {String} key 		a key value to be mapped
 * @param {Object} table 	an object with members that are arrays of strings
 * @return an array of string values, which may be empty if the given key is not found
 * @type [String]
 */
flykit.flyted.Service.mapNameUsingTable = function ( key, table ) {
	try {
		var result = table[key];
		if (typeof result == "undefined" || !result ) {
			result = [];
		}
		return result;
	}catch (error) {
        throw new flykit.UnexpectedException("flykit.flyted.Service.mapNameUsingTable", error);
    }
};


/**
 * TDO doc me
 */
flykit.flyted.Image = function () {
	
	/**
	 * @type String
	 */
	this.recordURL = null;
	
	/**
	 * @type String
	 */
	this.thumbnailURL = null;
	
	/**
	 * @type String
	 */
	 
	this.flytedURL = null;
	
	/**
	 * @type String
	 */
	this.caption = null;
	
	/**
	 * @type String
	 */
	this.probe = null;
	

};


/**
 * TODO doc me
 */
flykit.flyted.Image.newInstancesFromSPARQLResults = function(resultSet){
	try {
		var bindings = resultSet.results.bindings;
		var imagePool = new flykit.flyted.ImagePool();
		var probePool = new flykit.flyted.ProbePool();
		
		for (var i=0; i<bindings.length; i++) {
			var binding = bindings[i];
			
			var imageURI = binding.recordURL.value;
			//TODO
			var image = imagePool.get(imageURI);
//			image.recordURL = binding.recordURL.value;
			image.thumbnailURL = binding.thumbnailURL.value;
			image.flytedURL = binding.flytedURL.value;
			image.caption = binding.caption.value;
			
			if (binding.probe){
				var probeURI = binding.probe.value;
				var probe = probePool.get(probeURI);
				
				if (!probe.probeLabels){
					probe.probeLabels = new Array();
				}
	
				if (binding.probeLabel) {
					var probeLabel = binding.probeLabel.value;
					flykit.util.appendIfNotMember(probe.probeLabels, probeLabel);
				}
				image.probe = probe;
			}		
		}
		
		return imagePool.toArray();
	}catch (error) {
        throw new flykit.UnexpectedException("flykit.flyted.Image.newInstancesFromSPARQLResults", error);
    }
};


flykit.flyted.ImagePool = function() {
	/**
	 * @private
	 */
	this._pool = new Object();
};

flykit.flyted.ImagePool.prototype.toArray = function() {
	try {
		var array = new Array();
		for (var key in this._pool) {
			array[array.length] = this._pool[key];
		}
		return array;
	} catch (error) {
        throw new flykit.UnexpectedException("flykit.flyted.ImagePool.prototype.toArray", error);
    }
};

flykit.flyted.ImagePool.prototype.get = function( imagepath ) {
	
	try {
		var image = this._pool[imagepath];
	
		if ( typeof image == "undefined" || !image ) {
			image = new flykit.flyted.Image();
			image.recordURL = imagepath;		
			this._pool[imagepath] = image;	
		}
		
		return image;
	} catch (error) {
        throw new flykit.UnexpectedException("flykit.flyted.ImagePool.prototype.get", error);
    }
};

flykit.flyted.ProbePool = function() {
	/**
	 * @private
	 */
	this._pool = new Object();
};

flykit.flyted.ProbePool.prototype.get = function( probeURI ) {
	
	try {
		var probe = this._pool[probeURI];
		
		if (!probe ) {
			probe = new Object();
			probe.probeURI = probeURI;
			this._pool[probeURI] = probe;	
		}
		
		return probe;
	} catch (error) {
        throw new flykit.UnexpectedException("flykit.flyted.ProbePool.prototype.get", error);
    }
};

flykit.flyted.ProbePool.prototype.toArray = function() {
	try {
		var array = new Array();
		for (var key in this._pool) {
			array[array.length] = this._pool[key];
		}
		return array;
	} catch (error) {
        throw new flykit.UnexpectedException("flykit.flyted.ProbePool.prototype.toArray", error);
    }
};


flykit.flyted.Service.transformResponseForFindImagesByFlybaseGeneIDBatch = function( response ) {
    var _context = "flykit.flyted.Service.transformResponseForFindImagesByFlybaseGeneIDBatch";
    try {
        
        /* Turn results of query into result object like...
         * {
         *   "FBgn0036925" : {
         * 	{
         *     "recordURL": { "type": "uri" , "value": "http://www.fly-ted.org/767/2/wt01.bmp" } ,
         *	   "thumbnailURL": { "type": "uri" , "value": "http://www.fly-ted.org/767/thumbnails/2/medium.jpg" } ,
         * 	   "flytedURL": { "type": "uri" , "value": "http://www.fly-ted.org/767/" } ,
         *     "caption": { "type": "literal" , "value": "schuy in wt" } ,
         * 	   "probe": { "type": "uri" , "value": "http://openflydata.org/id/flyted/probe/schuy" } ,
         *     "probeLabel": { "type": "literal" , "value": "schuy" }
		 *	},
		 *  {
         *     "recordURL": { "type": "uri" , "value": "http://www.fly-ted.org/1478/2/cg17736-wt.jpg" } ,
         *     "thumbnailURL": { "type": "uri" , "value": "http://www.fly-ted.org/1478/thumbnails/2/medium.jpg" } ,
         *     "flytedURL": { "type": "uri" , "value": "http://www.fly-ted.org/1478/" } ,
         *     "caption": { "type": "literal" , "value": "CG17736/schuy in wt" } ,
         *     "probe": { "type": "uri" , "value": "http://openflydata.org/id/flyted/probe/schuy" } ,
         *      "probeLabel": { "type": "literal" , "value": "schuy" }
      	 *	} ,
		 *  ...
		 * },
         *   "FBgn0004903" : {
         {
         *     "recordURL": { "type": "uri" , "value": "http://www.fly-ted.org/2365/2/aly01.bmp" } ,
         *	   "thumbnailURL": { "type": "uri" , "value": "http://www.fly-ted.org/2365/thumbnails/2/medium.jpg" } ,
         * 	   "flytedURL": { "type": "uri" , "value": "http://www.fly-ted.org/2365/" } ,
         *     "caption": { "type": "literal" , "value": "Rb97D in aly" } ,
         * 	   "probe": { "type": "uri" , "value": "http://openflydata.org/id/flyted/probe/Rb97D" } ,
         *     "probeLabel": { "type": "literal" , "value": "Rb97D" }
		 *	},
		 *  {
         *     "recordURL": { "type": "uri" , "value": "http://www.fly-ted.org/2366/2/wt01.bmp" } ,
         *     "thumbnailURL": { "type": "uri" , "value": "http://www.fly-ted.org/2366/thumbnails/2/medium.jpg" } ,
         *     "flytedURL": { "type": "uri" , "value": "http://www.fly-ted.org/2366/" } ,
         *     "caption": { "type": "literal" , "value": "Rb97D in wt" } ,
         *     "probe": { "type": "uri" , "value": "http://openflydata.org/id/flyted/probe/Rb97D" } ,
         *     "probeLabel": { "type": "literal" , "value": "Rb97D" }
      	 *	},
      	 *  ....
      	 * }
         * }
         */

        flykit.debug("response status: "+response.status, _context);
        flykit.debug("try parsing response text as json", _context);
        flykit.debug("parsing response: "+response.responseText, _context);

        var resultSet = YAHOO.lang.JSON.parse(response.responseText);
        
        flykit.debug("convert result set to a map of fbgns to images indexed by recordURL", _context);
        
        var map = {};
        var imagePool = new flykit.flyted.ImagePool();
        var bindings = resultSet.results.bindings;
        
        for (var i=0; i<bindings.length; i++) {
            var binding = bindings[i];
            var fbgn = binding["fbgn"].value;
         
            var imagepath = binding["recordURL"].value;
            flykit.debug("add image : " + imagepath + " for gene " + fbgn, _context);
			var image = imagePool.get(imagepath);
			
			flykit.debug("get image object: " + image.recordURL + " for gene " + fbgn, _context);
			
			image.thumbnailURL = binding["thumbnailURL"].value;
			image.flytedURL = binding["flytedURL"].value;
			image.caption = binding["caption"].value;
						
            if (typeof map[fbgn] == "undefined" || !map[fbgn]) {
                flykit.debug("initialising gene label: "+fbgn, _context);
                map[fbgn] = {"images":[]};
            }

                        
            var images = map[fbgn].images;
                        
            flykit.util.appendIfNotMember(images, image);
                        
        }
            
        return map;
    
    } 
    catch (unexpected) {
        flykit.debug("rethrowing "+unexpected.name+", "+unexpected.message, _context);
        throw unexpected;    
    }    
};

