/*
 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:   CompileSourceFile.cpp
 * Author: alain
 *
 * Created on February 20, 2017, 9:54 PM
 */
#include "CommandLine/CommandLineParser.h"
#include "ErrorReporting/ErrorContainer.h"
#include "SourceCompile/SymbolTable.h"
#include "SourceCompile/CompilationUnit.h"
#include "SourceCompile/PreprocessFile.h"
#include "SourceCompile/CompilationUnit.h"

#include "antlr4-runtime.h"
using namespace antlr4;
#include "parser/SV3_1aLexer.h"
#include "parser/SV3_1aParser.h"

#include "SourceCompile/AntlrParserHandler.h"

#include "SourceCompile/CompileSourceFile.h"
#include "SourceCompile/Compiler.h"
#include "Utils/StringUtils.h"
#include "Utils/FileUtils.h"
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
using namespace std;
#include "SourceCompile/PreprocessFile.h"
#include "SourceCompile/ParseFile.h"
#include "API/PythonAPI.h"
#include "SourceCompile/PythonListen.h"
#include "Package/Precompiled.h"

using namespace SURELOG;

CompileSourceFile::CompileSourceFile(SymbolId fileId, CommandLineParser* clp,
                                     ErrorContainer* errors, Compiler* compiler,
                                     SymbolTable* symbols,
                                     CompilationUnit* compilationUnit,
                                     Library* library)
    : m_fileId(fileId),
      m_commandLineParser(clp),
      m_errors(errors),
      m_compiler(compiler),
      m_pp(NULL),
      m_symbolTable(symbols),
      m_parser(NULL),
      m_compilationUnit(compilationUnit),
      m_action(Preprocess),
      m_ppResultFileId(0),
      m_interpState(NULL),
      m_pythonListener(NULL),
      m_fileAnalyzer(NULL),
      m_library(library) {}

CompileSourceFile::CompileSourceFile(CompileSourceFile* parent,
                                     SymbolId ppResultFileId,
                                     unsigned int lineOffset)
    : m_fileId(parent->m_fileId),
      m_commandLineParser(parent->m_commandLineParser),
      m_errors(parent->m_errors),
      m_compiler(parent->m_compiler),
      m_pp(parent->m_pp),
      m_symbolTable(NULL),
      m_parser(NULL),
      m_compilationUnit(parent->m_compilationUnit),
      m_action(Parse),
      m_ppResultFileId(ppResultFileId),
      m_interpState(parent->m_interpState),
      m_pythonListener(NULL),
      m_fileAnalyzer(parent->m_fileAnalyzer),
      m_library(parent->m_library) {
  m_parser =
      new ParseFile(this, parent->m_parser, m_ppResultFileId, lineOffset);
}

bool CompileSourceFile::compile(Action action) {
  m_action = action;
  std::string fileName = m_symbolTable->getSymbol(m_fileId);
  if (m_commandLineParser->verbose()) {
    SymbolId fileId = m_fileId;
    if (strstr(fileName.c_str(), "builtin.sv")) {
      fileId = m_symbolTable->registerSymbol("builtin.sv");
    }
    Location loc(fileId);
    ErrorDefinition::ErrorType type =
        ErrorDefinition::PP_PROCESSING_SOURCE_FILE;
    switch (m_action) {
      case Preprocess:
      case PostPreprocess:
        type = ErrorDefinition::PP_PROCESSING_SOURCE_FILE;
        break;
      case Parse:
        type = ErrorDefinition::PA_PROCESSING_SOURCE_FILE;
        break;
      case PythonAPI:
        type = ErrorDefinition::PY_PROCESSING_SOURCE_FILE;
        break;
    }
    if (action != PostPreprocess) {
      Error err(type, loc);
      m_errors->printMessage(m_errors->addError(err, true));
    }
  }

  switch (m_action) {
    case Preprocess:
      return preprocess_();
    case PostPreprocess:
      return postPreprocess_();
    case Parse:
      return parse_();
    case PythonAPI: {
      if (!strstr(fileName.c_str(), "builtin.sv")) {
        return pythonAPI_();
      }
    }
  }
  return true;
}

