Base = require('../base')

debug = Base.logger('ix-caller')

exportedProps = null


exports.ixCall = (callData, responder, invoker) ->
  timeoutSecs = Number(callData.timeout || Base.env.IX_PROXY_TIMEOUT)
  if !(timeoutSecs > 0) # careful about NaN / Number(undefined)
    timeoutSecs = 30 # default 30 seconds
  wait = timeoutSecs * 1000
  timerOn = true
  timer = setTimeout ->
    if timerOn
      timerOn = false
      err = 'TIMEOUT: Callback not invoked after '+(wait/1000)+' seconds, aborting. (Start server with the environment variable FAAS_IX_PROXY_TIMEOUT set to customize the timeout.)'
      debug('ixCall', err)
      responder({ reason: err })
  , wait
  clientCallback = (err, data) ->
    debug('clientCallback', { err: err, data: data })
    if err instanceof Error
      err =
        name: err.name
        message: err.message
    if timerOn
      timerOn = false
      clearTimeout(timer)
      responder(err, data)
  try
    invoker(callData, clientCallback)
  catch e
    clientCallback(e)

exports.ixCallNodejs = (callData, responder) ->
  debug('ixCallNodejs', callData)
  func = findProp(callData.api)
  if func
    exports.ixCall callData, responder, (cd, clientCallback) ->
      args = cd.args.slice(0)
      args.push(clientCallback)
      func.apply({}, args)
      # ////
      # // 2015-01-23:
      # // Support coffeescript more easily, don't support return values.
      # ////
      # // if (returnVal !== void(0)) {
      # //   // JSON doesn't easily differentiate between (undefined) and (null),
      # //   // so we can't transmit (undefined) across the wire.
      # //   // Therefore, use (null) as the "don't wait for the callback" value
      # //   // (instead of using a special Base.IX_RETURN_UNDEFINED value, that
      # //   // we try to convert to (undefined) when transmitting it back).
      # //   //clientCallback(null, returnVal === Base.IX_RETURN_UNDEFINED ? void(0) : returnVal)
      # //   // Always be async. http://nodejs.org/api/process.html#process_process_nexttick_callback
      # //   process.nextTick(function(){ clientCallback(null, returnVal) })
      # // }
  else
    debug('ixCallNodejs', "Property not exported: '"+callData.api+"'.")
    throw 'Invalid function: '+callData.api

exports.setNodejsExports = (exportedPropsInput) ->
  exportedProps = exportedPropsInput

findProp = (name) ->
  names = name.split('.')
  findPropHelper(names, exportedProps)

findPropHelper = (names, props) ->
  name = names.shift()
  prop = props[name]
  if prop && names.length > 0
    prop = findPropHelper(names, prop)
  prop
