Sparcq = ( this["Sparcq"] || {}  );


if (!Sparcq.API) {
	Sparcq.API = function (settings) {
		this.init(settings);
	};
}


Sparcq.API.prototype.init = function(args) {
	this.api_version = '1.000';
	this.server_location = args.server_location || 'prod';
	this.hostname = args.hostname || 'http://www.sparcq.com';
	this.format = 'jsonp';
	this.currAcCount = 0;
	this.setMethods();

};

Sparcq.API.prototype.doWikiCall = function(args) {
	var url = 'http://en.wikipedia.org/w/api.php';

	var namespaces = {
		'Main': 0,
		'Talk': 1,
		'User': 2,
		'User talk': 3,
		'Wikipedia': 4, 
		'Wikipedia talk': 5,
		'File': 6, 
		'File talk': 7,
		'MediaWiki': 8,
		'MediaWiki talk': 9,
		'Template': 10,
		'Template talk': 11,
		'Help': 12,
		'Help talk': 13,
		'Category': 14,
		'Category talk': 15,
		'Portal': 100,
		'Portal talk': 101
	};

	args.request_params.namespace = args.request_params.namespace || namespaces.Main;

	args.request_params.format = args.request_params.format || 'json';	
	var wait_timeout = 15000;

	var self = this;

	jQuery.jsonp({
		url: url,
		callbackParameter: 'callback',
		success: function(resp,rt_string) {
			if (resp && resp.length > 1) {
				var newArray = resp[1];
				var pattern = /Portal\:|Talk\:|Category\:/i;

				for (var i = 0; i < newArray.length; i++)
					if (newArray[i].match(pattern))
						newArray.splice(i,1);
				resp = newArray;
			}
			args.success_callback.call(this,resp);
		},
		error: function(error_obj,rt_string) {
			args.error_callback.call(this,{ 
				error_obj: error_obj,
				return_type: rt_string,
				request_params: args.request_params
			});
		},
		timeout: wait_timeout,
		data: args.request_params
	});

}

Sparcq.API.prototype.getWikiEntry = function(q,args) {
	if (!args || !args.onSuccess) {
		this.throwError('need to pass on success ');
		return;
	}
	
	var success_callback = args.onSuccess; 
	var error_callback = (args.onError) ? args.onError : this.throwError;	
	
	var request_params = {
		action: 'parse',
		page: q,
		redirects: 1,
		prop: 'text'
	};
	this.doWikiCall({
		success_callback: success_callback,
		error_callback: error_callback,
		request_params: request_params
	});
}

Sparcq.API.prototype.doOpenSearch = function(q,args) {

	if (!args || !args.onSuccess) {
		this.throwError('need to pass on success ');
		return;
	}
	var success_callback = args.onSuccess; 
	var error_callback = (args.onError) ? args.onError : this.throwError;
	var request_params = {
		suggest: 1,
		action: 'opensearch',
		search: q,
		limit: 50
	};
	
	this.doWikiCall({
		success_callback: success_callback,
		error_callback: error_callback,
		request_params: request_params
	});
}

Sparcq.API.prototype.doSparcqSearch = function(q,args) {

	if (!args || !args.onSuccess) {
		this.throwError('need to pass on success ');
		return;
	}
	var success_callback = args.onSuccess; 
	var error_callback = (args.onError) ? args.onError : this.throwError;


	this.callMethod('topic.search', {
		params: {
			q: q
		},
		onSuccess: function(resp,rt_string) {	
			if (resp && resp.response.result) {
				resp = resp.response.result.topics;
			}
			success_callback.call(this,resp);
		},
		onError: function(error_obj,rt_string) {
			
			error_callback.call(this,{ 
				error_obj: error_obj,
				return_type: rt_string,
				request_params: { q: q }
			});
		}
		//onSuccess: success_callback, 
		//onError: error_callback, 
	}); 

}

