{% import 'functional.cpp' as functional %}
/*
 * file:   {{clss.name}}Bridge.cpp
 * author: A trusty code generator
 *
 * This file was autogenerated, do not modify.
 * See LICENSE for full modification and redistribution details.
 * Copyright 2018 The OpenCV Foundation
 */
#include <mex.h>
#include <vector>
#include <string>
#include <opencv2/matlab/map.hpp>
#include <opencv2/matlab/bridge.hpp>
#include <opencv2/core.hpp>
using namespace cv;
using namespace matlab;
using namespace bridge;

namespace {

typedef std::vector<Bridge> (*)({{clss.name}}&, const std::vector<Bridge>&) MethodSignature;

{% for function in clss.methods %}

{% if function.constructor %}
// wrapper for {{function.name}}() constructor
{{ function.clss }} {{function.name}}(const std::vector<Bridge>& inputs) {
  {{ functional.handleInputs(function) }}
  {{ functional.compose(function) }}
  return obj;
}
{% else %}
// wrapper for {{function.name}}() method
std::vector<Bridge> {{function.name}}({{clss.name}}& inst, const std::vector<Bridge>& inputs) {
  std::vector<Bridge> outputs{% if function|noutputs %}({{function|noutputs}}){% endif %};
  {{ functional.handleInputs(function) }}
  {{ functional.composeWithExceptionHandler(function) }}
  {{ functional.handleOutputs(function) }}
  return outputs;
}
{% endif %}
{% endfor %}

Map<std::string, MethodSignature> createMethodMap() {
  Map<std::string, MethodSignature> m;
  {% for function in clss.methods %}
  m["{{function.name}}"] = &{{function.name}};
  {% endfor %}

  return m;
}
static const Map<std::string, MethodSignature> methods = createMethodMap();

// map of created {{clss.name}} instances. Don't trust the user to keep them safe...
static Map<void *, {{clss.name}}> instances;

/*
 * {{ clss.name }}
 * Gateway routine
 *   nlhs - number of return arguments
 *   plhs - pointers to return arguments
 *   nrhs - number of input arguments
 *   prhs - pointers to input arguments
 */
void mexFunction(int nlhs, mxArray* plhs[],
                 int nrhs, const mxArray* prhs[]) {

  // parse the inputs
  Bridge method_name(prhs[0]);

  Bridge handle(prhs[1]);
  std::vector<Bridge> brhs(prhs+2, prhs+nrhs);

  // retrieve the instance of interest
  try {
    {{clss.name}}& inst = instances.at(handle.address());
  } catch (const std::out_of_range& e) {
    mexErrMsgTxt("Invalid object instance provided");
  }

  // invoke the correct method on the data
  try {
    std::vector<Bridge> blhs = (*methods.at(method_name))(inst, brhs);
  } catch (const std::out_of_range& e) {
    mexErrMsgTxt("Unknown method specified");
  }

  {% block postfun %}
  {% endblock %}

  {% block cleanup %}
  {% endblock %}

}

} // end namespace
