(function(exports){
	'use strict'
	
	exports.RPC = function(url, methods) {
		var rpc_id=0, sid="";
		
		// Функция запроса RPC
		var call = function(name) {
			// Получаем аргументы
			var args=Array.prototype.slice.call(arguments, 1);
			
			if ( (args.length == 1) && ('object' == typeof args[0]) )
				args=args[0];
			
			// Собираем запрос
			rpc_id++;
			var json={
				jsonrpc: "2.0",
				method: name,
				params: args,
				id: rpc_id,
			};
			fs.write("tmp/post.bin", JSON.stringify(json));
			
			// Отправляем запрос
			if (net.httpPost(url+((sid!="") ? ("?"+sid) : ""), "tmp/post.bin", "tmp/get.bin", "Запрос к серверу...", { "Content-Type": "application/json" }) != 200)
				throw new Error("RPC: post failed");
			
			// Читаем ответ
			json=fs.read("tmp/get.bin");
			try
			{
				json=JSON.parse(json);
			} catch (e)
			{
				print("Bad JSON: '"+json+"'");
				throw new Error("RPC: bad json");
			}
			
			// Проверяем поля
			if (json.jsonrpc != "2.0") throw new Error("RPC: bad jsonrpc version");
			if (json.id != rpc_id) throw new Error("RPC: id mismatch");
			if ('error' in json)
			{
				throw new Error("RPC: "+json.error.message+" ("+json.error.code+")");
			}
			if (! ('result' in json)) throw new Error("RPC: no result");
			
			// Обновляем сессию
			if ('sid' in json)
				sid=""+json.sid;
			
			// Готово
			return json.result;
		};
		this.call=call;
		
		// Привязываем все методы
		if (Array.isArray(methods))
		{
			for (var i=0; i<methods.length; i++)
				this[methods[i]] = call.bind(this, methods[i]);
		}
	}
	
})(typeof exports === 'undefined' ? this['_jsonrpc_js']={} : exports);
