/**
 * 
 * A class for communicating with the Flickr API
 *
 * @constructor
 * @author Stephen Calcott
 *
 * @param {String} api_key api_key given by flickr for use with this API
 * @param {String} secret (optional) The "secret" given by flickr - for use when authentication is required
 */
FlickrAPI = function (api_key, secret)
{
	/** 
	 * User information - stored if we have a user logged in and we're authenticated to know.
	 * @type Object
	 */
	this.user = {};
	/** 
	 * The last method requested to the API.
	 * @type String
	 */
	this.lastMethod = "";
	/** 
	 * The api_key passed in.
	 * @type String
	 */
	this.api_key = api_key ? api_key : "";
	/** 
	 * The secret passed in, for use in authentication.
	 * @type String
	 */
	this.secret = secret ? secret : "";
	/** 
	 * The api_sig generated by an MD5 munge, for authentication process and for further rights-enabled calls.
	 * @type String
	 */
	this.api_sig = "";
	/** 
	 * The frob passed back by flickr during authentication.
	 * @type String
	 */
	this.frob = "";
	/** 
	 * The auth_token generated by an MD5 munge.
	 * @type String
	 */
	this.auth_token = "";
	/** 
	 * The permission level we have for the current user, will mostly be "read".
	 * @type String
	 */
	this.perms = "";
	/** 
	 * A data object for storing more permanent data that is passed back.
	 * @type String
	 */
	this.data = {};
}

/**
 * 
 * Calls a flickr API function, returning data back to a callback function specified based on
 * optional parameters.
 *
 * @author Stephen Calcott
 *
 * @param {String} method The Flickr method to call
 * @param {String} callback The name of the function to handle the data passed back
 * @param {Object} params An object of parameters to send through to flickr
 */
FlickrAPI.prototype.callMethod = function (method, callback, params)
{
	var urlStart = "http://www.flickr.com/services/rest/?";
	if (!(params)) var params = {}; //if we have no params, create an empty object
	
	params.method = method;
	params.format = "json";
	params.jsoncallback = callback;
	params.api_key = this.api_key;

	//If we have an auth_token, add to our params and create an API sig
	if (this.auth_token)
	{
		params.auth_token = this.auth_token;
		params.api_sig = this.getAPISig(params);
	}
	
	//Set the last method to be what we called
	this.lastMethod = method;
	
	//Merge all name-val pairs into a &= querystring
	var url = urlStart + bbcjs.lib.string.obj2string(params);
	
	//Create a script element and append to the head
	var script = document.createElement("script");
	script.src = url;
	document.getElementsByTagName('head')[0].appendChild(script);
	this.cleanScripts(script);
}

//Currently Flickr returns JSON that calls the default function if it errors... so need to handle this
jsonFlickrApi = function (data)
{
	if (typeof(flickrErrorHandler)=="function") flickrErrorHandler(data);
	else bbcjs.trace("An error occured when calling the flickr API...\nMessage:\t"+data.message, 1);
}

/**
 * 
 * Creates a URL that flickr requires to allow authentication. The user will have to approve through this URL
 *
 * @author Stephen Calcott
 *
 * @param {String} perms The permission level required (read/write)
 * @param {String} callback The name of the function to handle the data passed back
 */
FlickrAPI.prototype.createLoginURL = function (perms)
{
	//our url to call:
	var loginURL = "http://www.flickr.com/services/auth/?";
	
	loginURL += "api_key=" + this.api_key + "&";
	loginURL += "perms=" + perms + "&";
	
	this.api_sig = hex_md5(this.secret + "api_key" + this.api_key + "perms" + perms);
	
	loginURL += "api_sig=" + this.api_sig;
	
	return loginURL;
}

/**
 * 
 * Converts a flickr "frob" to an "auth_token" for use in subsequent calls
 *
 * @author Stephen Calcott
 *
 * @param {String} frob The frob returned by flickr from their authentication URL
 * @param {String} callback The name of the function to handle the data passed back
 */
FlickrAPI.prototype.frob2token = function (frob, callback)
{
	var method = "flickr.auth.getToken";
	this.frob = frob;
		
	this.api_sig = hex_md5((this.secret + "api_key" + this.api_key + "formatjsonfrob" + this.frob + "jsoncallback" + callback + "method" + method));
	
	this.callMethod(method, callback, {api_sig:this.api_sig,frob:this.frob});
}

/**
 * 
 * Creates an "api_sig", which is generated per-call IF we have a token and we're passing parameters
 *
 * @author Stephen Calcott
 *
 * @param {Object} params The set of parameters to be sent to flickr's API call
 */
FlickrAPI.prototype.getAPISig = function (params)
{
	var ta = [];
	var sig = this.secret;
	for (var i in params) ta.push(i);
	ta.sort();
	
	for (i=0; i<ta.length; i++) {sig += ta[i] + params[ta[i]];}
	
	return hex_md5(sig);
}

/**
 * 
 * Cleans up previous script tag calls to flickr's API so we don't have many script tags.
 *
 * @author Stephen Calcott
 *
 * @param {Object} script The current script tag for an API call, NOT to be deleted in this run
 */
FlickrAPI.prototype.cleanScripts = function (script)
{
	var head = document.getElementsByTagName('head')[0];
	var scripts = document.getElementsByTagName("script");
	
	for (var i=0; i < scripts.length; i++)
	{
		if (scripts[i] != script && (scripts[i].src && (scripts[i].src.indexOf("flickr.com/services")!=-1)))
		{
			scripts[i].parentNode.removeChild(scripts[i]);
		}
	}
	
}