express = require('express')
sync = require('./sync').sync
fs = require('fs')
coffee = require('coffee-script')

class ServiceRpc
	constructor: (@app, server, endpoint)->
		server.use(express.bodyParser())
		
		server.post(endpoint, (req, res)->
			sync ->
				[service,method] = req.body.method.split('.')

				params = req.body.params

				if not app.services[service] or not app.services[service][method]
					res.send({"jsonrpc": "2.0", "error": {"code": -32601, "message": "Procedure not found."} })
				else
					result = app.services[service][method](params...)	
					res.send({"jsonrpc": "2.0", "result": result})
		)

		server.get("#{endpoint}/rpc-client.js", (req, res)=>
			root = req.query.root || 'app'
			res.contentType('rpc-client.js')
			res.send(@rpcClient(root, endpoint))
		)

	rpcClient: (root, endpoint)->
		coffee_source = fs.readFileSync(__dirname + "/client-rpc.coffee", 'utf8')
		services = JSON.stringify @servicesInfo()
		coffee_source += "\nwindow.#{root} = new ServiceRpc('#{endpoint}', #{services})"
		js_source = coffee.compile(coffee_source)
		return js_source

	servicesInfo: ()->
		({name: name, methods: @methods(service)} for name,service of @app.services)

	methods: (obj)->
		(prop for prop,value of obj when @isFunction(value))
			
	isFunction: (obj)->
 		getType = {};
 		return obj && getType.toString.call(obj) == '[object Function]';

exports.ServiceRpc = ServiceRpc