/*
 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:   ModuleInstance.cpp
 * Author: alain
 *
 * Created on October 16, 2017, 10:48 PM
 */
#include <string>
#include <iostream>
#include "SourceCompile/SymbolTable.h"
#include "Library/Library.h"
#include "Design/FileContent.h"

#include "Design/ModuleInstance.h"
using namespace SURELOG;

ModuleInstance::ModuleInstance(DesignComponent* moduleDefinition,
                               FileContent* fileContent, NodeId nodeId,
                               ModuleInstance* parent, std::string instName,
                               std::string modName)
    : ValuedComponentI(parent),
      m_definition(moduleDefinition),
      m_childrens(NULL),
      m_nbChildren(0),
      m_fileContent(fileContent),
      m_nodeId(nodeId),
      m_parent(parent),
      m_instName(instName) {
  if (m_definition == NULL) {
    m_instName = modName + "&" + instName;
  }
}

ModuleInstance::~ModuleInstance() {}

void ModuleInstance::addSubInstances(ModuleInstance** subInstances,
                                     unsigned int nbSubInstances) {
  m_childrens = subInstances;
  m_nbChildren = nbSubInstances;
}

ModuleInstance* ModuleInstanceFactory::newModuleInstance(
    DesignComponent* moduleDefinition, FileContent* fileContent, NodeId nodeId,
    ModuleInstance* parent, std::string instName, std::string modName) {
  return new ModuleInstance(moduleDefinition, fileContent, nodeId, parent,
                            instName, modName);
}

VObjectType ModuleInstance::getType() { return m_fileContent->Type(m_nodeId); }

VObjectType ModuleInstance::getModuleType() {
  VObjectType type = (VObjectType)0;
  if (m_definition) {
    type = m_definition->getType();
  }
  return type;
}

unsigned int ModuleInstance::getLineNb() {
  return m_fileContent->Line(m_nodeId);
}

SymbolId ModuleInstance::getFullPathId(SymbolTable* symbols) {
  return symbols->registerSymbol(getFullPathName());
}

SymbolId ModuleInstance::getInstanceId(SymbolTable* symbols) {
  return symbols->registerSymbol(getInstanceName());
}
SymbolId ModuleInstance::getModuleNameId(SymbolTable* symbols) {
  return symbols->registerSymbol(getModuleName());
}

std::string ModuleInstance::getFullPathName() {
  std::string path;
  ModuleInstance* tmp = this;
  std::vector<std::string> nibbles;
  while (tmp) {
    nibbles.push_back(tmp->getInstanceName());
    tmp = tmp->getParent();
  }
  for (int i = nibbles.size() - 1; i >= 0; i--) {
    path += nibbles[i];
    if (i > 0) {
      path += ".";
    }
  }
  return path;
}

unsigned int ModuleInstance::getDepth() {
  unsigned int depth = 0;
  ModuleInstance* tmp = this;
  while (tmp) {
    tmp = tmp->getParent();
    depth++;
  }
  return depth;
}

std::string ModuleInstance::getInstanceName() {
  if (m_definition == NULL) {
    std::string name =
        m_instName.substr(m_instName.find("&", 0, 1) + 1, m_instName.size());
    return name;
  } else {
    return m_instName;
  }
}

std::string ModuleInstance::getModuleName() {
  if (m_definition == NULL) {
    std::string name = m_instName.substr(0, m_instName.find("&", 0, 1));
    return name;
  } else {
    return m_definition->getName();
  }
}

void ModuleInstance::overrideParentChild(ModuleInstance* parent,
                                         ModuleInstance* interm,
                                         ModuleInstance* child) {
  if (parent != this) return;
  child->m_parent = this;
  std::vector<ModuleInstance*> children;

  for (unsigned int i = 0; i < m_nbChildren; i++) {
    if (m_childrens[i] == interm) {
      for (unsigned int j = 0; j < interm->m_nbChildren; j++) {
        children.push_back(interm->m_childrens[j]);
      }
    } else {
      children.push_back(m_childrens[i]);
    }
  }

  ModuleInstance** newChild = new ModuleInstance*[children.size()];
  for (unsigned int i = 0; i < children.size(); i++) {
    newChild[i] = children[i];
  }
  m_nbChildren = children.size();
  delete[] m_childrens;
  m_childrens = newChild;
}
