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