/*
 * Copyright 2013, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>

#include <cstdarg>
#include <cctype>

#include <algorithm>
#include <sstream>
#include <string>

#include "os_sep.h"
#include "slang_rs_context.h"
#include "slang_rs_export_var.h"
#include "slang_rs_export_foreach.h"
#include "slang_rs_export_func.h"
#include "slang_rs_reflect_utils.h"
#include "slang_version.h"

#include "slang_rs_reflection_cpp.h"

using namespace std;

namespace slang {

const char kRsTypeItemClassName[] = "Item";
const char kRsElemPrefix[] = "__rs_elem_";
// The name of the Allocation type that is reflected in C++
const char kAllocationSp[] = "android::RSC::sp<android::RSC::Allocation>";

static const char *GetMatrixTypeName(const RSExportMatrixType *EMT) {
  static const char *MatrixTypeCNameMap[] = {
      "rs_matrix2x2", "rs_matrix3x3", "rs_matrix4x4",
  };
  unsigned Dim = EMT->getDim();

  if ((Dim - 2) < (sizeof(MatrixTypeCNameMap) / sizeof(const char *)))
    return MatrixTypeCNameMap[EMT->getDim() - 2];

  slangAssert(false && "GetMatrixTypeName : Unsupported matrix dimension");
  return nullptr;
}

static std::string GetTypeName(const RSExportType *ET, bool PreIdentifier = true) {
  if((!PreIdentifier) && (ET->getClass() != RSExportType::ExportClassConstantArray)) {
    slangAssert(false && "Non-array type post identifier?");
    return "";
  }
  switch (ET->getClass()) {
  case RSExportType::ExportClassPrimitive: {
    const RSExportPrimitiveType *EPT =
        static_cast<const RSExportPrimitiveType *>(ET);
    if (EPT->isRSObjectType()) {
      return std::string("android::RSC::sp<const android::RSC::") +
             RSExportPrimitiveType::getRSReflectionType(EPT)->c_name + ">";
    } else {
      return RSExportPrimitiveType::getRSReflectionType(EPT)->c_name;
    }
  }
  case RSExportType::ExportClassPointer: {
    const RSExportType *PointeeType =
        static_cast<const RSExportPointerType *>(ET)->getPointeeType();

    if (PointeeType->getClass() != RSExportType::ExportClassRecord)
      return kAllocationSp;
    else
      return PointeeType->getElementName();
  }
  case RSExportType::ExportClassVector: {
    const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
    std::stringstream VecName;
    VecName << EVT->getRSReflectionType(EVT)->rs_c_vector_prefix
            << EVT->getNumElement();
    return VecName.str();
  }
  case RSExportType::ExportClassMatrix: {
    return GetMatrixTypeName(static_cast<const RSExportMatrixType *>(ET));
  }
  case RSExportType::ExportClassConstantArray: {
    const RSExportConstantArrayType *CAT =
        static_cast<const RSExportConstantArrayType *>(ET);
    if (PreIdentifier) {
      std::string ElementTypeName = GetTypeName(CAT->getElementType());
      return ElementTypeName;
    }
    else {
      std::stringstream ArraySpec;
      ArraySpec << "[" << CAT->getNumElement() << "]";
      return ArraySpec.str();
    }
  }
  case RSExportType::ExportClassRecord: {
    // TODO: Fix for C structs!
    return ET->getElementName() + "." + kRsTypeItemClassName;
  }
  default: { slangAssert(false && "Unknown class of type"); }
  }

  return "";
}

RSReflectionCpp::RSReflectionCpp(const RSContext *Context,
                                 const string &OutputDirectory,
                                 const string &RSSourceFileName,
                                 const string &BitCodeFileName)
    : mRSContext(Context), mRSSourceFilePath(RSSourceFileName),
      mBitCodeFilePath(BitCodeFileName), mOutputDirectory(OutputDirectory),
      mNextExportVarSlot(0), mNextExportFuncSlot(0), mNextExportForEachSlot(0) {
  mCleanedRSFileName = RootNameFromRSFileName(mRSSourceFilePath);
  mClassName = "ScriptC_" + mCleanedRSFileName;
}

RSReflectionCpp::~RSReflectionCpp() {}

bool RSReflectionCpp::reflect() {
  writeHeaderFile();
  writeImplementationFile();

  return true;
}

#define RS_TYPE_CLASS_NAME_PREFIX "ScriptField_"

bool RSReflectionCpp::writeHeaderFile() {
  // Create the file and write the license note.
  if (!mOut.startFile(mOutputDirectory, mClassName + ".h", mRSSourceFilePath,
                      mRSContext->getLicenseNote(), false,
                      mRSContext->getVerbose())) {
    return false;
  }

  mOut.indent() << "#include \"RenderScript.h\"\n\n";
  mOut.indent() << "using namespace android::RSC;\n\n";

  mOut.comment("This class encapsulates access to the exported elements of the script.  "
               "Typically, you would instantiate this class once, call the set_* methods "
               "for each of the exported global variables you want to change, then call "
               "one of the forEach_ methods to invoke a kernel.");
  mOut.indent() << "class " << mClassName << " : public android::RSC::ScriptC";
  mOut.startBlock();

  mOut.decreaseIndent();
  mOut.indent() << "private:\n";
  mOut.increaseIndent();

  genFieldsToStoreExportVariableValues();
  genTypeInstancesUsedInForEach();
  genFieldsForAllocationTypeVerification();

  mOut.decreaseIndent();
  mOut.indent() << "public:\n";
  mOut.increaseIndent();

  // Generate the constructor and destructor declarations.
  mOut.indent() << mClassName << "(android::RSC::sp<android::RSC::RS> rs);\n";
  mOut.indent() << "virtual ~" << mClassName << "();\n\n";

  genExportVariablesGetterAndSetter();
  genForEachDeclarations();
  genExportFunctionDeclarations();

  mOut.endBlock(true);
  mOut.closeFile();
  return true;
}

void RSReflectionCpp::genTypeInstancesUsedInForEach() {
  for (auto I = mRSContext->export_foreach_begin(),
            E = mRSContext->export_foreach_end();
       I != E; I++) {
    const RSExportForEach *EF = *I;
    const RSExportType *OET = EF->getOutType();

    if (OET) {
      genTypeInstanceFromPointer(OET);
    }

    const RSExportForEach::InTypeVec &InTypes = EF->getInTypes();

    for (RSExportForEach::InTypeIter BI = InTypes.begin(),
         EI = InTypes.end(); BI != EI; BI++) {

      genTypeInstanceFromPointer(*BI);
    }
  }
}

void RSReflectionCpp::genFieldsForAllocationTypeVerification() {
  bool CommentAdded = false;
  for (std::set<std::string>::iterator I = mTypesToCheck.begin(),
                                       E = mTypesToCheck.end();
       I != E; I++) {
    if (!CommentAdded) {
      mOut.comment("The following elements are used to verify the types of "
                   "allocations passed to kernels.");
      CommentAdded = true;
    }
    mOut.indent() << "android::RSC::sp<const android::RSC::Element> "
                  << kRsElemPrefix << *I << ";\n";
  }
}

void RSReflectionCpp::genFieldsToStoreExportVariableValues() {
  bool CommentAdded = false;
  for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
                                            E = mRSContext->export_vars_end();
       I != E; I++) {
    const RSExportVar *ev = *I;
    if (ev->isConst()) {
      continue;
    }
    if (!CommentAdded) {
      mOut.comment("For each non-const variable exported by the script, we "
                   "have an equivalent field.  This field contains the last "
                   "value this variable was set to using the set_ method.  "
                   "This may not be current value of the variable in the "
                   "script, as the script is free to modify its internal "
                   "variable without changing this field.  If the script "
                   "initializes the exported variable, the constructor will "
                   "initialize this field to the same value.");
      CommentAdded = true;
    }
    mOut.indent() << GetTypeName(ev->getType()) << " " RS_EXPORT_VAR_PREFIX
                  << ev->getName() << ";\n";
  }
}

void RSReflectionCpp::genForEachDeclarations() {
  bool CommentAdded = false;
  for (RSContext::const_export_foreach_iterator
           I = mRSContext->export_foreach_begin(),
           E = mRSContext->export_foreach_end();
       I != E; I++) {
    const RSExportForEach *ForEach = *I;

    if (ForEach->isDummyRoot()) {
      mOut.indent() << "// No forEach_root(...)\n";
      continue;
    }

    if (!CommentAdded) {
      mOut.comment("For each kernel of the script corresponds one method.  "
                   "That method queues the kernel for execution.  The kernel "
                   "may not have completed nor even started by the time this "
                   "function returns.  Calls that extract the data out of the "
                   "output allocation will wait for the kernels to complete.");
      CommentAdded = true;
    }

    std::string FunctionStart = "void forEach_" + ForEach->getName() + "(";
    mOut.indent() << FunctionStart;

    ArgumentList Arguments;
    const RSExportForEach::InVec &Ins = ForEach->getIns();
    for (RSExportForEach::InIter BI = Ins.begin(), EI = Ins.end();
         BI != EI; BI++) {

      Arguments.push_back(Argument(kAllocationSp, (*BI)->getName()));
    }

    if (ForEach->hasOut() || ForEach->hasReturn()) {
      Arguments.push_back(Argument(kAllocationSp, "aout"));
    }

    const RSExportRecordType *ERT = ForEach->getParamPacketType();
    if (ERT) {
      for (RSExportForEach::const_param_iterator i = ForEach->params_begin(),
                                                 e = ForEach->params_end();
           i != e; i++) {
        RSReflectionTypeData rtd;
        (*i)->getType()->convertToRTD(&rtd);
        Arguments.push_back(Argument(rtd.type->c_name, (*i)->getName()));
      }
    }
    genArguments(Arguments, FunctionStart.length());
    mOut << ");\n";
  }
}

void RSReflectionCpp::genExportFunctionDeclarations() {
  for (RSContext::const_export_func_iterator
           I = mRSContext->export_funcs_begin(),
           E = mRSContext->export_funcs_end();
       I != E; I++) {
    const RSExportFunc *ef = *I;

    makeFunctionSignature(false, ef);
  }
}

// forEach_* implementation
void RSReflectionCpp::genExportForEachBodies() {
  uint32_t slot = 0;
  for (auto I = mRSContext->export_foreach_begin(),
            E = mRSContext->export_foreach_end();
       I != E; I++, slot++) {
    const RSExportForEach *ef = *I;
    if (ef->isDummyRoot()) {
      mOut.indent() << "// No forEach_root(...)\n";
      continue;
    }

    ArgumentList Arguments;
    std::string FunctionStart =
        "void " + mClassName + "::forEach_" + ef->getName() + "(";
    mOut.indent() << FunctionStart;

    if (ef->hasIns()) {
      // FIXME: Add support for kernels with multiple inputs.
      slangAssert(ef->getIns().size() == 1);
      Arguments.push_back(Argument(kAllocationSp, "ain"));
    }

    if (ef->hasOut() || ef->hasReturn()) {
      Arguments.push_back(Argument(kAllocationSp, "aout"));
    }

    const RSExportRecordType *ERT = ef->getParamPacketType();
    if (ERT) {
      for (RSExportForEach::const_param_iterator i = ef->params_begin(),
                                                 e = ef->params_end();
           i != e; i++) {
        RSReflectionTypeData rtd;
        (*i)->getType()->convertToRTD(&rtd);
        Arguments.push_back(Argument(rtd.type->c_name, (*i)->getName()));
      }
    }
    genArguments(Arguments, FunctionStart.length());
    mOut << ")";
    mOut.startBlock();

    const RSExportType *OET = ef->getOutType();
    const RSExportForEach::InTypeVec &InTypes = ef->getInTypes();
    if (ef->hasIns()) {
      // FIXME: Add support for kernels with multiple inputs.
      slangAssert(ef->getIns().size() == 1);
      genTypeCheck(InTypes[0], "ain");
    }
    if (OET) {
      genTypeCheck(OET, "aout");
    }

    // TODO Add the appropriate dimension checking code, as seen in
    // slang_rs_reflection.cpp.

    std::string FieldPackerName = ef->getName() + "_fp";
    if (ERT) {
      if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) {
        genPackVarOfType(ERT, nullptr, FieldPackerName.c_str());
      }
    }
    mOut.indent() << "forEach(" << slot << ", ";

    if (ef->hasIns()) {
      // FIXME: Add support for kernels with multiple inputs.
      slangAssert(ef->getIns().size() == 1);
      mOut << "ain, ";
    } else {
      mOut << "NULL, ";
    }

    if (ef->hasOut() || ef->hasReturn()) {
      mOut << "aout, ";
    } else {
      mOut << "NULL, ";
    }

    // FIXME (no support for usrData with C++ kernels)
    mOut << "NULL, 0);\n";
    mOut.endBlock();
  }
}

// invoke_* implementation
void RSReflectionCpp::genExportFunctionBodies() {
  uint32_t slot = 0;
  // Reflect export function
  for (auto I = mRSContext->export_funcs_begin(),
            E = mRSContext->export_funcs_end();
       I != E; I++) {
    const RSExportFunc *ef = *I;

    makeFunctionSignature(true, ef);
    mOut.startBlock();
    const RSExportRecordType *params = ef->getParamPacketType();
    size_t param_len = 0;
    if (params) {
      param_len = params->getAllocSize();
      if (genCreateFieldPacker(params, "__fp")) {
        genPackVarOfType(params, nullptr, "__fp");
      }
    }

    mOut.indent() << "invoke(" << slot;
    if (params) {
      mOut << ", __fp.getData(), " << param_len << ");\n";
    } else {
      mOut << ", NULL, 0);\n";
    }
    mOut.endBlock();

    slot++;
  }
}

bool RSReflectionCpp::genEncodedBitCode() {
  FILE *pfin = fopen(mBitCodeFilePath.c_str(), "rb");
  if (pfin == nullptr) {
    fprintf(stderr, "Error: could not read file %s\n",
            mBitCodeFilePath.c_str());
    return false;
  }

  unsigned char buf[16];
  int read_length;
  mOut.indent() << "static const unsigned char __txt[] =";
  mOut.startBlock();
  while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) {
    mOut.indent();
    for (int i = 0; i < read_length; i++) {
      char buf2[16];
      snprintf(buf2, sizeof(buf2), "0x%02x,", buf[i]);
      mOut << buf2;
    }
    mOut << "\n";
  }
  mOut.endBlock(true);
  mOut << "\n";
  return true;
}

bool RSReflectionCpp::writeImplementationFile() {
  if (!mOut.startFile(mOutputDirectory, mClassName + ".cpp", mRSSourceFilePath,
                      mRSContext->getLicenseNote(), false,
                      mRSContext->getVerbose())) {
    return false;
  }

  // Front matter
  mOut.indent() << "#include \"" << mClassName << ".h\"\n\n";

  genEncodedBitCode();
  mOut.indent() << "\n\n";

  // Constructor
  const std::string &packageName = mRSContext->getReflectJavaPackageName();
  mOut.indent() << mClassName << "::" << mClassName
                << "(android::RSC::sp<android::RSC::RS> rs):\n"
                   "        ScriptC(rs, __txt, sizeof(__txt), \""
                << mCleanedRSFileName << "\", " << mCleanedRSFileName.length()
                << ", \"/data/data/" << packageName << "/app\", sizeof(\""
                << packageName << "\"))";
  mOut.startBlock();
  for (std::set<std::string>::iterator I = mTypesToCheck.begin(),
                                       E = mTypesToCheck.end();
       I != E; I++) {
    mOut.indent() << kRsElemPrefix << *I << " = android::RSC::Element::" << *I
                  << "(mRS);\n";
  }

  for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
                                            E = mRSContext->export_vars_end();
       I != E; I++) {
    const RSExportVar *EV = *I;
    if (!EV->getInit().isUninit()) {
      genInitExportVariable(EV->getType(), EV->getName(), EV->getInit());
    } else {
      genZeroInitExportVariable(EV->getName());
    }
  }
  mOut.endBlock();

  // Destructor
  mOut.indent() << mClassName << "::~" << mClassName << "()";
  mOut.startBlock();
  mOut.endBlock();

  // Function bodies
  genExportForEachBodies();
  genExportFunctionBodies();

  mOut.closeFile();
  return true;
}

void RSReflectionCpp::genExportVariablesGetterAndSetter() {
  mOut.comment("Methods to set and get the variables exported by the script. "
               "Const variables will not have a setter.\n\n"
               "Note that the value returned by the getter may not be the "
               "current value of the variable in the script.  The getter will "
               "return the initial value of the variable (as defined in the "
               "script) or the the last value set by using the setter method.  "
               "The script is free to modify its value independently.");
  for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
                                            E = mRSContext->export_vars_end();
       I != E; I++) {
    const RSExportVar *EV = *I;
    const RSExportType *ET = EV->getType();

    switch (ET->getClass()) {
    case RSExportType::ExportClassPrimitive: {
      genGetterAndSetter(static_cast<const RSExportPrimitiveType *>(ET), EV);
      break;
    }
    case RSExportType::ExportClassPointer: {
      // TODO Deprecate this.
      genPointerTypeExportVariable(EV);
      break;
    }
    case RSExportType::ExportClassVector: {
      genGetterAndSetter(static_cast<const RSExportVectorType *>(ET), EV);
      break;
    }
    case RSExportType::ExportClassMatrix: {
      genMatrixTypeExportVariable(EV);
      break;
    }
    case RSExportType::ExportClassConstantArray: {
      genGetterAndSetter(static_cast<const RSExportConstantArrayType *>(ET),
                         EV);
      break;
    }
    case RSExportType::ExportClassRecord: {
      genGetterAndSetter(static_cast<const RSExportRecordType *>(ET), EV);
      break;
    }
    default: { slangAssert(false && "Unknown class of type"); }
    }
  }
}

void RSReflectionCpp::genGetterAndSetter(const RSExportPrimitiveType *EPT,
                                         const RSExportVar *EV) {
  RSReflectionTypeData rtd;
  EPT->convertToRTD(&rtd);
  std::string TypeName = GetTypeName(EPT);

  if (!EV->isConst()) {
    mOut.indent() << "void set_" << EV->getName() << "(" << TypeName << " v)";
    mOut.startBlock();
    mOut.indent() << "setVar(" << getNextExportVarSlot() << ", ";
    if (EPT->isRSObjectType()) {
      mOut << "v";
   } else {
      mOut << "&v, sizeof(v)";
    }
    mOut << ");\n";
    mOut.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;\n";
    mOut.endBlock();
  }
  mOut.indent() << TypeName << " get_" << EV->getName() << "() const";
  mOut.startBlock();
  if (EV->isConst()) {
    const clang::APValue &val = EV->getInit();
    bool isBool = !strcmp(TypeName.c_str(), "bool");
    mOut.indent() << "return ";
    genInitValue(val, isBool);
    mOut << ";\n";
  } else {
    mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << EV->getName()
                  << ";\n";
  }
  mOut.endBlock();
}

void RSReflectionCpp::genPointerTypeExportVariable(const RSExportVar *EV) {
  const RSExportType *ET = EV->getType();

  slangAssert((ET->getClass() == RSExportType::ExportClassPointer) &&
              "Variable should be type of pointer here");

  std::string TypeName = GetTypeName(ET);
  std::string VarName = EV->getName();

  RSReflectionTypeData rtd;
  EV->getType()->convertToRTD(&rtd);
  uint32_t slot = getNextExportVarSlot();

  if (!EV->isConst()) {
    mOut.indent() << "void bind_" << VarName << "(" << TypeName << " v)";
    mOut.startBlock();
    mOut.indent() << "bindAllocation(v, " << slot << ");\n";
    mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n";
    mOut.endBlock();
  }
  mOut.indent() << TypeName << " get_" << VarName << "() const";
  mOut.startBlock();
  if (EV->isConst()) {
    const clang::APValue &val = EV->getInit();
    bool isBool = !strcmp(TypeName.c_str(), "bool");
    mOut.indent() << "return ";
    genInitValue(val, isBool);
    mOut << ";\n";
  } else {
    mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << VarName << ";\n";
  }
  mOut.endBlock();
}

void RSReflectionCpp::genGetterAndSetter(const RSExportVectorType *EVT,
                                         const RSExportVar *EV) {
  slangAssert(EVT != nullptr);

  RSReflectionTypeData rtd;
  EVT->convertToRTD(&rtd);

  if (!EV->isConst()) {
    mOut.indent() << "void set_" << EV->getName() << "("
                  << rtd.type->rs_c_vector_prefix << EVT->getNumElement()
                  << " v)";
    mOut.startBlock();
    mOut.indent() << "setVar(" << getNextExportVarSlot()
                  << ", &v, sizeof(v));\n";
    mOut.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;\n";
    mOut.endBlock();
  }
  mOut.indent() << rtd.type->rs_c_vector_prefix << EVT->getNumElement()
                << " get_" << EV->getName() << "() const";
  mOut.startBlock();
  if (EV->isConst()) {
    const clang::APValue &val = EV->getInit();
    mOut.indent() << "return ";
    genInitValue(val, false);
    mOut << ";\n";
  } else {
    mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << EV->getName()
                  << ";\n";
  }
  mOut.endBlock();
}

void RSReflectionCpp::genMatrixTypeExportVariable(const RSExportVar *EV) {
  uint32_t slot = getNextExportVarSlot();
  stringstream tmp;
  tmp << slot;

  const RSExportType *ET = EV->getType();
  if (ET->getName() == "rs_matrix4x4") {
    mOut.indent() << "void set_" << EV->getName() << "(float v[16])";
    mOut.startBlock();
    mOut.indent() << "setVar(" << tmp.str() << ", v, sizeof(float)*16);\n";
    mOut.endBlock();
  } else if (ET->getName() == "rs_matrix3x3") {
    mOut.indent() << "void set_" << EV->getName() << "(float v[9])";
    mOut.startBlock();
    mOut.indent() << "setVar(" << tmp.str() << ", v, sizeof(float)*9);";
    mOut.endBlock();
  } else if (ET->getName() == "rs_matrix2x2") {
    mOut.indent() << "void set_" << EV->getName() << "(float v[4])";
    mOut.startBlock();
    mOut.indent() << "setVar(" << tmp.str() << ", v, sizeof(float)*4);";
    mOut.endBlock();
  } else {
    mOut.indent() << "#error: TODO: " << ET->getName();
    slangAssert(false);
  }
}

void RSReflectionCpp::genGetterAndSetter(const RSExportConstantArrayType *AT,
                                         const RSExportVar *EV) {
  std::stringstream ArraySpec;
  const RSExportType *ET = EV->getType();

  const RSExportConstantArrayType *CAT =
      static_cast<const RSExportConstantArrayType *>(ET);

  uint32_t slot = getNextExportVarSlot();
  stringstream tmp;
  tmp << slot;

  ArraySpec << CAT->getNumElement();
  mOut.indent() << "void set_" << EV->getName() << "(" << GetTypeName(EV->getType()) << " v "
      << GetTypeName(EV->getType(), false) << ")";
  mOut.startBlock();
  mOut.indent() << "setVar(" << tmp.str() << ", v, sizeof(" << GetTypeName(EV->getType()) + ") *"
      << ArraySpec.str() << ");";
  mOut.endBlock();
}

void RSReflectionCpp::genGetterAndSetter(const RSExportRecordType *ERT,
                                         const RSExportVar *EV) {
  slangAssert(false);
}

void RSReflectionCpp::makeFunctionSignature(bool isDefinition,
                                            const RSExportFunc *ef) {
  mOut.indent() << "void ";
  if (isDefinition) {
    mOut << mClassName << "::";
  }
  mOut << "invoke_" << ef->getName() << "(";

  if (ef->getParamPacketType()) {
    bool FirstArg = true;
    for (RSExportFunc::const_param_iterator i = ef->params_begin(),
                                            e = ef->params_end();
         i != e; i++) {
      if (!FirstArg) {
        mOut << ", ";
      } else {
        FirstArg = false;
      }
      mOut << GetTypeName((*i)->getType()) << " " << (*i)->getName();
    }
  }

  if (isDefinition) {
    mOut << ")";
  } else {
    mOut << ");\n";
  }
}

void RSReflectionCpp::genArguments(const ArgumentList &Arguments, int Offset) {
  bool FirstArg = true;

  for (ArgumentList::const_iterator I = Arguments.begin(), E = Arguments.end();
       I != E; I++) {
    if (!FirstArg) {
      mOut << ",\n";
      mOut.indent() << string(Offset, ' ');
    } else {
      FirstArg = false;
    }

    mOut << I->Type << " " << I->Name;
    if (!I->DefaultValue.empty()) {
      mOut << " = " << I->DefaultValue;
    }
  }
}

bool RSReflectionCpp::genCreateFieldPacker(const RSExportType *ET,
                                           const char *FieldPackerName) {
  size_t AllocSize = ET->getAllocSize();

  if (AllocSize > 0) {
    mOut.indent() << "android::RSC::FieldPacker " << FieldPackerName << "("
                  << AllocSize << ");\n";
    return true;
  }

  return false;
}

void RSReflectionCpp::genPackVarOfType(const RSExportType *ET,
                                       const char *VarName,
                                       const char *FieldPackerName) {
  switch (ET->getClass()) {
  case RSExportType::ExportClassPrimitive:
  case RSExportType::ExportClassVector:
  case RSExportType::ExportClassPointer:
  case RSExportType::ExportClassMatrix: {
    mOut.indent() << FieldPackerName << ".add(" << VarName << ");\n";
    break;
  }
  case RSExportType::ExportClassConstantArray: {
    /*const RSExportConstantArrayType *ECAT =
        static_cast<const RSExportConstantArrayType *>(ET);

    // TODO(zonr): more elegant way. Currently, we obtain the unique index
    //             variable (this method involves recursive call which means
    //             we may have more than one level loop, therefore we can't
    //             always use the same index variable name here) name given
    //             in the for-loop from counting the '.' in @VarName.
    unsigned Level = 0;
    size_t LastDotPos = 0;
    std::string ElementVarName(VarName);

  while (LastDotPos != std::string::npos) {
    LastDotPos = ElementVarName.find_first_of('.', LastDotPos + 1);
    Level++;
  }
  std::string IndexVarName("ct");
  IndexVarName.append(llvm::utostr_32(Level));

  C.indent() << "for (int " << IndexVarName << " = 0; " <<
                      IndexVarName << " < " << ECAT->getSize() << "; " <<
                      IndexVarName << "++)";
  C.startBlock();

  ElementVarName.append("[" + IndexVarName + "]");
  genPackVarOfType(C, ECAT->getElementType(), ElementVarName.c_str(),
                   FieldPackerName);

  C.endBlock();*/
    break;
  }
  case RSExportType::ExportClassRecord: {
    const RSExportRecordType *ERT = static_cast<const RSExportRecordType *>(ET);
    // Relative pos from now on in field packer
    unsigned Pos = 0;

    for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
                                                  E = ERT->fields_end();
         I != E; I++) {
      const RSExportRecordType::Field *F = *I;
      std::string FieldName;
      size_t FieldOffset = F->getOffsetInParent();
      const RSExportType *T = F->getType();
      size_t FieldStoreSize = T->getStoreSize();
      size_t FieldAllocSize = T->getAllocSize();

      if (VarName != nullptr)
        FieldName = VarName + ("." + F->getName());
      else
        FieldName = F->getName();

      if (FieldOffset > Pos) {
        mOut.indent() << FieldPackerName << ".skip(" << (FieldOffset - Pos)
                      << ");\n";
      }

      genPackVarOfType(F->getType(), FieldName.c_str(), FieldPackerName);

      // There is padding in the field type
      if (FieldAllocSize > FieldStoreSize) {
        mOut.indent() << FieldPackerName << ".skip("
                      << (FieldAllocSize - FieldStoreSize) << ");\n";
      }

      Pos = FieldOffset + FieldAllocSize;
    }

    // There maybe some padding after the struct
    if (ERT->getAllocSize() > Pos) {
      mOut.indent() << FieldPackerName << ".skip(" << ERT->getAllocSize() - Pos
                    << ");\n";
    }
    break;
  }
  default: { slangAssert(false && "Unknown class of type"); }
  }
}

