/*
 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 "CompileDesign.h"
#include "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;
}