Sparcq.API.prototype.initSparcqAutocomplete = function(el,args) {
	if (!el) return;
	var self = this;
	el.autocomplete(function(ret) { 
		self.doSparcqSearch(el.val(),ret);
	}, {
		delay: 100,
		mustMatch: true,
		highlightItem: false,
		formatItem: function(row, i, max, smth, erm) {
			if (row) {
				return row.name.replace(new RegExp("(" + term + ")", "gi"), "<strong>$1</strong>") + "<div style='font-size: 80%;overflow:hidden;height:44px'" + row.description + "</div>";
			}
			return "";
		},
		formatResult: function(res) {
			if (res) {
				return res.name;
			}
		}
	});

};

Sparcq.API.prototype.bgLoadWiki = function(el_id) {
	var el = jQuery('#' + el_id);
	if (el) {
		SPARCQ.COMPONENTS.retrieveWikiText(el,"autocomplete_item");
	}
};

Sparcq.API.prototype.initOpenSearchElement = function(el,args) {
	if (!el) return;
	var self = this;
	var cntr = 0;
	el.autocomplete(function(ret) { 
		self.doOpenSearch(el.val(),ret);
	},{
		delay: 100,
		mustMatch: true,
		highlight: false,
		formatItem: function(row,i,max,smth,term) {
			if (row) {
				var ans = row;
				var unique_id = 'uniquer_' + parseInt(self.currAcCount++);
				row = "<div id='" + unique_id + "' onmouseover='return SPARCQ.COMPONENTS.retrieveWikiText(this,\"autocomplete_item\");' class='autocomplete_word'>" + 
				row.replace(new RegExp("(" + term + ")", "gi"), "<strong>$1</strong>") + 
				"<div class='autocomplete_item'><span class='the_title'>" + ans + "</span></div></div>"; 
				//setTimeout(function() { self.bgLoadWiki(unique_id) }, cntr*1500 + 300);
				cntr++;
				return row;
			}
		},
		formatResult: function(res) {
			if (res) return res;
		}
	});
}

Sparcq.API.prototype.getPath = function(args) {
	var api_path = this.hostname;

	var url = api_path + '/' + this.api_version + '/' + args.api_method + '?format=' + this.format + '&' + 'jsoncallback=?';
	if (args.params) {
		for (query_param in args.params) {
			url += '&' + query_param + '=' + encodeURIComponent(args.params[query_param]);
		}
	}

	return url;
};

Sparcq.API.prototype.getData = function(args) {
	if (!args.onSuccess) {
		this.throwError('request not made');
		return;
	}

	//pass these for all user login dependent methods....
	
	if (!args.params) args.params = {};
	args.params.session_key = SPARCQ.SESSION.getSessionKey();
	args.params.session_type = SPARCQ.SESSION.getSessionType();
	args.params.session_uid = SPARCQ.SESSION.getSessionUid();
	args.params.token = SPARCQ.SESSION.getToken();

	var url = this.getPath(args);
	var success_callback = args.onSuccess;
	var error_callback = (args.onError) ? args.onError : this.throwError;
	var wait_timeout = 15000;
	var self = this;

	var request_params = args;
		
	jQuery.jsonp({
		url: url,
		success: function(resp,rt_string) {
			self.handleMethodReturn({
				is_error: false,
				response: resp,
				error_callback: error_callback,
				success_callback: success_callback,
				return_type: rt_string,
				request_params: request_params
			});
		},
		error: function(error_obj,rt_string) {
			self.handleMethodReturn({
				is_error: true,
				error_callback: error_callback,
				error_obj: error_obj,
				return_type: rt_string,
				request_params: request_params
			});
		},
		timeout: wait_timeout
	});
};

Sparcq.API.prototype.throwError = function(msg,args) {
	var resp_error = 'unknown error';
	if (msg) {
		if (typeof(msg) == 'object') {
			resp_error = msg.return_type;
		} else {
			resp_error = msg;
		}
	}
	if (args && args.onError) {
		args.onError.call(this,resp_error);
	} else {	
		alert("Error: " + resp_error);
	}
};


Sparcq.API.prototype.trim = function(txt){
 	return txt.replace(/\w+$/, '');
};

