/*
 * Copyright 2010-2012, 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.
 */

#ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_H_  // NOLINT
#define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_H_

#include <fstream>
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <vector>

#include "llvm/ADT/StringExtras.h"

#include "slang_assert.h"
#include "slang_rs_export_type.h"

namespace slang {

  class RSContext;
  class RSExportVar;
  class RSExportFunc;
  class RSExportForEach;

class RSReflection {
 private:
  const RSContext *mRSContext;

  std::string mLastError;
  std::vector<std::string> *mGeneratedFileNames;

  inline void setError(const std::string &Error) { mLastError = Error; }

  class Context {
   private:
    static const char *const ApacheLicenseNote;

    bool mVerbose;

    std::string mOutputPathBase;

    std::string mInputRSFile;

    std::string mPackageName;
    std::string mRSPackageName;
    std::string mResourceId;
    std::string mPaddingPrefix;

    std::string mClassName;

    std::string mLicenseNote;

    std::string mIndent;

    int mPaddingFieldIndex;

    int mNextExportVarSlot;
    int mNextExportFuncSlot;
    int mNextExportForEachSlot;

    // A mapping from a field in a record type to its index in the rsType
    // instance. Only used when generates TypeClass (ScriptField_*).
    typedef std::map<const RSExportRecordType::Field*, unsigned>
        FieldIndexMapTy;
    FieldIndexMapTy mFieldIndexMap;
    // Field index of current processing TypeClass.
    unsigned mFieldIndex;

    inline void clear() {
      mClassName = "";
      mIndent = "";
      mPaddingFieldIndex = 1;
      mNextExportVarSlot = 0;
      mNextExportFuncSlot = 0;
      mNextExportForEachSlot = 0;
      return;
    }

    bool openClassFile(const std::string &ClassName,
                       std::string &ErrorMsg);

   public:
    typedef enum {
      AM_Public,
      AM_Protected,
      AM_Private,
      AM_PublicSynchronized
    } AccessModifier;

    bool mUseStdout;
    mutable std::ofstream mOF;

    // Generated RS Elements for type-checking code.
    std::set<std::string> mTypesToCheck;

    // Generated FieldPackers for unsigned setters/validation.
    std::set<std::string> mFieldPackerTypes;

    bool addTypeNameForElement(const std::string &TypeName);
    bool addTypeNameForFieldPacker(const std::string &TypeName);

    static const char *AccessModifierStr(AccessModifier AM);

    Context(const std::string &OutputPathBase,
            const std::string &InputRSFile,
            const std::string &PackageName,
            const std::string &RSPackageName,
            const std::string &ResourceId,
            const std::string &PaddingPrefix,
            bool UseStdout)
        : mVerbose(true),
          mOutputPathBase(OutputPathBase),
          mInputRSFile(InputRSFile),
          mPackageName(PackageName),
          mRSPackageName(RSPackageName),
          mResourceId(ResourceId),
          mPaddingPrefix(PaddingPrefix),
          mLicenseNote(ApacheLicenseNote),
          mUseStdout(UseStdout) {
      clear();
      resetFieldIndex();
      clearFieldIndexMap();
      return;
    }

    inline std::ostream &out() const {
      return ((mUseStdout) ? std::cout : mOF);
    }
    inline std::ostream &indent() const {
      out() << mIndent;
      return out();
    }

    inline void incIndentLevel() {
      mIndent.append(4, ' ');
      return;
    }

    inline void decIndentLevel() {
      slangAssert(getIndentLevel() > 0 && "No indent");
      mIndent.erase(0, 4);
      return;
    }

    inline int getIndentLevel() { return (mIndent.length() >> 2); }

    inline int getNextExportVarSlot() { return mNextExportVarSlot++; }

    inline int getNextExportFuncSlot() { return mNextExportFuncSlot++; }
    inline int getNextExportForEachSlot() { return mNextExportForEachSlot++; }

    // Will remove later due to field name information is not necessary for
    // C-reflect-to-Java
    inline std::string createPaddingField() {
      return mPaddingPrefix + llvm::itostr(mPaddingFieldIndex++);
    }

    inline void setLicenseNote(const std::string &LicenseNote) {
      mLicenseNote = LicenseNote;
    }

    bool startClass(AccessModifier AM,
                    bool IsStatic,
                    const std::string &ClassName,
                    const char *SuperClassName,
                    std::string &ErrorMsg);
    void endClass();

    void startFunction(AccessModifier AM,
                       bool IsStatic,
                       const char *ReturnType,
                       const std::string &FunctionName,
                       int Argc, ...);

    typedef std::vector<std::pair<std::string, std::string> > ArgTy;
    void startFunction(AccessModifier AM,
                       bool IsStatic,
                       const char *ReturnType,
                       const std::string &FunctionName,
                       const ArgTy &Args);
    void endFunction();

    void startBlock(bool ShouldIndent = false);
    void endBlock();

    inline const std::string &getPackageName() const { return mPackageName; }
    inline const std::string &getRSPackageName() const {
      return mRSPackageName;
    }
    inline const std::string &getClassName() const { return mClassName; }
    inline const std::string &getResourceId() const { return mResourceId; }

    void startTypeClass(const std::string &ClassName);
    void endTypeClass();

    inline void incFieldIndex() { mFieldIndex++; }

    inline void resetFieldIndex() { mFieldIndex = 0; }

