/*
 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:   Design.cpp
 * Author: alain
 * 
 * Created on July 1, 2017, 1:23 PM
 */
#include <queue>
#include <set>
#include "../Utils/StringUtils.h"
#include "../SourceCompile/VObjectTypes.h"
#include "../Design/VObject.h"
#include "FileContent.h"
#include "../SourceCompile/SymbolTable.h"
#include "../ErrorReporting/Error.h"
#include "../ErrorReporting/ErrorContainer.h"
#include "../ErrorReporting/ErrorDefinition.h"
#include "../CommandLine/CommandLineParser.hpp"
#include "../SourceCompile/CompilationUnit.h"
#include "../SourceCompile/PreprocessFile.h"
#include "../SourceCompile/CompileSourceFile.h"
#include "../SourceCompile/Compiler.h"
#include "../SourceCompile/ParseFile.h"
#include "../Utils/FileUtils.h"
#include "Design.h"
#include "../Testbench/ClassDefinition.h"

using namespace SURELOG;


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

Design::~Design() {
}

static std::mutex m;
void Design::addFileContent(SymbolId fileId, FileContent* content) { 
  m.lock();
  m_fileContents.push_back(std::make_pair(fileId, content)) ;
  m.unlock();
}

DesignComponent* Design::getComponentDefinition(const std::string& componentName) {
   DesignComponent* comp = (DesignComponent*) getModuleDefinition(componentName);
   if (comp)
     return comp;
   comp = (DesignComponent*) getProgram(componentName);
   if (comp)
     return comp; 
   comp = (DesignComponent*) getClassDefinition(componentName);
   if (comp)
     return comp; 
   return NULL;
}

ModuleDefinition* Design::getModuleDefinition(const std::string& moduleName) {
  ModuleNameModuleDefinitionMap::iterator itr =  m_moduleDefinitions.find(moduleName);
  if (itr != m_moduleDefinitions.end())
    {
      return (*itr).second;
    }
  return NULL;
}


std::string Design::reportInstanceTree() {
  std::string tree;
  ModuleInstance* tmp;
  std::queue<ModuleInstance*> queue;
  ErrorContainer* errors =  m_compiler->getErrorContainer ();
  SymbolTable* symbols = errors->getSymbolTable ();
  for (auto instance : m_topLevelModuleInstances) 
    {
      queue.push (instance);
    }
  while (!queue.empty ())
    {
      tmp = queue.front ();
      queue.pop();
      if (tmp->getNbChildren ())
        {
          for (unsigned int i = 0; i < tmp->getNbChildren (); i++)
            {
              queue.push (tmp->getChildren (i));
            }
        }
      std::string def;
      def = tmp->getModuleName();
      std::string undef;
      VObjectType type = tmp->getType();
      if (tmp->getDefinition () == NULL)
        {
          undef = " [U]";
        }
      std::string type_s;
      Location loc (symbols->registerSymbol (tmp->getFileName()), tmp->getLineNb (), 0, tmp->getFullPathId (symbols));
      if (type == slUdp_instantiation)
        {
          type_s = "[UDP]";
          Error err (ErrorDefinition::ELAB_INSTANCE_PATH, loc);
          errors->addError (err);
        }
      else if (type == VObjectType::slModule_instantiation)
        {
          type_s = "[MOD]";
          Error err (ErrorDefinition::ELAB_INSTANCE_PATH, loc);
          errors->addError (err);
        }
      else if (type ==  VObjectType::slGate_instantiation)
        {
          type_s = "[GAT]";
          Error err (ErrorDefinition::ELAB_INSTANCE_PATH, loc);
          errors->addError (err);
        }
      else if (type == slInterface_instantiation) 
        {
          type_s = "[I/F]";
          Error err (ErrorDefinition::ELAB_INTERFACE_INSTANCE_PATH, loc);
          errors->addError (err); 
        }
      else if (type == slProgram_instantiation) 
        {
          type_s = "[PRG]";
          Error err (ErrorDefinition::ELAB_PROGRAM_INSTANCE_PATH, loc);
          errors->addError (err); 
        }
      else if (type == slModule_declaration) 
        {
          type_s = "[TOP]";
          Error err (ErrorDefinition::ELAB_INSTANCE_PATH, loc);
          errors->addError (err); 
        }
      else 
        {
          type_s = "[SCO]";
          Error err (ErrorDefinition::ELAB_SCOPE_PATH, loc);
          errors->addError (err);
        }
      tree += type_s + " " + def + undef + " " + tmp->getFullPathName () + "\n";
      
    }
  
  
  return tree;
}

