/*
 Copyright 2019 Alain Dargelas

 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.
 */

/*
 * File:   ResolveSymbols.cpp
 * Author: alain
 *
 * Created on July 1, 2017, 12:38 PM
 */
#include "SourceCompile/VObjectTypes.h"
#include "Design/VObject.h"
#include "Library/Library.h"
#include "Design/FileContent.h"
#include "SourceCompile/SymbolTable.h"
#include "ErrorReporting/Error.h"
#include "ErrorReporting/Location.h"
#include "ErrorReporting/Error.h"
#include "ErrorReporting/ErrorDefinition.h"
#include "ErrorReporting/ErrorContainer.h"
#include "SourceCompile/CompilationUnit.h"
#include "SourceCompile/PreprocessFile.h"
#include "SourceCompile/CompileSourceFile.h"
#include "SourceCompile/ParseFile.h"
#include "SourceCompile/Compiler.h"
#include "Testbench/Program.h"
#include "Testbench/ClassDefinition.h"
#include "DesignCompile/CompileDesign.h"
#include "DesignCompile/ResolveSymbols.h"

using namespace SURELOG;

ResolveSymbols::~ResolveSymbols() {}

int FunctorCreateLookup::operator()() const {
  ResolveSymbols* instance = new ResolveSymbols(
      m_compileDesign, m_fileData, m_symbolTable, m_errorContainer);
  instance->createFastLookup();
  delete instance;
  return true;
}

int FunctorResolve::operator()() const {
  ResolveSymbols* instance = new ResolveSymbols(
      m_compileDesign, m_fileData, m_symbolTable, m_errorContainer);
  instance->resolve();
  delete instance;
  return true;
}

std::string ResolveSymbols::SymName(NodeId index) {
  return m_fileData->getSymbolTable()->getSymbol(Name(index));
}

