/*
 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:   DesignComponent.cpp
 * Author: alain
 * 
 * Created on March 25, 2018, 10:27 PM
 */
#include <vector>
#include "../SourceCompile/SymbolTable.h"
#include "../SourceCompile/VObjectTypes.h"
#include "FileContent.h"
#include "DesignComponent.h"
#include "Function.h"
#include "../Testbench/Variable.h"

using namespace SURELOG;

void DesignComponent::addFileContent (FileContent* fileContent, NodeId nodeId) { 
  bool add = true;
  for (auto f : m_fileContents)
    if (fileContent == f) 
      add = false;
  if (add)
    {
      m_fileContents.push_back(fileContent); 
      m_nodeIds.push_back(nodeId);
    }
}

std::vector<FileCNodeId>& DesignComponent::getObjects(VObjectType type)
{
  auto itr = m_objects.find(type);
  if (itr == m_objects.end())
    {
      return m_empty;
    }
  else 
    {
      return (*itr).second;
    }
}


void DesignComponent::addObject(VObjectType type, FileCNodeId object)
{
  auto itr = m_objects.find(type);
  if (itr == m_objects.end())
    {
      std::vector<FileCNodeId> tmp;
      tmp.push_back (object);
      m_objects.insert(std::make_pair(type, tmp));
    }
  else
    {
      (*itr).second.push_back (object);
    }
}

void
DesignComponent::addNamedObject (std::string name, FileCNodeId object, DesignComponent* def) {
  m_namedObjects.insert(std::make_pair(name, std::make_pair(object, def)));
}

std::pair<FileCNodeId, DesignComponent*>* DesignComponent::getNamedObject (std::string name) {
  std::map<std::string, std::pair<FileCNodeId, DesignComponent*>>::iterator itr = m_namedObjects.find(name);
  if (itr == m_namedObjects.end()) 
    {
      return NULL;
    }
  else
    {
      return &(*itr).second;
    }
}

void DesignComponent::append(DesignComponent* comp) {
  for (auto file : comp->m_fileContents)
    m_fileContents.push_back (file);
  for (auto nodeId : comp->m_nodeIds)
    m_nodeIds.push_back (nodeId);
  for (auto& obj : comp->m_objects)
    {
      for (auto& elem : obj.second)
        addObject(obj.first, elem);
    }
  for (auto& obj : comp->m_namedObjects)
    {
      addNamedObject(obj.first, obj.second.first, obj.second.second);
    }
  for (auto dtype : comp->m_dataTypes)
    insertDataType(dtype.first, dtype.second);
}


void DesignComponent::insertDataType(const std::string& dataTypeName, DataType* dataType) {
  m_dataTypes.insert(std::make_pair(dataTypeName, dataType));
}

DataType* DesignComponent::getDataType(const std::string& name) {
  DataTypeMap::iterator itr = m_dataTypes.find(name);
  if (itr == m_dataTypes.end ())
    {
      DesignComponent* parent = (DesignComponent*) getParentScope ();
      if (parent)
        {
          return parent->getDataType (name);
        }
      else 
        return NULL;
    }
  else 
    {
      return (*itr).second;
    }
}

void DesignComponent::insertUsedDataType(const std::string& dataTypeName, DataType* dataType) {
  m_usedDataTypes.insert(std::make_pair(dataTypeName, dataType));
}

DataType* DesignComponent::getUsedDataType(const std::string& name) {
  DataTypeMap::iterator itr = m_usedDataTypes.find(name);
  if (itr == m_usedDataTypes.end ())
    {
        return NULL;
    }
  else 
    {
      return (*itr).second;
    }
}

TypeDef* DesignComponent::getTypeDef(const std::string& name) {
  TypeDefMap::iterator itr = m_typedefs.find(name);
  if (itr == m_typedefs.end ())
    {
      DesignComponent* parent = dynamic_cast<DesignComponent*> (getParentScope ());
      if (parent)
        {
          return parent->getTypeDef(name);
        }
      else 
        return NULL;
    }
  else 
    {
      return (*itr).second;
    }
}

void DesignComponent::insertTypeDef(TypeDef* p) {
  m_typedefs.insert(std::make_pair(p->getName (), p));
}

Function* DesignComponent::getFunction(const std::string& name) {
  FunctionMap::iterator itr = m_functions.find(name);
  if (itr == m_functions.end ())
    {
      DesignComponent* parent = dynamic_cast<DesignComponent*> (getParentScope ());
      if (parent)
        {
          return parent->getFunction(name);
        }
      else 
        return NULL;
    }
  else 
    {
      return (*itr).second;
    }
}

void DesignComponent::insertFunction(Function* p) {
  m_functions.insert(std::make_pair(p->getName (), p));
}

void
DesignComponent::addVariable (Variable* var)
{
  m_variables.insert (std::make_pair (var->getName (), var));
}

Variable* DesignComponent::getVariable(const std::string& name) {
  VariableMap::const_iterator itr = m_variables.find(name);
  if (itr == m_variables.end ())
    {
        return NULL;
    }
  else 
    {
      return (*itr).second;
    }
}