void RSReflectionCpp::genTypeCheck(const RSExportType *ET,
                                   const char *VarName) {
  mOut.indent() << "// Type check for " << VarName << "\n";

  if (ET->getClass() == RSExportType::ExportClassPointer) {
    const RSExportPointerType *EPT =
        static_cast<const RSExportPointerType *>(ET);
    ET = EPT->getPointeeType();
  }

  std::string TypeName;
  switch (ET->getClass()) {
  case RSExportType::ExportClassPrimitive:
  case RSExportType::ExportClassVector:
  case RSExportType::ExportClassRecord: {
    TypeName = ET->getElementName();
    break;
  }

  default:
    break;
  }

  if (!TypeName.empty()) {
    mOut.indent() << "if (!" << VarName
                  << "->getType()->getElement()->isCompatible("
                  << kRsElemPrefix << TypeName << "))";
    mOut.startBlock();
    mOut.indent() << "mRS->throwError(RS_ERROR_RUNTIME_ERROR, "
                     "\"Incompatible type\");\n";
    mOut.indent() << "return;\n";
    mOut.endBlock();
  }
}

void RSReflectionCpp::genTypeInstanceFromPointer(const RSExportType *ET) {
  if (ET->getClass() == RSExportType::ExportClassPointer) {
    // For pointer parameters to original forEach kernels.
    const RSExportPointerType *EPT =
        static_cast<const RSExportPointerType *>(ET);
    genTypeInstance(EPT->getPointeeType());
  } else {
    // For handling pass-by-value kernel parameters.
    genTypeInstance(ET);
  }
}

