/*
 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:   CompileDesign.cpp
 * Author: alain
 * 
 * Created on July 1, 2017, 1:11 PM
 */
#include "../SourceCompile/SymbolTable.h"
#include "../Library/Library.h"
#include "../Design/FileContent.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 "../CommandLine/CommandLineParser.hpp"
#include "../SourceCompile/ParseFile.h"
#include "../Testbench/ClassDefinition.h"
#include "../SourceCompile/Compiler.h"
#include "CompileDesign.h"
#include "ResolveSymbols.h"
#include "DesignElaboration.h"
#include "UVMElaboration.h"
#include "CompilePackage.h"
#include "CompileModule.h"
#include "CompileFileContent.h"
#include "CompileProgram.h"
#include "CompileClass.h"
#include "Builtin.h"
#include "PackageAndRootElaboration.h"

#ifdef USETBB
#include <tbb/task.h>
#include <tbb/task_group.h>
#include "tbb/task_scheduler_init.h"
#endif

#include <vector>
#include <thread>

using namespace SURELOG;


CompileDesign::CompileDesign(Compiler* compiler) : m_compiler(compiler) {
}

CompileDesign::CompileDesign(const CompileDesign& orig) { }


CompileDesign::~CompileDesign() {
}


bool
CompileDesign::compile ()
{
  
  Location loc(0);
  Error err1 (ErrorDefinition::COMP_COMPILE, loc);
  ErrorContainer* errors = new ErrorContainer(getCompiler ()->getSymbolTable ());
  errors->regiterCmdLine(getCompiler ()->getCommandLineParser ());
  errors->addError (err1);
  errors->printMessage (err1, getCompiler ()->getCommandLineParser ()->muteStdout ()); 
  delete errors;
  if (!preCompile_())
    {
      return false;
    }
  
  return true;
}

template <class ObjectType, class ObjectMapType, typename FunctorType>
void
CompileDesign::compileMT_ (ObjectMapType& objects, int maxThreadCount)
{
  if (maxThreadCount == 0)
    {
       for (auto itr : objects)
        {
          FunctorType funct (this, itr.second, m_compiler->getDesign (), m_symbolTables[0], m_errorContainers[0]);
          funct.operator() ();
        }
    }
  else 
    {
      // Optimize the load balance, try to even out the work in each thread by the number of VObjects
      std::vector<unsigned long> jobSize (maxThreadCount);
      for (unsigned short i = 0; i < maxThreadCount; i++)
        {
          jobSize[i] = 0;
        }
      std::vector<std::vector < ObjectType*>> jobArray (maxThreadCount);
      for (auto mod : objects)
        {
          unsigned int size = mod.second->getSize ();
          if (size == 0)
            size = 100;
          unsigned int newJobIndex = 0;
          unsigned long minJobQueue = ULLONG_MAX;
          for (unsigned short ii = 0; ii < maxThreadCount; ii++)
            {
              if (jobSize[ii] < minJobQueue)
                {
                  newJobIndex = ii;
                  minJobQueue = jobSize[ii];
                }
            }
          jobSize[newJobIndex] += size;
          jobArray[newJobIndex].push_back (mod.second);
        }
      
      if (getCompiler ()->getCommandLineParser ()->profile()) 
        { 
          std::cout << "Compilation Task\n";    
          for (unsigned short i = 0; i < maxThreadCount; i++)
            {
              std::cout << "Thread " << i << " : \n";
              for (unsigned int j = 0; j < jobArray[i].size (); j++)
                { 
                  std::cout << jobArray[i][j]->getName() << "\n";
                }
            }
        }    
      
      // Create the threads with their respective workloads
      std::vector<std::thread*> threads;
      for (unsigned short i = 0; i < maxThreadCount; i++)
        {
          std::thread* th = new std::thread ([ = ]{
                                             for (unsigned int j = 0; j < jobArray[i].size (); j++)
              {
                                             FunctorType funct (this, jobArray[i][j], m_compiler->getDesign (), m_symbolTables[i], m_errorContainers[i]);
                                             funct.operator() ();
              }
          });
          threads.push_back (th);
        }
      // Sync the threads
      for (unsigned int th = 0; th < threads.size (); th++)
        {
          threads[th]->join ();
        }
      // Delete the threads
      for (unsigned int th = 0; th < threads.size (); th++)
        {
          delete threads[th];
        }
    }
}

