/*
 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 "FileContent.h"

#include "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;
}