void ResolveSymbols::createFastLookup() {
  Library* lib = m_fileData->getLibrary();
  std::string libName = lib->getName();

  // std::string fileName =  "FILE: " + m_fileData->getFileName() + " " +
  // m_fileData->getChunkFileName () + "\n"; std::cout << fileName;

  std::vector<VObjectType> types = {
      VObjectType::slModule_declaration,    VObjectType::slPackage_declaration,
      VObjectType::slConfig_declaration,    VObjectType::slUdp_declaration,
      VObjectType::slInterface_declaration, VObjectType::slProgram_declaration,
      VObjectType::slClass_declaration};

  std::vector<VObjectType> stopPoints = {
      VObjectType::slModule_declaration, VObjectType::slPackage_declaration,
      VObjectType::slProgram_declaration, VObjectType::slClass_declaration};

  std::vector<NodeId> objects =
      m_fileData->sl_collect_all(m_fileData->getRootNode(), types, stopPoints);

  for (auto object : objects) {
    VObjectType type = m_fileData->Type(object);
    NodeId stId = m_fileData->sl_collect(object, VObjectType::slStringConst,
                                         VObjectType::slAttr_spec);
    if (stId != InvalidNodeId) {
      std::string name = SymName(stId);
      m_fileData->insertObjectLookup(name, object, m_errorContainer);
      std::string fullName = libName + "@" + name;

      switch (type) {
        case VObjectType::slPackage_declaration: {
          // Package names are not prefixed by Library names!
          std::string pkgname = name;
          Package* pdef = new Package(pkgname, lib, m_fileData, object);
          m_fileData->addPackageDefinition(pkgname, pdef);

          std::vector<VObjectType> subtypes = {
              VObjectType::slClass_declaration};
          std::vector<NodeId> subobjects =
              m_fileData->sl_collect_all(object, subtypes, subtypes);
          for (auto subobject : subobjects) {
            NodeId stId =
                m_fileData->sl_collect(subobject, VObjectType::slStringConst,
                                       VObjectType::slAttr_spec);
            if (stId != InvalidNodeId) {
              std::string name = SymName(stId);
              std::string fullSubName = pkgname + "::" + name;
              m_fileData->insertObjectLookup(fullSubName, subobject,
                                             m_errorContainer);

              ClassDefinition* def = new ClassDefinition(
                  fullSubName, lib, pdef, m_fileData, subobject, NULL);
              m_fileData->addClassDefinition(fullSubName, def);
              pdef->addClassDefinition(fullSubName, def);
            }
          }
          break;
        }
        case VObjectType::slProgram_declaration: {
          Program* mdef = new Program(fullName, lib, m_fileData, object);
          m_fileData->addProgramDefinition(fullName, mdef);

          std::vector<VObjectType> subtypes = {
              VObjectType::slClass_declaration};
          std::vector<NodeId> subobjects =
              m_fileData->sl_collect_all(object, subtypes, subtypes);
          for (auto subobject : subobjects) {
            NodeId stId =
                m_fileData->sl_collect(subobject, VObjectType::slStringConst,
                                       VObjectType::slAttr_spec);
            if (stId != InvalidNodeId) {
              std::string name = SymName(stId);
              std::string fullSubName = fullName + "::" + name;
              m_fileData->insertObjectLookup(fullSubName, subobject,
                                             m_errorContainer);
              ClassDefinition* def = new ClassDefinition(
                  fullSubName, lib, mdef, m_fileData, subobject, NULL);
              m_fileData->addClassDefinition(fullSubName, def);
              mdef->addClassDefinition(fullSubName, def);
            }
          }
          break;
        }
        case VObjectType::slClass_declaration: {
          ClassDefinition* def = new ClassDefinition(fullName, lib, NULL,
                                                     m_fileData, object, NULL);
          m_fileData->addClassDefinition(fullName, def);
          break;
        }
        case VObjectType::slModule_declaration: {
          ModuleDefinition* mdef =
              new ModuleDefinition(m_fileData, object, fullName);
          m_fileData->addModuleDefinition(fullName, mdef);

          std::vector<VObjectType> subtypes = {
              VObjectType::slClass_declaration,
              VObjectType::slModule_declaration};
          std::vector<NodeId> subobjects =
              m_fileData->sl_collect_all(object, subtypes, subtypes);
          for (auto subobject : subobjects) {
            NodeId stId =
                m_fileData->sl_collect(subobject, VObjectType::slStringConst,
                                       VObjectType::slAttr_spec);
            if (stId != InvalidNodeId) {
              std::string name = SymName(stId);
              std::string fullSubName = fullName + "::" + name;
              m_fileData->insertObjectLookup(fullSubName, subobject,
                                             m_errorContainer);

              if (m_fileData->Type(subobject) ==
                  VObjectType::slClass_declaration) {
                ClassDefinition* def = new ClassDefinition(
                    fullSubName, lib, mdef, m_fileData, subobject, NULL);
                m_fileData->addClassDefinition(fullSubName, def);
                mdef->addClassDefinition(fullSubName, def);
              } else {
                ModuleDefinition* def =
                    new ModuleDefinition(m_fileData, subobject, fullSubName);
                m_fileData->addModuleDefinition(fullSubName, def);
              }
            }
          }

          break;
        }
        case VObjectType::slConfig_declaration:
        case VObjectType::slUdp_declaration:
        case VObjectType::slInterface_declaration:
        default:
          ModuleDefinition* def =
              new ModuleDefinition(m_fileData, object, fullName);
          m_fileData->addModuleDefinition(fullName, def);
          break;
      }
    }
  }
}

VObject& ResolveSymbols::Object(NodeId index) {
  if (index == InvalidNodeId) return m_fileData->Object(0);
  return m_fileData->Object(index);
}

NodeId ResolveSymbols::UniqueId(NodeId index) { return index; }

SymbolId ResolveSymbols::Name(NodeId index) {
  if (index == InvalidNodeId) return 0;
  return Object(index).m_name;
}

NodeId ResolveSymbols::Child(NodeId index) {
  if (index == InvalidNodeId) return 0;
  return Object(index).m_child;
}

NodeId ResolveSymbols::Sibling(NodeId index) {
  if (index == InvalidNodeId) return 0;
  return Object(index).m_sibling;
}

static NodeId UndefinedObjectDefinition = 0;
NodeId& ResolveSymbols::Definition(NodeId index) {
  if (index == InvalidNodeId) return UndefinedObjectDefinition;
  return Object(index).m_definition;
}

NodeId ResolveSymbols::Parent(NodeId index) {
  if (index == InvalidNodeId) return 0;
  return Object(index).m_parent;
}

static unsigned short UndefinedObjectType = 0;
unsigned short& ResolveSymbols::Type(NodeId index) {
  if (index == InvalidNodeId) return UndefinedObjectType;
  return Object(index).m_type;
}

unsigned int ResolveSymbols::Line(NodeId index) {
  if (index == InvalidNodeId) return 0;
  return Object(index).m_line;
}

std::string ResolveSymbols::Symbol(SymbolId id) {
  return m_fileData->getSymbolTable()->getSymbol(id);
}