void Design::reportInstanceTreeStats(unsigned int& nbTopLevelModules, unsigned int& maxDepth, unsigned int& numberOfInstances, 
                                     unsigned int& numberOfLeafInstances, unsigned int& nbUndefinedModules, unsigned int& nbUndefinedInstances) {
  nbTopLevelModules = 0;
  maxDepth = 0;
  numberOfInstances = 0;
  numberOfLeafInstances = 0;
  nbUndefinedModules = 0;
  nbUndefinedInstances = 0;
  std::set<std::string> undefModules;
  ModuleInstance* tmp;
  std::queue<ModuleInstance*> queue;
  for (auto instance : m_topLevelModuleInstances) 
    {
      queue.push (instance);
      nbTopLevelModules++;
    }
  while (!queue.empty ())
    {
      tmp = queue.front ();
      queue.pop();
      bool isInstance = false;
      if (!tmp->getDefinition ())
        isInstance = true;
      else 
        {
          isInstance = tmp->getDefinition()->isInstance();
        }
           
      if (isInstance)
        {
          numberOfInstances++;
          unsigned int depth = tmp->getDepth ();
          if (depth > maxDepth)
            {
              maxDepth = depth;
            }
        }
      if (tmp->getNbChildren ())
        {
          for (unsigned int i = 0; i < tmp->getNbChildren (); i++)
            {
              queue.push (tmp->getChildren (i));
            }
        }
      else 
        {
          if (isInstance)
            numberOfLeafInstances++;
        }
      std::string def;
      if (tmp->getDefinition())
        {
          
        }
      else 
        {
          nbUndefinedInstances++;
          undefModules.insert(tmp->getModuleName());
        }
     
    }
  
   nbUndefinedModules = undefModules.size();
}



ModuleInstance* Design::findInstance(std::string path, ModuleInstance* scope) {
  std::vector<std::string> vpath;
  StringUtils::tokenize(path, ".", vpath); 
  return findInstance(vpath, scope);
}

ModuleInstance* Design::findInstance(std::vector<std::string>& path, ModuleInstance* scope) {
  if (!path.size())
    return NULL;
  if (scope)
    {
      ModuleInstance* res = findInstance_ (path, scope);
      if (res)
        return res;   
    }
  else
    {
      for (auto top : m_topLevelModuleInstances)
        {
          if (path.size() == 1)
            {
              if (top->getInstanceName () == path[0])
                {
                  return top;
                }
            }
          else 
            {
              if (top->getInstanceName () == path[0])
                {
                  std::vector<std::string> subpath = path;
                  subpath.erase (subpath.begin ());
                  ModuleInstance* res = findInstance_ (subpath, top);
                  if (res)
                    return res;
                }
            }  
        }
    }
  
  return NULL;
}
  
  
ModuleInstance* Design::findInstance_(std::vector<std::string>& path, ModuleInstance* scope) {
  if (!path.size())
    return NULL;
  if (scope == NULL)
    return NULL;
  if (path.size () == 1)
    {
      if (scope->getInstanceName () == path[0])
        {
          return scope;
        }
    }
  
  for (unsigned int i = 0; i < scope->getNbChildren (); i++)
    {
      ModuleInstance* child = scope->getChildren (i);
      if (path.size ())
        {
          if (child->getInstanceName () == path[0])
            {
              if (path.size () == 1)
                {
                  return child;
                }
              else
                {
                  std::vector<std::string> subpath = path;
                  subpath.erase (subpath.begin ());
                  ModuleInstance* res = findInstance (subpath, child);
                  if (res)
                    return res;
                }
            }
        }
    }
  return NULL;
}