void RSReflectionCpp::genTypeInstance(const RSExportType *ET) {
  switch (ET->getClass()) {
  case RSExportType::ExportClassPrimitive:
  case RSExportType::ExportClassVector:
  case RSExportType::ExportClassConstantArray:
  case RSExportType::ExportClassRecord: {
    std::string TypeName = ET->getElementName();
    mTypesToCheck.insert(TypeName);
    break;
  }

  default:
    break;
  }
}

void RSReflectionCpp::genInitExportVariable(const RSExportType *ET,
                                            const std::string &VarName,
                                            const clang::APValue &Val) {
  slangAssert(!Val.isUninit() && "Not a valid initializer");

  switch (ET->getClass()) {
  case RSExportType::ExportClassPrimitive: {
    const RSExportPrimitiveType *EPT =
        static_cast<const RSExportPrimitiveType *>(ET);
    if (EPT->getType() == DataTypeBoolean) {
      genInitBoolExportVariable(VarName, Val);
    } else {
      genInitPrimitiveExportVariable(VarName, Val);
    }
    break;
  }
  case RSExportType::ExportClassPointer: {
    if (!Val.isInt() || Val.getInt().getSExtValue() != 0)
      std::cerr << "Initializer which is non-NULL to pointer type variable "
                   "will be ignored" << std::endl;
    break;
  }
  case RSExportType::ExportClassVector: {
    const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
    switch (Val.getKind()) {
    case clang::APValue::Int:
    case clang::APValue::Float: {
      for (unsigned i = 0; i < EVT->getNumElement(); i++) {
        std::string Name = VarName + "." + getVectorAccessor(i);
        genInitPrimitiveExportVariable(Name, Val);
      }
      break;
    }
    case clang::APValue::Vector: {
      unsigned NumElements = std::min(
          static_cast<unsigned>(EVT->getNumElement()), Val.getVectorLength());
      for (unsigned i = 0; i < NumElements; i++) {
        const clang::APValue &ElementVal = Val.getVectorElt(i);
        std::string Name = VarName + "." + getVectorAccessor(i);
        genInitPrimitiveExportVariable(Name, ElementVal);
      }
      break;
    }
    case clang::APValue::MemberPointer:
    case clang::APValue::Uninitialized:
    case clang::APValue::ComplexInt:
    case clang::APValue::ComplexFloat:
    case clang::APValue::LValue:
    case clang::APValue::Array:
    case clang::APValue::Struct:
    case clang::APValue::Union:
    case clang::APValue::AddrLabelDiff: {
      slangAssert(false && "Unexpected type of value of initializer.");
    }
    }
    break;
  }
  case RSExportType::ExportClassMatrix:
  case RSExportType::ExportClassConstantArray:
  case RSExportType::ExportClassRecord: {
    slangAssert(false && "Unsupported initializer for record/matrix/constant "
                         "array type variable currently");
    break;
  }
  default: { slangAssert(false && "Unknown class of type"); }
  }
}