NodeId ResolveSymbols::sl_get(NodeId parent, VObjectType type) {
  return m_fileData->sl_get(parent, type);
}

NodeId ResolveSymbols::sl_parent(NodeId parent, VObjectType type) {
  return m_fileData->sl_parent(parent, type);
}

NodeId ResolveSymbols::sl_parent(NodeId parent, std::vector<VObjectType> types,
                                 VObjectType& actualType) {
  return m_fileData->sl_parent(parent, types, actualType);
}

std::vector<NodeId> ResolveSymbols::sl_get_all(NodeId parent,
                                               VObjectType type) {
  return m_fileData->sl_get_all(parent, type);
}

NodeId ResolveSymbols::sl_collect(NodeId parent, VObjectType type) {
  return m_fileData->sl_collect(parent, type);
}

std::vector<NodeId> ResolveSymbols::sl_collect_all(NodeId parent,
                                                   VObjectType type) {
  return m_fileData->sl_collect_all(parent, type);
}

bool ResolveSymbols::bindDefinition_(unsigned int objIndex,
                                     std::vector<VObjectType> bindTypes) {
  std::string modName =
      SymName(sl_collect(objIndex, VObjectType::slStringConst));
  std::string instName =
      SymName(Child(sl_collect(objIndex, slName_of_instance)));
  Design::FileIdDesignContentMap& all_files =
      this->m_compileDesign->getCompiler()->getDesign()->getAllFileContents();

  bool found = false;
  for (auto file : all_files) {
    SymbolId fileId = file.first;
    FileContent* fcontent = file.second;

    auto itr = fcontent->getObjectLookup().find(modName);
    if (itr != fcontent->getObjectLookup().end()) {
      VObjectType actualType;
      NodeId index = (*itr).second;
      NodeId mod = fcontent->sl_parent(index, bindTypes, actualType);
      if (mod != InvalidNodeId) {
        Definition(objIndex) = mod;
        fcontent->getReferencedObjects().insert(modName);
        m_fileData->SetDefinitionFile(objIndex, fileId);
        switch (actualType) {
          case VObjectType::slUdp_declaration:
            Type(objIndex) = VObjectType::slUdp_instantiation;
            break;
          case VObjectType::slModule_declaration:
            Type(objIndex) = VObjectType::slModule_instantiation;
            break;
          case VObjectType::slInterface_declaration:
            Type(objIndex) = VObjectType::slInterface_instantiation;
            break;
          case VObjectType::slProgram_declaration:
            Type(objIndex) = VObjectType::slProgram_instantiation;
            break;
          default:
            break;
        }
        found = true;
        // std::cout << "FOUND MODEL FOR " << modName << " " << instName <<
        // std::endl; std::cout << m_fileData->printSubTree (objIndex) <<
        // std::endl;
        break;
      }
    }
  }
  return found;
}

bool ResolveSymbols::resolve() {
  unsigned int size = m_fileData->getVObjects().size();
  for (unsigned int objIndex = 0; objIndex < size; objIndex++) {
    // ErrorDefinition::ErrorType errorType;
    bool bind = false;
    if (Type(objIndex) == VObjectType::slUdp_instantiation) {
      bind = true;
      // errorType = ErrorDefinition::ELAB_NO_UDP_DEFINITION;
    } else if (Type(objIndex) == VObjectType::slModule_instantiation) {
      bind = true;
      // errorType = ErrorDefinition::ELAB_NO_MODULE_DEFINITION;
    } else if (Type(objIndex) == VObjectType::slInterface_instantiation) {
      bind = true;
      // errorType = ErrorDefinition::ELAB_NO_INTERFACE_DEFINITION;
    } else if (Type(objIndex) == VObjectType::slProgram_instantiation) {
      bind = true;
      // errorType = ErrorDefinition::ELAB_NO_PROGRAM_DEFINITION;
    }
    if (bind) {
      /*bool found = */
      bindDefinition_(objIndex,
                      {slUdp_declaration, slModule_declaration,
                       slInterface_declaration, slProgram_declaration});
      /*
       * This warning is now treated in the elaboration to give the library
      information if (!found)
        {
          std::string modName = SymName (sl_collect (objIndex, slStringConst));
          Location loc (m_fileData->getFileId (), Line (objIndex), 0,
      m_symbolTable->registerSymbol (modName)); Error err (errorType, loc);
          m_errorContainer->addError (err, false, false);
        }
      */
    }
  }

  return true;
}