Sparcq.API.prototype.getExpectedReturn = function(method_name) {
	return this.methodAvailable(method_name);	
}

Sparcq.API.prototype.setMethods = function() {
	this.availableMethods = {
		site: {
			getTopList: { return_type: 'TOPIC_LIST' },
			getTopUsers: { return_type: 'USER_LIST' },
			getDetail: { return_type: 'SITE' },
			search: { return_type: 'MIXED_LIST' },
			checkAvailable: { return_type: 'SPARCQ_RETURN' }
		},
		user: {
			getIntroductoryTopics: { return_type: 'TOPIC_LIST' },
			isValidSession: { return_type: 'USER' },
			authenticate: { return_type: 'USER' },
			endSession: { return_type: 'SPARCQ_RETURN' },
			register: { return_type: 'ACCOUNT' },
			getLoginAccounts: { return_type: 'ACCOUNT_LIST' },
			authorizeExtraAccount: { return_type: 'SPARCQ_RETURN' },
			getNextTopic: { return_type: 'TOPIC' },
			getRatingForTopic: {  return_type: 'TOPIC' },
			getTags: { return_type: 'TAG_LIST' },
			getRecentRatings: { login_only: true, return_type: 'TOPIC_LIST' },
			getRecommendedTopics: { login_only: true, return_type: 'TOPIC_LIST' },
			searchRecommendedTopicTags: { login_only: true, return_type: 'SPARCQ_RETURN' },
			getDetail: { return_type: 'USER' },
			getComments: { return_type: 'COMMENT_LIST' },
			getEstimatedSimilarUsers: { return_type: 'USER_LIST' },
			checkByFacebookId: { return_type: 'SPARCQ_RETURN' },
			isLinkedWithService: { return_type: 'SPARCQ_RETURN' },
			linkAccountWithService: { return_type: 'URL_REDIRECT' },
			unlinkAccountWithService: { return_type: 'SPARCQ_RETURN' },
			completeLinkAccountWithService: { return_type: 'URL_REDIRECT' },
			saveFacebookOfflineSessionKey: { return_type: 'URL_REDIRECT' },
            friendMemberOnService: { return_type: 'SPARCQ_RETURN' },
            unfriendMemberOnService: { return_type: 'SPARCQ_RETURN' },
            postStoryOnService: { return_type: 'SPARCQ_RETURN' },
            sendMessageOnService: { return_type: 'SPARCQ_RETURN' },
			getAccountPreferences: { return_type: 'USER_PREFERENCES' },
			setAccountPreferences: { return_type: 'SPARCQ_RETURN' },
			addJavascriptJob: { return_type: 'SPARCQ_RETURN' },
			removeJavascriptJob: { return_type: 'SPARCQ_RETURN' },
			getJavascriptJobs: { return_type: 'JOB_LIST' }
		},
		topic: {
			getPredictedRating: { return_type: 'TOPIC' },
			getRating: { return_type: 'TOPIC' },
			getRecentRatings: { return_type: 'TOPIC_LIST' },
			getTags: { return_type: 'TAG_LIST' },
			getDetail: { return_type: 'TOPIC' },
			getRelatedTopics: { return_type: 'TOPIC_LIST' },
			getComments: { return_type: 'COMMENT_LIST' },
			search: { return_type: 'TOPIC_LIST' },
			skip: { return_type: 'TOPIC' },
			addRating: { return_type: 'TOPIC' },
			addRatings: { return_type: 'TOPIC_LIST' },
			deleteRating: { return_type: 'TOPIC' },
			addTags: { return_type: 'SPARCQ_RETURN' },
			deleteTags: { return_type: 'SPARCQ_RETURN' },
			addComment: { return_type: 'COMMENT' },
			deleteComment: { return_type: 'SPARCQ_RETURN' }
		},
		comment: {
			getDetail: { return_type: 'COMMENT' },
			addRating: { return_type: 'COMMENT' }
		},
		tag: {
			getUsers: { return_type: 'USER_LIST' },
			getTopics: { return_type: 'TOPIC_LIST' }
		}
	};

	this.returnTypes = {
		COMMENT: {},
		COMMENT_LIST: {},
		TOPIC: {},
		TOPIC_LIST: {},
		USER: {},
		USER_LIST: {},
		TAG: {},
		TAG_LIST: {},
		SITE: {},
		ACCOUNT: {},
		ACCOUNT_LIST: {},
		MIXED_LIST: {},
		SPARCQ_RETURN: {},
		URL_REDIRECT: {},
		USER_PREFERENCES: {},
        JOB_LIST: {},
		NOT_IMPLEMENTED: {},
		UNKNOWN_TYPE: {}
	};

	this.returnStatuses = {
		OK: 200,
		BAD_REQUEST: 400,
		UNAUTHORIZED: 401,
		FORBIDDEN: 403,
		NOT_FOUND: 404,
		BAD_METHOD: 405,
		ERROR: 500
	};
};

