/*
 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:   CompileProgram.cpp
 * Author: alain
 *
 * Created on June 6, 2018, 10:43 PM
 */
#include "SourceCompile/VObjectTypes.h"
#include "Design/VObject.h"
#include "Library/Library.h"
#include "Design/Signal.h"
#include "Design/FileContent.h"
#include "Design/ClockingBlock.h"
#include "Testbench/ClassDefinition.h"
#include "SourceCompile/SymbolTable.h"
#include "ErrorReporting/Error.h"
#include "ErrorReporting/Location.h"
#include "ErrorReporting/Error.h"
#include "CommandLine/CommandLineParser.h"
#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 "DesignCompile/CompileHelper.h"
#include "DesignCompile/CompileDesign.h"
#include "DesignCompile/CompileProgram.h"

using namespace SURELOG;

CompileProgram::~CompileProgram() {}

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

bool CompileProgram::compile() {
  FileContent* fC = m_program->m_fileContents[0];
  NodeId nodeId = m_program->m_nodeIds[0];

  Location loc(m_symbols->registerSymbol(fC->getFileName(nodeId)),
               fC->Line(nodeId), 0,
               m_symbols->registerSymbol(m_program->getName()));

  Error err1(ErrorDefinition::COMP_COMPILE_PROGRAM, loc);
  ErrorContainer* errors = new ErrorContainer(m_symbols);
  errors->regiterCmdLine(
      m_compileDesign->getCompiler()->getCommandLineParser());
  errors->addError(err1);
  errors->printMessage(
      err1,
      m_compileDesign->getCompiler()->getCommandLineParser()->muteStdout());
  delete errors;

  Error err2(ErrorDefinition::COMP_PROGRAM_OBSOLETE_USAGE, loc);
  m_errors->addError(err2);

  std::vector<VObjectType> stopPoints = {
      VObjectType::slClass_declaration,
  };

  if (fC->getSize() == 0) return true;
  VObject current = fC->Object(nodeId);
  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_program, 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_program, m_design, fC, id);
        break;
      }
      case VObjectType::slClass_declaration: {
        NodeId nameId = fC->Child(id);
        std::string name = fC->SymName(nameId);
        FileCNodeId fnid(fC, nameId);
        m_program->addObject(type, fnid);

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

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

        m_program->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_program, fC, id);
            break;
          }
          default:
            break;
        }
        break;
      }
      case VObjectType::slNet_declaration: {
        /*
          n<C> u<230> t<StringConst> p<234> s<233> l<58>
          n<c> u<231> t<StringConst> p<232> l<58>
          n<> u<232> t<Net_decl_assignment> p<233> c<231> l<58>
          n<> u<233> t<List_of_net_decl_assignments> p<234> c<232> l<58>
          n<> u<234> t<Net_declaration> p<235> c<230> l<58>
         */
        NodeId netTypeId = fC->Child(id);

        std::string dataTypeName = fC->SymName(netTypeId);
        DesignComponent* def = NULL;
        std::pair<FileCNodeId, DesignComponent*>* datatype =
            m_program->getNamedObject(dataTypeName);
        if (datatype) {
          def = datatype->second;
        }
        if (def == NULL) {
          std::string libName = m_program->m_library->getName();
          def = m_design->getClassDefinition(libName + "@" + dataTypeName);
        }
        if (def == NULL) {
          // TODO: import class in design
          Location loc(m_symbols->registerSymbol(fC->getFileName(id)),
                       fC->Line(id), 0,
                       m_symbols->registerSymbol(dataTypeName));
          Error err(ErrorDefinition::COMP_UNDEFINED_CLASS, loc);
          m_errors->addError(err);
        }
        NodeId list_of_net_decl_assignments = fC->Sibling(netTypeId);
        NodeId net_decl_assignment = fC->Child(list_of_net_decl_assignments);
        while (net_decl_assignment) {
          NodeId netId = fC->Child(net_decl_assignment);
          FileCNodeId fnid(fC, netId);
          std::string varname = fC->SymName(netId);
          m_program->addNamedObject(varname, fnid, def);
          net_decl_assignment = fC->Sibling(net_decl_assignment);
        }
        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;
}