CompileSourceFile::CompileSourceFile(const CompileSourceFile& orig) {}

CompileSourceFile::~CompileSourceFile() {
  std::vector<PreprocessFile*>::iterator itr;
  for (itr = m_ppIncludeVec.begin(); itr != m_ppIncludeVec.end(); itr++) {
    delete *itr;
  }

  if (m_parser) delete m_parser;

  if (m_pythonListener) delete m_pythonListener;

  std::map<SymbolId, PreprocessFile::AntlrParserHandler*>::iterator itr2;
  for (itr2 = m_antlrPpMap.begin(); itr2 != m_antlrPpMap.end(); itr2++) {
    delete (*itr2).second;
  }
}

unsigned int CompileSourceFile::getJobSize(Action action) {
  switch (action) {
    case Preprocess:
    case PostPreprocess: {
      std::string fileName = getSymbolTable()->getSymbol(m_fileId);
      return FileUtils::fileSize(fileName);
    }
    case Parse: {
      std::string fileName = getSymbolTable()->getSymbol(m_ppResultFileId);
      return FileUtils::fileSize(fileName);
    }
    case PythonAPI: {
      std::string fileName = getSymbolTable()->getSymbol(m_ppResultFileId);
      return FileUtils::fileSize(fileName);
    }
  };
  return 0;
}

bool CompileSourceFile::pythonAPI_() {
  if (getCommandLineParser()->pythonListener()) {
    m_pythonListener = new PythonListen(m_parser, this);
    if (!m_pythonListener->listen()) {
      return false;
    }
    bool fatalErrors = m_errors->hasFatalErrors();
    if (fatalErrors) {
      return false;
    }
  }
  if (getCommandLineParser()->pythonEvalScriptPerFile()) {
    PythonAPI::evalScriptPerFile(
        getCommandLineParser()->getSymbolTable()->getSymbol(
            getCommandLineParser()->pythonEvalScriptPerFileId()),
        m_errors, m_parser->getFileContent(), m_interpState);
  }
  return true;
}

bool CompileSourceFile::initParser() {
  if (m_parser == NULL)
    m_parser = new ParseFile(m_fileId, this, m_compilationUnit, m_library,
                             m_ppResultFileId,
                             getCommandLineParser()->pythonListener());
  return true;
}

bool CompileSourceFile::parse_() {
  initParser();
  if (!m_parser->parse()) {
    return false;
  }
  bool fatalErrors = m_errors->hasFatalErrors();
  if (fatalErrors) {
    return false;
  }
  return true;
}

bool CompileSourceFile::preprocess_() {
  Precompiled* prec = Precompiled::getSingleton();
  std::string root = getSymbolTable()->getSymbol(m_fileId);
  root = StringUtils::getRootFileName(root);

  PreprocessFile::SpecialInstructions instructions(
      PreprocessFile::SpecialInstructions::DontMute,
      PreprocessFile::SpecialInstructions::DontMark,
      m_commandLineParser->filterFileLine()
          ? PreprocessFile::SpecialInstructions::Filter
          : PreprocessFile::SpecialInstructions::DontFilter,
      PreprocessFile::SpecialInstructions::CheckLoop,
      PreprocessFile::SpecialInstructions::ComplainUndefinedMacro);
  m_pp = new PreprocessFile(m_fileId, this, instructions, m_compilationUnit,
                            m_library);
  registerPP(m_pp);

  if (!m_pp->preprocess()) {
    return false;
  }
  bool fatalErrors = m_errors->hasFatalErrors();
  if (fatalErrors) {
    return false;
  }

  if (m_commandLineParser->getDebugIncludeFileInfo())
    std::cout << m_pp->reportIncludeInfo();

  if ((!m_commandLineParser->createCache()) && prec->isFilePrecompiled(root))
    return true;

  m_pp->saveCache();
  return true;
}

