// Requires jQuery >= 1.4.2, Facebook Javascript SDK

// Binds together both services (Facebook and our application) and our
// expectations about views
// To Use:
//
// window.LOL = window.configureTheLOL({ app_root: root_url_of_app })
//
// Then
//
// myAwesomeLOL1 = window.LOL(pid1, caption1, optional_server_info, optional_fb_info);
// window.LOL.loadlols({ type: 'all', limit: 10, offset: 0 }, drawlols)
//
window.configureTheLOL = function(config) {

    var counter = 0;
    var new_id = function() {
 	counter = counter + 1;
	return counter;
    }



    // CONCERNS: Knows how to build appropriate URLS and interpret
    // information from the app server. 
    //
    // HEY, YOU! KNOW THAT THIS AFFECTS YOUR SERVER URLS!
    // All kinds of duplicate knowledge about how to construct URLS
    // in the app is encoded here!
    var AppServer = {
	
	// query_type in 'all', 'my_friends', 'mine',
	// offset, limit integers
	// listener 
	browse_query: function(query_type, offset, limit, listener) {
	    var data_url = config.app_root + "find/" + query_type + "/" + offset + "," + limit;

	    $.getJSON(data_url, function(data, status) {	    
		// TODO ERROR HANDLING- Likely go nuclear here, since
		// if we can't service these URLS something has gone bad crazy...
		var results = $.map(data, function(datum) {
		    return window.LOL(datum.photo_fb_id, datum.caption, datum);
		});
	    
		listener(results);
	    });

	},


	// config/urlresolver friendly! (For now!)
	create_form_url: function() {
	    return config.create_url;
	}

    };

    // mutilates the given fields object in-place,
    // accepts (and returns) false arguments gracefully.
    var PhotoInfo = function(fields_or_false) {
	
	if(fields_or_false) {
	    fields_or_false.aspect_ratio = function() {
		var aspect_ratio = this.width/this.height;
		return (aspect_ratio < 1 ? "lol-tall" : "lol-wide");
	    }
	}

	return fields_or_false;
    }

    // CONCERNS: Knows how to get photo information from facebook
    // and present different API in a common format, that being
    // {
    //   object_id: the GRAPH API object id of the image (*NOT the pid*)
    //   source: big image url,
    //   picture: thumbnail image url,
    //   width: width of big image,
    //   height: height of big image,
    //   owner: Facebook UID of owner of the photo
    // }
    var FacebookPhotos = {

	// Calls listener(photo) for each photo found. Fails silenty if
	// it can't load photos for some reason.
	photos_for_user: function(fb_user_id, offset, limit, listener) {

	    var query = "SELECT pid, object_id, owner, src_small, src_big, src_big_width, src_big_height " +
                        "FROM photo " +
	                "WHERE aid IN " +
	                "(SELECT aid FROM album WHERE owner=" + fb_user_id + ") " +
	                "LIMIT " + limit + " OFFSET " + offset;

	    FB.api({ method : "fql.query", query : query  },
		   function(found) {
		       $.each(found, function(ix, result) {
			   listener(PhotoInfo({ 
			       object_id: result.object_id,
			       source: result.src_big, 
                               owner: result.owner,
                               picture: result.src_small,
                               width: result.src_big_width,
                               height: result.src_big_height 
                           }));
		       });//each
		   }); //found
	},

	// Calls listener(info), POSSIBLY WITH null on error.
	photo_info : function(photo_object_id, listener) {
	    FB.api(photo_object_id,
		   function(result) {
		       var photo_info = null
		       if(result) {
			   photo_info = PhotoInfo({ 
			       object_id: result.id,
			       source: result.source, 
			       picture: result.picture, 
			       width: result.width,
			       height: result.height,
			       owner: result.from.id 
			   });
		       }

		       listener(photo_info);
		   });
	}

    };


    // CONCERNS: Binding together the data sources AND control layers for
    // Facebook and our Application server.
    //
    // object_id: facebook photo id (NOT pid, the full on object_id)
    // caption: Delightfully clever text
    //
    // server_info: Optional description of a server peer to this
    // object, including both Model and Control layer info for managing
    // this lol. If null, assumed that this lol has no peer on the server.
    //
    // photo_info, if provided, is a middle ground between the FQL
    // results for photo and the graph API results. In particular, we expect
    // { 
    //   source: URL for full sized version of photo,
    //   owner: Facebook UID of owner,
    //   picture: URL for album sized version of photo,
    //   width: width of full sized image, in px
    //   height: height of full sized image, in px
    // }
    //
    var constructor = function(object_id, caption, 
	                       server_info /* optional */, 
			       photo_info /* optional */){

	return {

	    caption: function() { return caption; },

	    edit_form_url: function() { return AppServer.create_form_url(); },

	    // MIGHT BE NULL!
	    share_url: function() {
		var ret = null;
		if(server_info) ret = server_info.share_url;
		return ret;
	    },

	    // calls listener with a photo_info object, or
	    // null if the info can't be aquired.
	    photo_info: function(listener) {
		if(photo_info) {
		    listener(photo_info);
		}
		else {
		    FacebookPhotos.photo_info(object_id, function(result) {
			photo_info = result;
			listener(photo_info);
		    });
		}
	    }


	};//returned object


    }// Constructor


    
    // Loads an array of (Server-Peerless) LOLS from a slice
    // of the given user's photo library, passes them to listener
    // one at a time.
    //
    // query is { fb_user_id : a user id, fb_photo_ids: [ some photo ids ] },
    //
    constructor.loadLOLSFromPhotos = function(query, offset, limit, listener) {

	var tell_lol = function(found_photo) {
	    var newlol = constructor(found_photo.object_id, "", null, found_photo);
	    listener(newlol);
	}

	if("undefined" != typeof query["fb_user_id"]) {
	    var fb_user_id = query.fb_user_id;

	    FacebookPhotos.photos_for_user(fb_user_id, offset, limit, tell_lol);
	}

	if("undefined" != typeof query["fb_photo_ids"]) {
	    $.each(query.fb_photo_ids, function(ix, fb_photo_id) {
		FacebookPhotos.photo_info(fb_photo_id, tell_lol);
	    });
	}
    }

    // query is { type: ("all","my_self","my_friends"), 
    //            offset: int from 0, 
    //            limit: int count }
    // all of which are optional.
    constructor.loadlols = function(query, listener) {

	if(!query) { query = {}; }

	var offset = 0;
	if("undefined" != typeof query["offset"]) {
	    offset = query["offset"];
	}

	var limit = 1000;
	if("undefined" != typeof query["limit"]) {
	    limit = query["limit"];
	}
	
	var qtype = "all";
	if("undefined" != typeof query["type"]) {
	    qtype = query["type"];
	}

	AppServer.browse_query(qtype, offset, limit, listener);

    };


    return constructor
}