    inline void addFieldIndexMapping(const RSExportRecordType::Field *F) {
      slangAssert((mFieldIndexMap.find(F) == mFieldIndexMap.end()) &&
                  "Nested structure never occurs in C language.");
      mFieldIndexMap.insert(std::make_pair(F, mFieldIndex));
    }

    inline unsigned getFieldIndex(const RSExportRecordType::Field *F) const {
      FieldIndexMapTy::const_iterator I = mFieldIndexMap.find(F);
      slangAssert((I != mFieldIndexMap.end()) &&
                  "Requesting field is out of scope.");
      return I->second;
    }

    inline void clearFieldIndexMap() { mFieldIndexMap.clear(); }
  };

  bool genScriptClass(Context &C,
                      const std::string &ClassName,
                      std::string &ErrorMsg);
  void genScriptClassConstructor(Context &C);

  static void genInitBoolExportVariable(Context &C,
                                        const std::string &VarName,
                                        const clang::APValue &Val);
  static void genInitPrimitiveExportVariable(Context &C,
                                             const std::string &VarName,
                                             const clang::APValue &Val);
  static void genInitExportVariable(Context &C,
                                    const RSExportType *ET,
                                    const std::string &VarName,
                                    const clang::APValue &Val);
  static void genInitValue(Context &C, const clang::APValue &Val);
  void genExportVariable(Context &C, const RSExportVar *EV);
  void genPrimitiveTypeExportVariable(Context &C, const RSExportVar *EV);
  void genPointerTypeExportVariable(Context &C, const RSExportVar *EV);
  void genVectorTypeExportVariable(Context &C, const RSExportVar *EV);
  void genMatrixTypeExportVariable(Context &C, const RSExportVar *EV);
  void genConstantArrayTypeExportVariable(Context &C, const RSExportVar *EV);
  void genRecordTypeExportVariable(Context &C, const RSExportVar *EV);
  void genPrivateExportVariable(Context &C,
                                const std::string &TypeName,
                                const std::string &VarName);
  void genSetExportVariable(Context &C,
                            const std::string &TypeName,
                            const RSExportVar *EV);
  void genGetExportVariable(Context &C,
                            const std::string &TypeName,
                            const std::string &VarName);
  void genGetFieldID(Context &C,
                     const std::string &VarName);

  void genExportFunction(Context &C,
                         const RSExportFunc *EF);

  void genExportForEach(Context &C,
                        const RSExportForEach *EF);

  static void genTypeCheck(Context &C,
                           const RSExportType *ET,
                           const char *VarName);

  static void genTypeInstanceFromPointer(Context &C,
                                         const RSExportType *ET);

  static void genTypeInstance(Context &C,
                              const RSExportType *ET);

  static void genFieldPackerInstance(Context &C,
                                     const RSExportType *ET);

  bool genTypeClass(Context &C,
                    const RSExportRecordType *ERT,
                    std::string &ErrorMsg);
  void genTypeItemClass(Context &C, const RSExportRecordType *ERT);
  void genTypeClassConstructor(Context &C, const RSExportRecordType *ERT);
  void genTypeClassCopyToArray(Context &C, const RSExportRecordType *ERT);
  void genTypeClassCopyToArrayLocal(Context &C, const RSExportRecordType *ERT);
  void genTypeClassItemSetter(Context &C, const RSExportRecordType *ERT);
  void genTypeClassItemGetter(Context &C, const RSExportRecordType *ERT);
  void genTypeClassComponentSetter(Context &C, const RSExportRecordType *ERT);
  void genTypeClassComponentGetter(Context &C, const RSExportRecordType *ERT);
  void genTypeClassCopyAll(Context &C, const RSExportRecordType *ERT);
  void genTypeClassResize(Context &C);

  void genBuildElement(Context &C,
                       const char *ElementBuilderName,
                       const RSExportRecordType *ERT,
                       const char *RenderScriptVar,
                       bool IsInline);
  void genAddElementToElementBuilder(Context &C,
                                     const RSExportType *ERT,
                                     const std::string &VarName,
                                     const char *ElementBuilderName,
                                     const char *RenderScriptVar,
                                     unsigned ArraySize);
  void genAddPaddingToElementBuiler(Context &C,
                                    int PaddingSize,
                                    const char *ElementBuilderName,
                                    const char *RenderScriptVar);

  bool genCreateFieldPacker(Context &C,
                            const RSExportType *T,
                            const char *FieldPackerName);
  void genPackVarOfType(Context &C,
                        const RSExportType *T,
                        const char *VarName,
                        const char *FieldPackerName);
  void genAllocateVarOfType(Context &C,
                            const RSExportType *T,
                            const std::string &VarName);
  void genNewItemBufferIfNull(Context &C, const char *Index);
  void genNewItemBufferPackerIfNull(Context &C);

 public:
  explicit RSReflection(const RSContext *Context,
      std::vector<std::string> *GeneratedFileNames)
      : mRSContext(Context),
        mLastError(""),
        mGeneratedFileNames(GeneratedFileNames) {
    slangAssert(mGeneratedFileNames && "Must supply GeneratedFileNames");
    return;
  }

  bool reflect(const std::string &OutputPathBase,
               const std::string &OutputPackageName,
               const std::string &RSPackageName,
               const std::string &InputFileName,
               const std::string &OutputBCFileName);

  inline const char *getLastError() const {
    if (mLastError.empty())
      return NULL;
    else
      return mLastError.c_str();
  }
};  // class RSReflection

}   // namespace slang

#endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_H_  NOLINT