void CompileDesign::collectObjects_ (Design::FileIdDesignContentMap& all_files, Design* design, bool finalCollection)
{
  
  typedef std::map<std::string, std::vector<Package*>> FileNamePackageMap;
  FileNamePackageMap fileNamePackageMap;
  SymbolTable* symbols = m_compiler->getSymbolTable ();
  ErrorContainer* errors = m_compiler->getErrorContainer ();
  // Collect all packages and module definitions
  for (Design::FileIdDesignContentMap::iterator itr = all_files.begin (); itr != all_files.end (); itr++)
    {
      FileContent* fC = (*itr).second;
      std::string fileName = fC->getChunkFileName ();
      Library* lib = fC->getLibrary ();
      for (auto mod : fC->getModuleDefinitions ())
        {
          ModuleDefinition* existing = design->getModuleDefinition (mod.first);
          if (existing)
            {
              FileContent* oldFC = existing->getFileContents ()[0];
              FileContent* oldParentFile = oldFC->getParent ();
              
              ModuleDefinition* newM = mod.second;
              FileContent* newFC = newM->getFileContents ()[0];
              FileContent* newParentFile = newFC->getParent ();
              
              if (oldParentFile && (oldParentFile == newParentFile))
                {
                  // Recombine splitted module
                  existing->addFileContent (mod.second->getFileContents ()[0], mod.second->getNodeIds ()[0]);
                  for (auto classdef : mod.second->getClassDefinitions ())
                    {
                      existing->addClassDefinition (classdef.first, classdef.second);
                      classdef.second->setContainer (existing);
                    }
                }
              else
                {
                  design->addModuleDefinition (mod.first, mod.second);
                  if (finalCollection)
                    lib->addModuleDefinition (mod.second);
                }
            }
          else
            {
              design->addModuleDefinition (mod.first, mod.second);
              if (finalCollection)
                lib->addModuleDefinition (mod.second);
            }          
        }
      for (auto prog : fC->getProgramDefinitions ())
        {
          design->addProgramDefinition (prog.first, prog.second);        
        }
      for (auto pack : fC->getPackageDefinitions ())
        {
          Package* existing = design->getPackage (pack.first);
          if (existing)
            {
              FileContent* oldFC = existing->getFileContents ()[0];
              FileContent* oldParentFile = oldFC->getParent ();
              NodeId oldNodeId = existing->getNodeIds ()[0];
              std::string oldFileName = oldFC->getFileName ();
              unsigned int oldLine = oldFC->Line(oldNodeId);
              Package* newP = pack.second;
              FileContent* newFC = newP->getFileContents ()[0];
              FileContent* newParentFile = newFC->getParent ();
              NodeId newNodeId = newP->getNodeIds ()[0];
              std::string newFileName = newFC->getFileName ();
              unsigned int newLine = newFC->Line(newNodeId);
              if (!finalCollection)
                {
                  if (((oldParentFile != newParentFile) || (oldParentFile == NULL && newParentFile == NULL)) && ((oldFileName != newFileName) || (oldLine != newLine)))
                    {
                      Location loc1 (symbols->registerSymbol (oldFileName), oldLine, 0, symbols->registerSymbol (pack.first));
                      Location loc2 (symbols->registerSymbol (newFileName), newLine, 0, symbols->registerSymbol (pack.first));
                      Error err (ErrorDefinition::COMP_MULTIPLY_DEFINED_PACKAGE, loc1, loc2);
                      errors->addError (err);
                    }
                }
              if (oldParentFile && (oldParentFile == newParentFile))
                {
                  // Recombine splitted package
                  existing->addFileContent (newFC, newNodeId);
                  for (auto classdef : pack.second->getClassDefinitions ())
                    {
                      existing->addClassDefinition (classdef.first, classdef.second);
                      classdef.second->setContainer (existing);
                    }
                }
              else
                {
                  design->addPackageDefinition (pack.first, pack.second);
                }
            }
          else
            {
              design->addPackageDefinition (pack.first, pack.second);
            }
        }
      for (auto def : fC->getClassDefinitions ())
        {
          design->addClassDefinition (def.first, def.second);
          for (auto def1 : def.second->getClassMap ())  
            {
              design->addClassDefinition (def1.first, def1.second);
            }
        }
    }
}

bool CompileDesign::elaborate() {
  Location loc(0);
  Error err2 (ErrorDefinition::ELAB_ELABORATING_DESIGN, loc);
  ErrorContainer* errors = new ErrorContainer(getCompiler ()->getSymbolTable ());
  errors->regiterCmdLine(getCompiler ()->getCommandLineParser ());
  errors->addError (err2);
  errors->printMessage (err2, getCompiler ()->getCommandLineParser ()->muteStdout ()); 
  delete errors;
  if (!elaboration_()) 
    {
      return false;
    }
  return true;
 }

