/*
 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:   CompilePackage.cpp
 * Author: alain
 * 
 * Created on March 22, 2018, 9:57 PM
 */

#include "../SourceCompile/VObjectTypes.h"
#include "../Design/VObject.h"
#include "../Library/Library.h"
#include "../Design/FileContent.h"
#include "../SourceCompile/SymbolTable.h"
#include "../ErrorReporting/Error.h"
#include "../ErrorReporting/Location.h"
#include "../ErrorReporting/Error.h"
#include "../CommandLine/CommandLineParser.hpp"
#include "../ErrorReporting/ErrorDefinition.h"
#include "../ErrorReporting/ErrorContainer.h"
#include "../SourceCompile/CompilationUnit.h"
#include "../SourceCompile/PreprocessFile.h"
#include "../SourceCompile/CompileSourceFile.h"
#include "../SourceCompile/ParseFile.h"
#include "../SourceCompile/Compiler.h"
#include "../Design/Statement.h"
#include "CompileDesign.h"
#include "CompileHelper.h"
#include "CompilePackage.h"

using namespace SURELOG;

int FunctorCompilePackage::operator()() const {
    CompilePackage* instance = new CompilePackage(m_compileDesign, m_package, m_design, m_symbols, m_errors);
    instance->compile();
    delete instance;   
    return true;
}

CompilePackage::~CompilePackage () { }

bool CompilePackage::compile() {
  if (!m_package)
    return false;
  FileContent* fC = m_package->m_fileContents[0];
  NodeId packId = m_package->m_nodeIds[0];
  
  Location loc (m_symbols->registerSymbol (fC->getFileName(packId)), fC->Line(packId), 0, m_symbols->getId(m_package->getName ()));
  Error err (ErrorDefinition::COMP_COMPILE_PACKAGE, loc);
  
  ErrorContainer* errors = new ErrorContainer (m_symbols);
  errors->regiterCmdLine (m_compileDesign->getCompiler ()->getCommandLineParser ());
  errors->addError (err);
  errors->printMessage (err, m_compileDesign->getCompiler ()->getCommandLineParser ()->muteStdout ());
  delete errors;
  
  collectObjects_();

  return true;
}


bool CompilePackage::collectObjects_() {
  
  std::vector<VObjectType> stopPoints = {
    VObjectType::slClass_declaration,
    VObjectType::slFunction_declaration
  };
 
 for (unsigned int i = 0; i < m_package->m_fileContents.size (); i++)
    {
      FileContent* fC = m_package->m_fileContents[i];
      std::string libName = fC->getLibrary ()->getName ();
      VObject current = fC->Object (m_package->m_nodeIds[i]);
      NodeId id = current.m_child;

      if (!id)
        id = current.m_sibling;
      if (!id)
        return false;

      // Package imports 
      std::vector<FileCNodeId> pack_imports;
      // - Local file imports
      for (auto import : fC->getObjects (VObjectType::slPackage_import_item))
        {
          pack_imports.push_back (import);
        }

      for (auto pack_import : pack_imports)
        {
          FileContent* pack_fC = pack_import.fC;
          NodeId pack_id = pack_import.nodeId;
          m_helper.importPackage (m_package, m_design, pack_fC, pack_id);
        }
      
      std::stack<NodeId> stack;
      stack.push (id);
      while (stack.size ())
        {
          id = stack.top ();
          stack.pop ();
          current = fC->Object (id);
          VObjectType type = fC->Type (id);
          switch (type)
            {
            case VObjectType::slPackage_import_item:
              {
                m_helper.importPackage (m_package, m_design, fC, id);            
                break;
              }
            case VObjectType::slParam_assignment:
              {
                NodeId ident = fC->Child (id);
                std::string name = fC->SymName (ident);
                m_package->m_exprBuilder.seterrorReporting (m_errors, m_symbols);
                Value* value = m_package->m_exprBuilder.evalExpr (fC, fC->Sibling (ident), m_package);
                m_package->setValue (name, value, m_package->m_exprBuilder);
                FileCNodeId fnid (fC, id);
                m_package->addObject (type, fnid);
                break;
              }
            case VObjectType::slClass_declaration:
              {
                NodeId nameId = fC->Child (id);
                std::string name = fC->SymName (nameId);
                FileCNodeId fnid (fC, nameId);
                m_package->addObject (type, fnid);

                std::string completeName = m_package->getName () + "::" + name;

                DesignComponent* comp = fC->getComponentDefinition (completeName);

                m_package->addNamedObject (name, fnid, comp);
                break;
              }
            case VObjectType::slData_declaration:
              {
                NodeId subNode = fC->Child (id);
                VObjectType subType = fC->Type (subNode);
                switch (subType)
                  {
                  case VObjectType::slType_declaration:
                    {
                      /*
                        n<> u<15> t<Data_type> p<17> c<8> s<16> l<13>
                        n<fsm_t> u<16> t<StringConst> p<17> l<13>
                        n<> u<17> t<Type_declaration> p<18> c<15> l<13>
                        n<> u<18> t<Data_declaration> p<19> c<17> l<13>
                      */
                      m_helper.compileTypeDef (m_package, fC, id);
                 
                      break;
                    }
                  default:
                    break;
                  }
                break;
              }
            case VObjectType::slDpi_import_export:
            {
              Function* func = m_helper.compileFunctionPrototype (m_package, fC, id);
              m_package->insertFunction (func);
              break;
            }
            default:
              break;
            }

         if (current.m_sibling)
            stack.push (current.m_sibling);
          if (current.m_child)
            {
              if (stopPoints.size ())
                {
                  bool stop = false;
                  for (auto t : stopPoints)
                    {
                      if (t == current.m_type)
                        {
                          stop = true;
                          break;
                        }
                    }
                  if (!stop)
                    if (current.m_child)
                      stack.push (current.m_child);
                }
              else
                {
                  if (current.m_child)
                    stack.push (current.m_child);
                }
            }
        }
    }
  return true;
}