DefParam* Design::getDefParam(std::string name) {
  std::vector<std::string> vpath;
  StringUtils::tokenize(name, ".", vpath); 
  std::map<std::string, DefParam*>::iterator itr = m_defParams.find(vpath[0]);
  if (itr != m_defParams.end())
    {
      vpath.erase(vpath.begin());
      return getDefParam_(vpath, (*itr).second);
    }
  return NULL;
}

Value* Design::getDefParamValue(std::string name) {
  DefParam* def = getDefParam(name);
  if (def)
    return def->getValue ();
  return NULL;
}

DefParam* Design::getDefParam_(std::vector<std::string>& path, DefParam* parent) {
  if (path.size() == 0)
    {
      return parent;
    }
  std::map<std::string, DefParam*>::iterator itr = parent->getChildren ().find (path[0]);
  if (itr != parent->getChildren ().end ())
    {
      path.erase (path.begin ());
      return getDefParam_ (path, (*itr).second);
    }
  return NULL;
}

void Design::addDefParam(std::string name, FileContent* fC, NodeId nodeId, Value* value) {
  std::vector<std::string> vpath;
  StringUtils::tokenize(name, ".", vpath); 
  std::map<std::string, DefParam*>::iterator itr = m_defParams.find(vpath[0]);
  if (itr != m_defParams.end())
    {
      vpath.erase(vpath.begin());
      addDefParam_(vpath, fC, nodeId, value, (*itr).second);
    }
  else 
    {
      DefParam* def = new DefParam (vpath[0]);
      m_defParams.insert(std::make_pair(vpath[0], def));
      vpath.erase (vpath.begin ());
      addDefParam_ (vpath, fC, nodeId, value, def);
    }
}

void
Design::addDefParam_ (std::vector<std::string>& path, FileContent* fC, NodeId nodeId, Value* value, DefParam* parent)
{
  if (path.size() == 0)
    {
      parent->setValue (value);
      parent->setLocation (fC, nodeId);
      return;
    }
  std::map<std::string, DefParam*>::iterator itr = parent->getChildren ().find (path[0]);
  if (itr != parent->getChildren ().end ())
    {
      path.erase (path.begin ());
      if (path.size() == 0)
        {
          DefParam* previous = (*itr).second;
          if ((fC->getFileId (nodeId) != previous->getLocation ()->getFileId (previous->getNodeId ())) || 
              (fC->Line (nodeId) != previous->getLocation ()->Line (previous->getNodeId ())))
            {
              Location loc1 (fC->getFileId (nodeId),
                             fC->Line (nodeId),
                             0,
                             m_compiler->getErrorContainer ()->getSymbolTable ()->registerSymbol (previous->getFullName ()));
              Location loc2 (previous->getLocation ()->getFileId (previous->getNodeId ()),
                             previous->getLocation ()->Line (previous->getNodeId ()),
                             0,
                             0);
              Error err (ErrorDefinition::ELAB_MULTI_DEFPARAM_ON_OBJECT, loc1, loc2);
              m_compiler->getErrorContainer ()->addError (err);
          }
        }
      addDefParam_ (path, fC, nodeId, value, (*itr).second);
    }
  else
    {
      DefParam* def = new DefParam (path[0], parent);
      parent->setChild (path[0], def);
      path.erase (path.begin ());
      addDefParam_ (path, fC, nodeId, value, def);
    }
}

void
Design::checkDefParamUsage (DefParam* parent)
{
  if (parent == NULL)
    {
      // Start by all the top defs of the trie
      for (auto top : m_defParams)
        {
          checkDefParamUsage (top.second);
        }
    }
  else
    {
      // Check the leaf
      if (parent->getValue () && (!parent->isUsed ()))
        {
          if (parent->getParent ())
            {            
              ModuleInstance* inst = findInstance (parent->getParent ()->getFullName ());
              if (inst && (!inst->getDefinition ()))
                {
                 return;
                }
              else 
                {
                }
            }
          else 
            {
              return;
            }

          Location loc (parent->getLocation ()->getFileId (parent->getNodeId ()),
                        parent->getLocation ()->Line (parent->getNodeId ()),
                        0,
                        m_compiler->getErrorContainer ()->getSymbolTable ()->registerSymbol (parent->getFullName ()));

          Error err (ErrorDefinition::ELAB_UNMATCHED_DEFPARAM, loc);
          m_compiler->getErrorContainer ()->addError (err);
                
        }
      for (auto param : parent->getChildren ())
        {
          checkDefParamUsage (param.second);
        }
    }
}


