/*
 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();
}