bool
CompileDesign::preCompile_()
{
  Design* design = m_compiler->getDesign ();
  
  auto& all_files = design->getAllFileContents ();
  
  int maxThreadCount = m_compiler->getCommandLineParser ()->getNbMaxTreads ();
  if (maxThreadCount == 0)
    {
      SymbolTable* symbols = new SymbolTable (*m_compiler->getCommandLineParser ()->getSymbolTable ());
      m_symbolTables.push_back (symbols);
       
      ErrorContainer* errors = new ErrorContainer (symbols);
      errors->regiterCmdLine (m_compiler->getCommandLineParser ());
      m_errorContainers.push_back (errors);
             
    }
  else if (m_compiler->getCommandLineParser ()->useTbb ())
    {
#ifdef USETBB
      // Use TBB Thread management
      
      tbb::task_group& group = m_compiler->getTaskGroup ();
      for (Design::FileIdDesignContentMap::iterator itr = all_files.begin ();
              itr != all_files.end (); itr++)
        {
          group.run (FunctorCreateLookup (this, (*itr).second));
        }
      group.wait ();

#endif
    }
  else
    {
      for (unsigned short i = 0; i < maxThreadCount; i++)
        {
          SymbolTable* symbols = new SymbolTable (*m_compiler->getCommandLineParser ()->getSymbolTable ());
          m_symbolTables.push_back (symbols);
          ErrorContainer* errors = new ErrorContainer (symbols);
          errors->regiterCmdLine (m_compiler->getCommandLineParser ());
          m_errorContainers.push_back (errors);
        }
    }

  compileMT_ <FileContent, Design::FileIdDesignContentMap, FunctorCreateLookup> (
                                                                                 all_files, maxThreadCount);

  compileMT_ <FileContent, Design::FileIdDesignContentMap, FunctorResolve> (
                                                                            all_files, maxThreadCount);

  compileMT_ <FileContent, Design::FileIdDesignContentMap, FunctorCompileFileContent> (
                                                                                       all_files, maxThreadCount);
  collectObjects_ (all_files, design, false);
  m_compiler->getDesign ()->orderPackages ();

  // Compile packages in strict order        
  //compileMT_ <Package, PackageNamePackageDefinitionMap, FunctorCompilePackage> (
  //                                                                             m_compiler->getDesign ()->getPackageDefinitions (), 0);
  for (auto itr : m_compiler->getDesign ()->getOrderedPackageDefinitions ())
    {
      FunctorCompilePackage funct (this, itr, m_compiler->getDesign (), m_symbolTables[0], m_errorContainers[0]);
      funct.operator() ();
    }
  
  // Compile modules
  compileMT_ <ModuleDefinition, ModuleNameModuleDefinitionMap, FunctorCompileModule> (
                                                                                      m_compiler->getDesign ()->getModuleDefinitions (), maxThreadCount);

  // Compile programs
  compileMT_ <Program, ProgramNameProgramDefinitionMap, FunctorCompileProgram> (
                                                                                m_compiler->getDesign ()->getProgramDefinitions (), maxThreadCount);

  // Compile classes
  compileMT_ <ClassDefinition, ClassNameClassDefinitionMultiMap, FunctorCompileClass> (
                                                                                  m_compiler->getDesign ()->getClassDefinitions (), maxThreadCount);
  design->clearContainers ();
  collectObjects_ (all_files, design, true);

  Builtin* builtin = new Builtin(design);
  builtin->addBuiltins ();

  m_compiler->getDesign ()->orderPackages ();
  
  unsigned int size = m_symbolTables.size ();
  for (unsigned int i = 0; i < size; i++)
    {
      m_compiler->getErrorContainer ()->appendErrors (*m_errorContainers[i]);
      delete m_symbolTables[i];
      delete m_errorContainers[i];
    }

  return true;
}

bool
CompileDesign::checkPrecompilation_ ()
{
  return true;
}

bool
CompileDesign::elaboration_ ()
{

  int maxThreadCount = m_compiler->getCommandLineParser ()->getNbMaxTreads ();
  maxThreadCount = 0;
  if (maxThreadCount == 0)
    {
      PackageAndRootElaboration* packEl = new PackageAndRootElaboration(this);
      packEl->elaborate ();
      delete packEl;
      DesignElaboration* designEl = new DesignElaboration (this);
      designEl->elaborate ();
      delete designEl;
      UVMElaboration* uvmEl = new UVMElaboration (this);
      uvmEl->elaborate ();
      delete uvmEl;
    }
  else 
    {
    PackageAndRootElaboration* packEl = new PackageAndRootElaboration(this);
    packEl->elaborate ();
    delete packEl;  
      
    std::vector<std::thread*> threads;

    std::thread* th = new std::thread ([ = ]{
                                     DesignElaboration* designEl = new DesignElaboration (this);
                                     designEl->elaborate ();
                                     delete designEl;
    });
    threads.push_back (th);

    th = new std::thread ([ = ]{
                        UVMElaboration* uvmEl = new UVMElaboration (this);
                        uvmEl->elaborate ();
                        delete uvmEl;
    });
    threads.push_back (th);

    // Sync the threads
    for (unsigned int th = 0; th < threads.size (); th++)
      {
        threads[th]->join ();
      }

    // Delete the threads
    for (unsigned int th = 0; th < threads.size (); th++)
      {
        delete threads[th];
      }
    }
  return true;
}




