// create a namespace if not already defined
flykit.namespace("flykit.flybasepub");


/**
 * Create a service object.
 * @class
 * A wrapper for a flybase SPARQL endpoint.
 * @extends flykit.sparql.Service
 * @constructor 
 * @param {String} endpointURL the location of the flybase SPARQL endpoint
 */
flykit.flybasepub.Service = function( endpointURL ) {
	
	/**
	 * @private
	 */
	this._endpoint = endpointURL;
	
};

// extend
flykit.flybasepub.Service.prototype = new flykit.sparql.Service();



flykit.flybasepub.Service.prototype.findPubsByUniqueGeneName = function( fbgn, success, failure, limit ) {
	
	var _context = "flykit.flybasepub.Service.prototype.findPubsByUniqueGeneName";
	try {
        flykit.info("request: "+fbgn, _context);
        flykit.debug("request: "+fbgn, _context);
        flykit.debug("limit: "+limit, _context);
        var chain = flykit.chain(flykit.flybasepub.Service.responseToGene, success);
        var query = flykit.flybasepub.Service._buildQueryForFindPubsByUniqueGeneName(fbgn, limit);
        this.postQuery(query, chain, failure);    
    } catch (error) {
        flykit.debug("wrap and rethrow error to get a stack trace", _context);
        throw new flykit.UnexpectedException(_context, error);
    }   
};





flykit.flybasepub.Service.responseToGene = function( response ) {
    var _context = "flykit.flybasepub.Service.responseToGene";
    try {
        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 an array of publications", _context);
        //TODO
        var publications = flykit.flybasepub.Publication.newInstancesFromSPARQLResults(resultSet);
        return publications;
    } catch (error) {
        flykit.debug("wrap and rethrow error to get a stack trace", _context);
        throw new flykit.UnexpectedException(_context, error);
    }    
};

flykit.flybasepub.Service._buildQueryForFindPubsByUniqueGeneName = function( fbgn, limit ) {
    var _context = "flykit.flybasepub.Service._buildQueryForFindPubsByUniqueGeneName";
    try {

        var prefixes =  "PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>\n" +
                        "PREFIX chado: <http://purl.org/net/chado/schema/>\n" +
                        "PREFIX so: <http://purl.org/obo/owl/SO#>\n";

        var body =      "SELECT DISTINCT ?flybaseID ?pub ?title ?miniref ?uniquename WHERE {\n" +
                        "  ?flybaseID \n" +
                        "	 chado:uniquename	\"" + fbgn + "\"^^xsd:string ;\n" +
                        "    a so:SO_0000704 ;\n" +
                        "    chado:organism <http://openflydata.org/id/flybase/organism/Drosophila_melanogaster> ;\n" +
                        "    chado:feature_pub ?pub .\n" +
                        "	 ?pub a chado:Pub ;\n" +
    					"	 	chado:uniquename ?uniquename .\n" +
    					"  OPTIONAL { ?pub chado:title ?title }\n" +
    					"  OPTIONAL { ?pub chado:pyear ?pyear }\n" +
    					"  OPTIONAL { ?pub chado:miniref ?miniref }\n" +
    					"} orderby desc(?pyear) limit "+limit+"\n";
    							    					

        var query = prefixes + body;
    
        return query;
    } catch (error) {
        flykit.debug("wrap and rethrow error to get a stack trace", _context);
        throw new flykit.UnexpectedException(_context, error);
    }    

};


flykit.flybasepub.Publication = function() {
	var that = this ;
	
	this.flybaseID = null;
	
	this.pubID = null;
	
	this.title = "";
	
	this.pyear = "";
	
	this.miniref = "";
};

flykit.flybasepub.Publication.newInstancesFromSPARQLResults = function( resultSet ) {
    var _context = "flykit.flybasepub.Publication.newInstancesFromSPARQLResults";
    try {
		var pool = new flykit.flybasepub.PublicationPool();
				            
        var bindings = resultSet.results.bindings;
        
        for (var i in bindings) {
            var flybaseID = bindings[i].flybaseID.value;
            //flykit.debug("==== the flybaseID " + flybaseID);
            var pubID = bindings[i].pub.value;
            flykit.debug("==== the pubID " + pubID, _context);
            
            if (pubID.search(/unattributed/) == -1){
            
            	publication = pool.get(pubID);
            	publication.flybaseID = flybaseID;         
            	publication.uniquename = bindings[i].uniquename.value;
            	
            	if (bindings[i].title) {
            		publication.title = bindings[i].title.value;
            	}
            
            	if (bindings[i].pyear) {
                	publication.pyear = bindings[i].pyear.value;
            	}
	            if (bindings[i].miniref) {
	                publication.miniref = bindings[i].miniref.value;
	            }
            }
        }
            return pool.toArray();
    } catch (error) {
        flykit.debug("wrap and rethrow error to get a stack trace", _context);
        throw new flykit.UnexpectedException(_context, error);
    }    
};

flykit.flybasepub.PublicationPool = function() {
	
	/**
	 * @private
	 */
	this._pool = new Object();

};

/**
 * Get a publication from the pool, or create a new one if it doesn't exist.
 * @param {String} pubID 
 * @return a flykit.flybasepub.Publication object
 */
flykit.flybasepub.PublicationPool.prototype.get = function( pubID ) {
    var _context = "flykit.flybasepub.PublicationPool.prototype.get";
    try {
        var publication = this._pool[pubID];
        
        if ( typeof publication == "undefined" || !publication ) {
            publication = new flykit.flybasepub.Publication();
            publication.pubID = pubID;
            this._pool[pubID] = publication;   
        }
        
        return publication;
    
    } catch (error) {
        flykit.debug("wrap and rethrow error to get a stack trace", _context);
        throw new flykit.UnexpectedException(_context, error);
    }    	
};

flykit.flybasepub.PublicationPool.prototype.toArray = function() {
    var _context = "flykit.flybasepub.PublicationPool.prototype.toArray";
    try {
        var array = new Array();
        for (var key in this._pool) {
            array[array.length] = this._pool[key];
        }
//        function pubsort(x,y) {
//            if (x.pyear < y.pyear) return 1;
//            else return -1;
//        }
//        array.sort(pubsort);
        return array;
    } catch (error) {
        flykit.debug("wrap and rethrow error to get a stack trace", _context);
        throw new flykit.UnexpectedException(_context, error);
    }    
};

