// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/**
 * @fileoverview Defines an invoker to invoke service methods.
 * @private
 */

module.exports = Invoker;

var createSignatures = require('../vdl/create-signatures');
var isPublicMethod = require('../lib/service-reflection').isPublicMethod;
var verror = require('../gen-vdl/v.io/v23/verror');
var capitalize = require('../vdl/util').capitalize;
var isCapitalized = require('../vdl/util').isCapitalized;
var format = require('format');
var context = require('../context');
var asyncCall = require('../lib/async-call');
var InspectableFunction = require('../lib/inspectable-function');

// Method signatures for internal methods that are not present in actual
// signatures.
// These signatures are meant to simplify the implementation of invoke
// and may be partial.
var internalMethodSignatures = {
  __glob: {
    name: '__glob',
    outArgs: []
  },
  __globChildren: {
    name: '__globChildren',
    outArgs: []
  }
};

/**
  * Create an invoker.
  * @param {Service} service Service object.
  * @constructor
  * @private
  */
function Invoker(service) {
  if (!(this instanceof Invoker)) {
    return new Invoker(service);
  }

  var invoker = this;

  invoker._service = service;
  invoker._signature = createSignatures(service, service._serviceDescription);
  invoker._methods = {};

  // See comment in src/vdl/reflect-signature.js for..in loop
  for (var key in service) { // jshint ignore:line
    if (!isPublicMethod(key, service)) {
      continue;
    }

    if (isCapitalized(key)) {
      throw new Error('Can\'t export capitalized method ' + key);
    }

    var capitalizedMethodName = capitalize(key);
    var method = service[key];

    var inspectableFn = new InspectableFunction(method);
    // Check whether the number of args reported by javascript (method.length)
    // and the number of args retrieved from fn.toString() are the same.
    // This usually differs if the method is a native method.
    if (inspectableFn.names.length !== method.length) {
      throw new Error('Function "' + key + '" can not be inspected. ' +
        'This is usually because it is a native method or bind is used.');
    }

    invoker._methods[capitalizedMethodName] = {
      name: capitalizedMethodName,
      fn: inspectableFn
    };
  }


  var fn;
  if (typeof service.__glob === 'function') {
    fn = new InspectableFunction(service.__glob);
    if (fn.filteredNames.length !== 1 ||
        fn.names.indexOf('$stream') === -1) {
      // TODO(bjornick): Throw a verror of appropriate type.
      throw new Error(
        '__glob needs to take in a string and be streaming');
    }

    this._methods.__glob = {
      name: '__glob',
      fn: fn
    };
  }

  if (typeof service.__globChildren === 'function') {
    fn = new InspectableFunction(service.__globChildren);
    if (fn.filteredNames.length !== 0 ||
        fn.names.indexOf('$stream') === -1 ) {
      // TODO(bjornick): Throw a verror of appropriate type.
      throw new Error(
        '__globChildren needs to take in no args and be streaming');
    }

    this._methods.__globChildren = {
      name: '__globChildren',
      fn: fn
    };
  }
}

Invoker.prototype.hasGlobber = function() {
  return this.hasMethod('__glob') || this.hasMethod('__globChildren');
};

/**
 * Find a method signature corresponding to the named method.
 *
 * @param {String} methodName - The name of the method
 * @return {MethodSignature} The signature of the named method, or null.
 * @private
 */
Invoker.prototype._findMethodSignature = function(methodName) {
  for (var i = 0; i < this._signature.length; i++) {
    var sig = this._signature[i];
    if (sig.methods) {
      for (var m = 0; m < sig.methods.length; m++) {
        var method = sig.methods[m];
        if (method.name === methodName) {
          return method;
        }
      }
    }
  }
  return null;
};

/**
 * Invoker.prototype.invoke - Invoke a method
 *
 * @param  {String} name - The upper camel case name of the method to invoke.
 * @param  {Array} args - A list of arguments to call the method with, may
 * differ because of injections e.g. function x(a,$stream,b) => [0, 2].
 * @param  {Object} injections - A map of injections, should always
 * contain `context`, could also contain `stream`
 * e.g. function(ctx, x, $stream, b)
 * @param  {Invoker~invokeCallback} cb - The callback fired after completion.
 */
Invoker.prototype.invoke = function(name, args, injections, cb) {
  // TODO(jasoncampbell): Maybe throw if there are unkown injections

  var message;
  var err;

  var invoker = this;
  var method = invoker._methods[name];
  var errorContext = injections.context || new context.Context();
  if (!method) {
    message = format('Method "%s"', name);
    err = new verror.NoExistError(errorContext, message);

    cb(err);
    return;
  }
  var methodSig = this._findMethodSignature(name) ||
    internalMethodSignatures[name];
  if (!methodSig) {
    cb(verror.InternalError(errorContext,
                            'Missing method signature for method ' + name));
  }

  if (!injections.context) {
    message = 'Can not call invoker.invoke(...) without a context injection';
    err = verror.InternalError(errorContext, message);
    cb(err);
    return;
  }

  var arity = method.fn.arity();

  // Check argument arity against the method's declared arity
  if (args.length !== arity) {
    var template = 'Expected %d arguments but got "%s"';

    message = format(template, arity, args.join(', '));
    err = new verror.BadArgError(errorContext, message);
    cb(err);
    return;
  }

  // Clone the array so we can simply manipulate and apply later
  var clonedArgs = args.slice(0);

  // call and context go in front
  clonedArgs.unshift(injections.call);
  clonedArgs.unshift(injections.context);

  // splice in stream
  if (injections.stream) {
    var start = method.fn.position('$stream');
    var deleteCount = 0;

    clonedArgs.splice(start, deleteCount, injections.stream);
  }

  asyncCall(injections.context, invoker._service, method.fn,
    methodSig.outArgs.length, clonedArgs, cb);
};

/**
 * This callback is fired on completion of invoker.invoke.
 * @callback Invoker~invokeCallback
 * @param {Error} err
 * @param {results} results
 */

/**
 * Return the signature of the service.
 * @return {Object} The signature
 */
Invoker.prototype.signature = function() {
  return this._signature;
};


/**
 * returns whether the function <name> is invokable.
 * @param {string} name the name of the function
 * @return {boolean} whether the function is invokable.
 */
Invoker.prototype.hasMethod = function(name) {
  return !!this._methods[name];
};