Sparcq.API.prototype.parseReturn = function(rt_type,ret_resp) {
	var ret = {};
	if (!this.returnTypes[rt_type]) {
		return false;
	}
	switch(rt_type) {
		case 'SITE':
			return ret_resp.site;
			break;
		case 'USER':
			return ret_resp.user;
			break;
		case 'USER_LIST':
			return ret_resp.user_list;
			break;
		case 'TOPIC_LIST':
			if (ret_resp['topics']) {
				return ret_resp.topics;
			}
			return ret_resp.topic_list;
			break;
		case 'TOPIC':
			return ret_resp.topic;
			break;
		case 'COMMENT':
			return ret_resp.comment;
			break;
		case 'URL_REDIRECT':
			return ret_resp.redirect;
			break;
		case 'USER_PREFERENCES':
			return ret_resp.preferences;
			break;
		case 'COMMENT_LIST':
			return { 
				comment_count: ret_resp.comment_count,
				comments: ret_resp.comments,
				page: ret_resp.page,
				total_pages: ret_resp.total_pages
			};
			break;
        case 'JOB_LIST':
            return ret_resp.jobs;
            break;
		default: 
			return false;
	}
};

Sparcq.API.prototype.handleMethodReturn = function(args) {
	/*
	is_error: true,
	error_callback: error_callback,
	error_obj: error_obj,
	return_type: rt_string,
	request_params: request_params
	*/
   
	if (args.is_error) {
		args.error_callback.call(this,args);
		return;
	}
	//validate return here
	try {
		var resp = args.response;
		var method_name = resp.method;
		var expected_return = this.getExpectedReturn(method_name);	
		var actual_return = resp.result.return_type;
		if (expected_return == actual_return) {
		} else {
			//return;
		}
		args.parsed_return = this.parseReturn(expected_return,resp.result);	
		args.success_callback.call(this,args);
		return;
	} catch(e) {
	}
	args.error_callback.call(this,args);
}

Sparcq.API.prototype.methodAvailable = function(method_name) {
	if (!method_name) return false;
	var method_parts = method_name.split(".");
	if (method_parts && method_parts.length == 2) {
		if (this.availableMethods[method_parts[0]]) {
			if (this.availableMethods[method_parts[0]][method_parts[1]]) {
				return this.availableMethods[method_parts[0]][method_parts[1]].return_type;
			}
		}
	}
	return false;
};

Sparcq.API.prototype.testMethod = function() {

};


Sparcq.API.prototype.callMethod = function(method_name,args) {
	if (!this.methodAvailable(method_name)) {
		this.throwError('method ' + method_name + ' unavailable');
		return false;
	}
	if (!args) {
		this.throwError('must pass args',args);
		return false;
	}
	if (!args.onSuccess) {
		this.throwError('must pass args success callback ',args);
		return false;
	}

	if (!args.onError) {
		this.throwError('must pass args error callback ',args);
		return false;
	}

	this.getData({
			onSuccess: args.onSuccess, 
			onError: args.onError, 
			api_method: method_name,
			params: args.params || {}
	});
	
	return true;
};