Package* Design::getPackage(std::string name) {
  PackageNamePackageDefinitionMultiMap::iterator itr = m_packageDefinitions.find(name);
  if (itr == m_packageDefinitions.end())
    {
      return NULL;
    }
  else 
    {
      return (*itr).second;
    }
}


Program* Design::getProgram(std::string name) {
  ProgramNameProgramDefinitionMap::iterator itr = m_programDefinitions.find(name);
  if (itr == m_programDefinitions.end())
    {
      return NULL;
    }
  else 
    {
      return (*itr).second;
    }
}


ClassDefinition* Design::getClassDefinition(std::string name) {
  ClassNameClassDefinitionMap::iterator itr = m_uniqueClassDefinitions.find(name);
  if (itr == m_uniqueClassDefinitions.end())
    {
      return NULL;
    }
  else 
    {
      return (*itr).second;
    }
}

void Design::orderPackages()
{
  if (m_orderedPackageNames.size () == 0)
    return;
  m_orderedPackageDefinitions.resize (m_orderedPackageNames.size ());
  unsigned int index = 0;
  typedef std::map<std::string, int> MultiDefCount;
  MultiDefCount multiDefCount;
  for (auto packageName : m_orderedPackageNames)
    {
      for (unsigned int i = 0; i < m_packageDefinitions.size(); i++)
        {
          PackageNamePackageDefinitionMultiMap::iterator pos = m_packageDefinitions.begin();
          for (unsigned ii = 0; ii < i; ii++)
            pos++;          
          std::pair<const std::string, Package*>* name_pack;
          name_pack = &(*pos);
          
          if (packageName == name_pack->first)
            {
              MultiDefCount::iterator itr = multiDefCount.find(packageName);
              if (itr == multiDefCount.end())
                {
                  multiDefCount.insert(std::make_pair(packageName, 1));
                }
              else
                {
                  int level = (*itr).second;
                  (*itr).second++;
                  pos = m_packageDefinitions.begin();
                  for (unsigned ii = 0; ii < i + level; ii++)
                     pos++;     
                  name_pack = &(*pos);
                }
              m_orderedPackageDefinitions[index] = name_pack->second;
              index++;
              break;
            }
        }
    }
}

Package* Design::addPackageDefinition(std::string packageName, Package* package) {
  PackageNamePackageDefinitionMultiMap::iterator itr = m_packageDefinitions.find(packageName);
  if (itr == m_packageDefinitions.end())
    {
      m_packageDefinitions.insert(std::make_pair(packageName, package)); 
      return package;
    } 
  else 
    {
      Package* old = (*itr).second;
      if (old->getFileContents()[0]->getParent() && (old->getFileContents()[0]->getParent() == package->getFileContents()[0]->getParent()))
        {
           old->append(package);
           return old;
        }
      else 
        {
          m_packageDefinitions.insert(std::make_pair(packageName, package)); 
          return package;
        }
    }
}

void Design::addClassDefinition(std::string className, ClassDefinition* classDef) {
  m_classDefinitions.insert(std::make_pair(className, classDef)); 
  m_uniqueClassDefinitions.insert(std::make_pair(className, classDef));
}

    
void Design::clearContainers() {
    
    m_moduleDefinitions.clear();

    m_topLevelModuleInstances.clear();
    
    m_defParams.clear(); 
    
    m_packageDefinitions.clear();
    m_orderedPackageDefinitions.clear(); 
    
    m_programDefinitions.clear();
  
    m_classDefinitions.clear();
    
    m_uniqueClassDefinitions.clear();
    
    m_orderedPackageNames.clear();
  
}