bool CompileSourceFile::postPreprocess_() {
  SymbolTable* symbolTable = getCompiler()->getSymbolTable();
  if (m_commandLineParser->parseOnly()) {
    m_ppResultFileId = m_symbolTable->registerSymbol(symbolTable->getSymbol(m_fileId));
    return true;
  }
  std::string m_pp_result = m_pp->getPreProcessedFileContent();
  if (m_commandLineParser->writePpOutput() ||
      (m_commandLineParser->writePpOutputFileId() != 0)) {
    const std::string& directory =
        symbolTable->getSymbol(m_commandLineParser->getFullCompileDir());
    std::string fileName = symbolTable->getSymbol(m_fileId);
    std::string fullPath = FileUtils::getFullPath(fileName);
    fileName = StringUtils::eliminateRelativePath(fileName);
    const std::string& writePpOutputFileName =
        symbolTable->getSymbol(m_commandLineParser->writePpOutputFileId());
    std::string libName = m_library->getName() + "/";
    string ppFileName = m_commandLineParser->writePpOutput()
                            ? directory + libName + fileName
                            : writePpOutputFileName;
    std::string dirPpFile = ppFileName;
    StringUtils::rtrim(dirPpFile, '/');
    SymbolId ppOutId = symbolTable->registerSymbol(ppFileName);
    m_ppResultFileId = m_symbolTable->registerSymbol(ppFileName);
    SymbolId ppDirId = symbolTable->registerSymbol(dirPpFile);

    if (FileUtils::mkDir(dirPpFile.c_str()) != 0) {
      Location loc(ppDirId);
      Error err(ErrorDefinition::PP_CANNOT_CREATE_DIRECTORY, loc);
      m_errors->addError(err);
      return false;
    }
    if ((!m_pp->usingCachedVersion()) || (!FileUtils::fileExists(ppFileName))) {
      ofstream ofs;
      ofs.open(ppFileName);
      if (ofs.good()) {
        ofs << m_pp_result;
        ofs.close();
      } else {
        Location loc(ppOutId);
        Error err(ErrorDefinition::PP_OPEN_FILE_FOR_WRITE, loc);
        m_errors->addError(err);
        return false;
      }
    }
  }
  return true;
}

void CompileSourceFile::registerAntlrPpHandlerForId(
    SymbolId id, PreprocessFile::AntlrParserHandler* pp) {
  std::map<SymbolId, PreprocessFile::AntlrParserHandler*>::iterator itr =
      m_antlrPpMap.find(id);
  if (itr != m_antlrPpMap.end()) {
    delete (*itr).second;
    m_antlrPpMap.erase(itr);
    m_antlrPpMap.insert(std::make_pair(id, pp));
    return;
  }
  m_antlrPpMap.insert(std::make_pair(id, pp));
}

PreprocessFile::AntlrParserHandler* CompileSourceFile::getAntlrPpHandlerForId(
    SymbolId id) {
  std::map<SymbolId, PreprocessFile::AntlrParserHandler*>::iterator itr =
      m_antlrPpMap.find(id);
  if (itr != m_antlrPpMap.end()) {
    PreprocessFile::AntlrParserHandler* ptr = (*itr).second;
    return ptr;
  }
  return NULL;
}

void CompileSourceFile::setSymbolTable(SymbolTable* symbols) {
  m_symbolTable = symbols;
}

void CompileSourceFile::setPythonInterp(PyThreadState* interpState) {
  m_interpState = interpState;
  m_errors->setPythonInterp(interpState);
}

void CompileSourceFile::shutdownPythonInterp() {
  m_errors->setPythonInterp(NULL);
  PythonAPI::shutdown(m_interpState);
  m_interpState = NULL;
}