const char *RSReflectionCpp::getVectorAccessor(unsigned Index) {
  static const char *VectorAccessorMap[] = {/* 0 */ "x",
                                            /* 1 */ "y",
                                            /* 2 */ "z",
                                            /* 3 */ "w",
  };

  slangAssert((Index < (sizeof(VectorAccessorMap) / sizeof(const char *))) &&
              "Out-of-bound index to access vector member");

  return VectorAccessorMap[Index];
}

void RSReflectionCpp::genZeroInitExportVariable(const std::string &VarName) {
  mOut.indent() << "memset(&" << RS_EXPORT_VAR_PREFIX << VarName
                << ", 0, sizeof(" << RS_EXPORT_VAR_PREFIX << VarName << "));\n";
}

void
RSReflectionCpp::genInitPrimitiveExportVariable(const std::string &VarName,
                                                const clang::APValue &Val) {
  slangAssert(!Val.isUninit() && "Not a valid initializer");

  mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
  genInitValue(Val);
  mOut << ";\n";
}

void RSReflectionCpp::genInitValue(const clang::APValue &Val, bool asBool) {
  switch (Val.getKind()) {
  case clang::APValue::Int: {
    llvm::APInt api = Val.getInt();
    if (asBool) {
      mOut << ((api.getSExtValue() == 0) ? "false" : "true");
    } else {
      // TODO: Handle unsigned correctly for C++
      mOut << api.getSExtValue();
      if (api.getBitWidth() > 32) {
        mOut << "L";
      }
    }
    break;
  }

  case clang::APValue::Float: {
    llvm::APFloat apf = Val.getFloat();
    llvm::SmallString<30> s;
    apf.toString(s);
    mOut << s.c_str();
    if (&apf.getSemantics() == &llvm::APFloat::IEEEsingle) {
      if (s.count('.') == 0) {
        mOut << ".f";
      } else {
        mOut << "f";
      }
    }
    break;
  }

  case clang::APValue::ComplexInt:
  case clang::APValue::ComplexFloat:
  case clang::APValue::LValue:
  case clang::APValue::Vector: {
    slangAssert(false && "Primitive type cannot have such kind of initializer");
    break;
  }

  default: { slangAssert(false && "Unknown kind of initializer"); }
  }
}

void RSReflectionCpp::genInitBoolExportVariable(const std::string &VarName,
                                                const clang::APValue &Val) {
  slangAssert(!Val.isUninit() && "Not a valid initializer");
  slangAssert((Val.getKind() == clang::APValue::Int) &&
              "Bool type has wrong initial APValue");

  mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = "
                << ((Val.getInt().getSExtValue() == 0) ? "false" : "true")
                << ";";
}

} // namespace slang
