﻿function Binom_WSCrossDomain(options)
{
	var IsArray = function (obj) { return obj.constructor.toString().toLowerCase().indexOf("array") != -1 ? true : false; };
	var ThrowError = function (msg, data) { if (options.error != null) options.error(msg, data); };
	var ValidateParams = function (definitions)
	{
		var valid = true;
		if (options.wsParams != undefined)
		{
			for (var prop in options.wsParams)
			{
				var located = false;
				for (var i = 0; i < definitions.length; i++)
				{
					if (definitions[i].name == prop)
					{
						var type = definitions[i].type.split(":")[1];
						if (options.wsParams[prop].constructor.toString().toLowerCase().indexOf(type.toLowerCase()) == -1) valid = false;
						located = true;
						break;
					}
				}
				if (!located) valid = false;
				if (!valid) break;
			}
		}
		return true;
	};

	var propCount = 0;
	var wsCall = options.wsUrl + "/" + options.wsMethod;
	if (options.wsParams != undefined)
	{
		for (var prop in options.wsParams)
		{
			wsCall += propCount > 0 ? "&" : "?";
			wsCall += prop.toString() + "=" + escape(options.wsParams[prop]);
			propCount++;
		}
	}

	var query = "SELECT * FROM xml WHERE url='{1}'";
	var wsdlQuery = query.replace("{1}", options.wsUrl + "?WSDL");
	query = query.replace("{1}", wsCall);

	$.yql(wsdlQuery, function (data)
	{
		var schema = null;
		try { schema = data.query.results.definitions.types.schema[0]; } catch (err) { }
		var request = null;
		var response = null;
		var responseType = null;
		var responseIsComplex = false;
		if (schema != null)
		{
			for (var i = 0; i < schema.element.length; i++)
			{
				if (schema.element[i].name == options.wsMethod) request = schema.element[i];
				if (schema.element[i].name == options.wsMethod + "Response") response = schema.element[i];
				if (request != null && response != null) break;
			}
		}
		else { ThrowError("invalid schema", data); }
		if (request != null && response != null)
		{
			var e = request.complexType != null ? request.complexType.sequence.element : null;
			if (e != null && !IsArray(e)) e = [e];
			if (e == null || e.length == propCount)
			{
				if (e == null || ValidateParams(e))
				{
					var r = response.complexType.sequence.element.type.split(":");
					if (r[0].toLowerCase() != "s") responseIsComplex = true;
					responseType = r[1];
					if (responseType != null)
					{
						// execute YQL as WS CALL
						$.yql(query, function (data)
						{
							if (data != null)
							{
								try
								{
									data = data.query.results[responseType];
									if (!responseIsComplex) data = data.content;
									if (options.success != null) options.success(data);
								}
								catch (err) { ThrowError("response format is invalid", data); }
							}
							else { ThrowError("response is null", null); }
						});
					}
					else { ThrowError("unknown response type", null); }
				}
				else { ThrowError("properties not set correct", null); }
			}
			else { ThrowError("properties count not correct", null); }
		}
	});
}

function Binom_WSOnDomain(options)
{
	var BuildParams = function ()
	{
		var output = null;
		var errOccurred = false;
		if (options.wsParams != undefined)
		{
			var params = new Array();
			for (var prop in options.wsParams) params.push({ name: prop, value: options.wsParams[prop] });
			if (params.length > 0)
			{
				output = "{";
				$(params).each(function (index)
				{
					try
					{
						output += "\"" + params[index].name + "\"" + ":" + "\"" + params[index].value.toString() + "\"";
						if (index < params.length - 1) output += ",";
					}
					catch (err) { errOccurred = true; }
				});
				output += "}";
			}
		}
		if (errOccurred == true) output = null;
		return output;
	};
	$.ajax(
	{
		type: 'POST',
		url: options.wsUrl + "/" + options.wsMethod,
		data: BuildParams(),
		contentType: 'application/json; charset=utf-8',
		dataType: 'json',
		success: function (data)
		{
			if (options.success != undefined) options.success(data);
		},
		error: function (msg)
		{
			if (options.error != undefined) options.error(msg, null);
		}
	});
}

(function ($)
{
	$.extend(
	{
		ws: function (options)
		{
			if (options.wsUrl != undefined && options.wsMethod != undefined)
			{
				if (options.crossdomain == true && options.YQLSrc != undefined)
				{
					$.getScript(options.YQLSrc, function ()
					{
						new Binom_WSCrossDomain(options);
					});
				}
				else
				{
					new Binom_WSOnDomain(options);
				}
			}
		}
	});
})(jQuery);
