/*
 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:   ClassDefinition.cpp
 * Author: alain
 * 
 * Created on June 1, 2018, 10:12 PM
 */
#include "../SourceCompile/SymbolTable.h"
#include "../Design/FileContent.h"
#include "ClassDefinition.h"

using namespace SURELOG;

ClassDefinition::ClassDefinition (std::string name, Library* library, DesignComponent* container, FileContent* fC, NodeId nodeId, ClassDefinition* parent) :
        DesignComponent (container ? container : fC), 
        DataType (fC, nodeId, name, fC ? fC->Type(nodeId) : VObjectType::slClass_declaration),
        m_name (name), m_library (library), m_container (container), m_parent (parent)
{
  addFileContent (fC, nodeId);
}

ClassDefinition::~ClassDefinition () { }


unsigned int ClassDefinition::getSize() {
  NodeId end = m_nodeIds[0];
  NodeId begin = m_fileContents[0]->Child (end);
  unsigned int size = end - begin;
  return size;
}

Property* ClassDefinition::getProperty(const std::string& name) {
  PropertyMap::iterator itr = m_properties.find (name);
  if (itr == m_properties.end ())
    {
      for (auto parent : getBaseClassMap ())
        {
          if (parent.second)
            {
              ClassDefinition* cparent = dynamic_cast<ClassDefinition*> (parent.second);
              if (cparent)
                {
                  Property* d = cparent->getProperty (name);
                  if (d)
                    return d;
                }
            }
        }
      return NULL;
    }
  else
    {
      return (*itr).second;
    }
}

void ClassDefinition::insertProperty(Property* p) {
  m_properties.insert(std::make_pair(p->getName (), p));
}

Function* ClassDefinition::getFunction(const std::string& name) {
  FunctionMap::iterator itr = m_functions.find (name);
  if (itr != m_functions.end ())
    {
      return (*itr).second;
    }

  for (auto parent : getBaseClassMap ())
    {
      if (parent.second)
        {
          ClassDefinition* cparent = dynamic_cast<ClassDefinition*> (parent.second);
          if (cparent)
            {
              Function* d = cparent->getFunction (name);
              if (d)
                return d;
            }
        }
    }
  
  if (m_container)
    {
      return m_container->getFunction (name);
    }
  
  return NULL;
}


TaskMethod* ClassDefinition::getTask(const std::string& name) {
  TaskMap::iterator itr = m_tasks.find (name);
  if (itr == m_tasks.end ())
    {
      for (auto parent : getBaseClassMap ())
        {
          if (parent.second)
            {
              ClassDefinition* cparent = dynamic_cast<ClassDefinition*> (parent.second);
              if (cparent)
                {
                  TaskMethod* d = cparent->getTask (name);
                  if (d)
                    return d;
                }
            }
        }
      return NULL;
    }
  else
    {
      return (*itr).second;
    }
}

void ClassDefinition::insertTask(TaskMethod* p) {
  m_tasks.insert(std::make_pair(p->getName (), p));
}

Constraint* ClassDefinition::getConstraint(const std::string& name) {
  ConstraintMap::iterator itr = m_constraints.find(name);
  if (itr == m_constraints.end ())
    {
      return NULL;
    }
  else 
    {
      return (*itr).second;
    }
}

void ClassDefinition::insertConstraint(Constraint* p) {
  m_constraints.insert(std::make_pair(p->getName (), p));
}

ClassDefinition* ClassDefinition::getClass(const std::string& name) {
  ClassMap::iterator itr = m_classes.find(name);
  if (itr == m_classes.end ())
    {
      return NULL;
    }
  else 
    {
      return (*itr).second;
    }
}

void ClassDefinition::insertClass(ClassDefinition* p) {
  m_classes.insert(std::make_pair(p->getName (), p));
}

CoverGroupDefinition* ClassDefinition::getCoverGroup(const std::string& name) {
  CoverGroupMap::iterator itr = m_covergroups.find(name);
  if (itr == m_covergroups.end ())
    {
      return NULL;
    }
  else 
    {
      return (*itr).second;
    }
}

void ClassDefinition::insertCoverGroup(CoverGroupDefinition* p) {
  m_covergroups.insert(std::make_pair(p->getName (), p));
}

DataType*
ClassDefinition::getBaseClass (const std::string& name)
{
  BaseClassMap::iterator itr = m_baseclasses.find (name);
  if (itr == m_baseclasses.end ())
    {
      return NULL;
    }
  else
    {
      return (*itr).second;
    }
}

void
ClassDefinition::insertBaseClass (DataType* p)
{
  m_baseclasses.insert (std::make_pair (p->getName (), p));
}


Parameter*
ClassDefinition::getParameter (const std::string& name)
{
  ParameterMap::iterator itr = m_parameters.find (name);
  if (itr == m_parameters.end ())
    {
      return NULL;
    }
  else
    {
      return (*itr).second;
    }
}

void
ClassDefinition::insertParameter (Parameter* p)
{
  m_parameters.insert (std::make_pair (p->getName (), p));
}

DataType*
ClassDefinition::getBaseDataType (std::string name)
{
  DataTypeMap& dataTypes = getDataTypeMap();
  DataTypeMap::iterator itr = dataTypes.find (name);
  if (itr == dataTypes.end ())
    {
      for (auto parent : getBaseClassMap ())
        {
          if (parent.second)
            {
              ClassDefinition* cparent = dynamic_cast<ClassDefinition*> (parent.second);
              if (cparent)
                {
                  DataType* d = cparent->getBaseDataType (name);
                  if (d)
                    return d;
                }
            }
        }
      return NULL;
    }
  else
    {
      return (*itr).second;
    }
}

bool
ClassDefinition::hasCompleteBaseSpecification () {
  
      for (auto parent : getBaseClassMap ())
        {
          if (parent.second)
            {
              ClassDefinition* cparent = dynamic_cast<ClassDefinition*> (parent.second);
              if (cparent)
                {
                  return cparent->hasCompleteBaseSpecification ();
                }
              Parameter* param = dynamic_cast<Parameter*> (parent.second);
              if (param)
                return false;
            }
        }
      return true;
 }


