/*
 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:   ParseFile.cpp
 * Author: alain
 *
 * Created on February 24, 2017, 10:03 PM
 */

#include "SourceCompile/SymbolTable.h"
#include "CommandLine/CommandLineParser.h"
#include "ErrorReporting/ErrorContainer.h"
#include "SourceCompile/CompilationUnit.h"
#include "SourceCompile/PreprocessFile.h"
#include "SourceCompile/CompileSourceFile.h"
#include "SourceCompile/Compiler.h"
#include "SourceCompile/ParseFile.h"
#include "SourceCompile/AntlrParserHandler.h"
#include <cstdlib>
#include <iostream>
#include "antlr4-runtime.h"
#include "atn/ParserATNSimulator.h"

using namespace std;
using namespace antlr4;
using namespace SURELOG;

#include "parser/SV3_1aLexer.h"
#include "parser/SV3_1aParser.h"
#include "parser/SV3_1aParserBaseListener.h"
#include "SourceCompile/SV3_1aTreeShapeListener.h"
#include "API/SV3_1aPythonListener.h"
using namespace antlr4;
#include "Utils/ParseUtils.h"
#include "Utils/FileUtils.h"
#include "Cache/ParseCache.h"
#include "SourceCompile/AntlrParserErrorListener.h"
#include "Package/Precompiled.h"
#include "Utils/StringUtils.h"
#include "Utils/Timer.h"
ParseFile::ParseFile(SymbolId fileId, SymbolTable* symbolTable,
                     ErrorContainer* errors)
    : m_fileId(fileId),
      m_ppFileId(0),
      m_compileSourceFile(NULL),
      m_compilationUnit(NULL),
      m_library(NULL),
      m_antlrParserHandler(NULL),
      m_listener(NULL),
      m_usingCachedVersion(false),
      m_keepParserHandler(false),
      m_fileContent(NULL),
      debug_AstModel(false),
      m_parent(NULL),
      m_offsetLine(0),
      m_symbolTable(symbolTable),
      m_errors(errors) {
  debug_AstModel = true;
}

ParseFile::ParseFile(SymbolId fileId, CompileSourceFile* csf,
                     CompilationUnit* compilationUnit, Library* library,
                     SymbolId ppFileId, bool keepParserHandler)
    : m_fileId(fileId),
      m_ppFileId(ppFileId),
      m_compileSourceFile(csf),
      m_compilationUnit(compilationUnit),
      m_library(library),
      m_antlrParserHandler(NULL),
      m_listener(NULL),
      m_usingCachedVersion(false),
      m_keepParserHandler(keepParserHandler),
      m_fileContent(NULL),
      debug_AstModel(false),
      m_parent(NULL),
      m_offsetLine(0),
      m_symbolTable(NULL),
      m_errors(NULL) {
  debug_AstModel =
      m_compileSourceFile->getCommandLineParser()->getDebugAstModel();
}

ParseFile::ParseFile(CompileSourceFile* compileSourceFile, ParseFile* parent,
                     SymbolId chunkFileId, unsigned int offsetLine)
    : m_fileId(parent->m_fileId),
      m_ppFileId(chunkFileId),
      m_compileSourceFile(compileSourceFile),
      m_compilationUnit(parent->m_compilationUnit),
      m_library(parent->m_library),
      m_antlrParserHandler(NULL),
      m_listener(NULL),
      m_usingCachedVersion(false),
      m_keepParserHandler(parent->m_keepParserHandler),
      m_fileContent(parent->m_fileContent),
      debug_AstModel(false),
      m_parent(parent),
      m_offsetLine(offsetLine),
      m_symbolTable(NULL),
      m_errors(NULL) {
  parent->m_children.push_back(this);
}

ParseFile::~ParseFile() {
  if (!m_keepParserHandler) delete m_antlrParserHandler;
}

SymbolTable* ParseFile::getSymbolTable() {
  return m_symbolTable ? m_symbolTable : m_compileSourceFile->getSymbolTable();
}

ErrorContainer* ParseFile::getErrorContainer() {
  return m_errors ? m_errors : m_compileSourceFile->getErrorContainer();
}

SymbolId ParseFile::registerSymbol(const std::string symbol) {
  return getCompileSourceFile()->getSymbolTable()->registerSymbol(symbol);
}

SymbolId ParseFile::getId(const std::string symbol) {
  return getCompileSourceFile()->getSymbolTable()->getId(symbol);
}

const std::string ParseFile::getSymbol(SymbolId id) {
  return getCompileSourceFile()->getSymbolTable()->getSymbol(id);
}

const std::string ParseFile::getFileName(unsigned int line) {
  return getSymbol(getFileId(line));
}

void ParseFile::addError(Error& error) {
  getCompileSourceFile()->getErrorContainer()->addError(error);
}

SymbolId ParseFile::getFileId(unsigned int line) {
  if (!getCompileSourceFile()) return m_fileId;
  PreprocessFile* pp = getCompileSourceFile()->getPreprocessor();
  auto& infos = pp->getIncludeFileInfo();
  if (line == 0) return m_fileId;
  if (infos.size()) {
    bool inRange = false;
    unsigned int indexOpeningRange = 0;
    for (unsigned int i = infos.size() - 1; i >= 0; i--) {
      // if (!inRange)
      //  {
      if ((line >= infos[i].m_originalLine) && (infos[i].m_type == 2)) {
        SymbolId fileId = getSymbolTable()->registerSymbol(
            pp->getSymbol(infos[i].m_sectionFile));
        return (fileId);
      }
      // }
      if (infos[i].m_type == 2) {
        if (!inRange) {
          inRange = true;
          indexOpeningRange = infos[i].m_indexOpening;
        }
      } else {
        if (inRange) {
          if (i == indexOpeningRange) inRange = false;
        }
      }
      if ((line >= infos[i].m_originalLine) && (infos[i].m_type == 1) &&
          (line < infos[infos[i].m_indexClosing].m_originalLine)) {
        SymbolId fileId = getSymbolTable()->registerSymbol(
            pp->getSymbol(infos[i].m_sectionFile));
        return (fileId);
      }
      if (i == 0) break;
    }
    return m_fileId;
  } else {
    return m_fileId;
  }
}

unsigned int ParseFile::getLineNb(unsigned int line) {
  if (!getCompileSourceFile()) return line;
  PreprocessFile* pp = getCompileSourceFile()->getPreprocessor();
  auto& infos = pp->getIncludeFileInfo();
  if (line == 0) return 1;

  if (infos.size()) {
    bool inRange = false;
    unsigned int indexOpeningRange = 0;
    for (unsigned int i = infos.size() - 1; i >= 0; i--) {
      // if (!inRange)
      //  {
      if ((line >= infos[i].m_originalLine) && (infos[i].m_type == 2)) {
        return (infos[i].m_sectionStartLine + (line - infos[i].m_originalLine));
      }
      //   }
      if (infos[i].m_type == 2) {
        if (!inRange) {
          inRange = true;
          indexOpeningRange = infos[i].m_indexOpening;
        }
      } else {
        if (inRange) {
          if (i == indexOpeningRange) inRange = false;
        }
      }
      if ((line >= infos[i].m_originalLine) && (infos[i].m_type == 1) &&
          (line < infos[infos[i].m_indexClosing].m_originalLine)) {
        return (infos[i].m_sectionStartLine + (line - infos[i].m_originalLine));
      }

      if (i == 0) break;
    }
    return line;
  } else {
    return line;
  }
}

bool ParseFile::parseOneFile_(std::string fileName, unsigned int lineOffset) {
  Timer tmr;
  AntlrParserHandler* antlrParserHandler = new AntlrParserHandler();
  m_antlrParserHandler = antlrParserHandler;
  std::ifstream stream;
  stream.open(fileName);
  if (!stream.good()) {
    SymbolId fileId = registerSymbol(fileName);
    Location ppfile(fileId);
    Error err(ErrorDefinition::PA_CANNOT_OPEN_FILE, ppfile);
    addError(err);
    return false;
  }

  antlrParserHandler->m_inputStream = new ANTLRInputStream(stream);
  antlrParserHandler->m_errorListener =
      new AntlrParserErrorListener(this, false, lineOffset, fileName);
  antlrParserHandler->m_lexer =
      new SV3_1aLexer(antlrParserHandler->m_inputStream);
  antlrParserHandler->m_lexer->removeErrorListeners();
  antlrParserHandler->m_lexer->addErrorListener(
      antlrParserHandler->m_errorListener);
  antlrParserHandler->m_tokens =
      new CommonTokenStream(antlrParserHandler->m_lexer);
  antlrParserHandler->m_tokens->fill();

  if (getCompileSourceFile()->getCommandLineParser()->profile()) {
    // m_profileInfo += "Tokenizer: " + std::to_string (tmr.elapsed_rounded ())
    // + " " + fileName + "\n";
    tmr.reset();
  }

  antlrParserHandler->m_parser = new SV3_1aParser(antlrParserHandler->m_tokens);

  m_antlrParserHandler->m_parser->getInterpreter<atn::ParserATNSimulator>()
      ->setPredictionMode(atn::PredictionMode::SLL);
  m_antlrParserHandler->m_parser->setErrorHandler(
      std::make_shared<BailErrorStrategy>());
  m_antlrParserHandler->m_parser->removeErrorListeners();

  try {
    m_antlrParserHandler->m_tree =
        m_antlrParserHandler->m_parser->top_level_rule();

    if (getCompileSourceFile()->getCommandLineParser()->profile()) {
      m_profileInfo +=
          "SLL Parsing: " + StringUtils::to_string(tmr.elapsed_rounded()) +
          " " + fileName + "\n";
      tmr.reset();
    }
  } catch (ParseCancellationException& pex) {
    m_antlrParserHandler->m_tokens->reset();
    m_antlrParserHandler->m_parser->reset();

    m_antlrParserHandler->m_parser->setErrorHandler(
        std::make_shared<DefaultErrorStrategy>());
    antlrParserHandler->m_parser->removeErrorListeners();
    antlrParserHandler->m_parser->addErrorListener(
        antlrParserHandler->m_errorListener);
    antlrParserHandler->m_parser->getInterpreter<atn::ParserATNSimulator>()
        ->setPredictionMode(atn::PredictionMode::LL);
    antlrParserHandler->m_tree = antlrParserHandler->m_parser->top_level_rule();

    if (getCompileSourceFile()->getCommandLineParser()->profile()) {
      m_profileInfo +=
          "LL  Parsing: " + StringUtils::to_string(tmr.elapsed_rounded()) +
          " " + fileName + "\n";
      tmr.reset();
    }
  }
  stream.close();
  return true;
}

std::string ParseFile::getProfileInfo() {
  std::string profile;
  profile = m_profileInfo;
  for (unsigned int i = 0; i < m_children.size(); i++)
    profile += m_children[i]->m_profileInfo;

  return profile;
}

bool ParseFile::parse() {
  Precompiled* prec = Precompiled::getSingleton();
  std::string root = this->getPpFileName();
  root = StringUtils::getRootFileName(root);
  bool precompiled = false;
  if (prec->isFilePrecompiled(root)) precompiled = true;

  if (m_children.size() == 0) {
    ParseCache cache(this);

    if (cache.restore()) {
      m_usingCachedVersion = true;
      if (debug_AstModel && !precompiled)
        std::cout << m_fileContent->printObjects();
      return true;
    }
 } else {
    bool ok = true;
    for (unsigned int i = 0; i < m_children.size(); i++) {
      ParseCache cache(m_children[i]);

      if (cache.restore()) {
        m_children[i]->m_fileContent->setParent(m_fileContent);
        m_usingCachedVersion = true;
        if (debug_AstModel && !precompiled)
          std::cout << m_children[i]->m_fileContent->printObjects();
      } else {
        ok = false;
      }
    }
    if (ok) {
      return true;
    }
  }

  // This is not a parent Parser object
  if (m_children.size() == 0) {
    // std::cout << std::endl << "Parsing " << getSymbol(m_ppFileId) << " Line:
    // " << m_offsetLine << std::endl << std::flush;

    parseOneFile_(getSymbol(m_ppFileId), m_offsetLine);

    // m_listener = new SV3_1aTreeShapeListener (this,
    // m_antlrParserHandler->m_tokens, m_offsetLine);
    // tree::ParseTreeWalker::DEFAULT.walk (m_listener,
    // m_antlrParserHandler->m_tree); std::cout << std::endl << "End Parsing " <<
    // getSymbol(m_ppFileId) << " Line: " << m_offsetLine << std::endl <<
    // std::flush;
  }

  // This is either a parent Parser object of this Parser object has no parent
  if ((m_children.size() != 0) || (m_parent == NULL)) {
    if ((m_parent == NULL) && (m_children.size() == 0)) {
      Timer tmr;

      m_listener = new SV3_1aTreeShapeListener(
          this, m_antlrParserHandler->m_tokens, m_offsetLine);
      tree::ParseTreeWalker::DEFAULT.walk(m_listener,
                                          m_antlrParserHandler->m_tree);

      if (debug_AstModel && !precompiled)
        std::cout << m_fileContent->printObjects();

      if (getCompileSourceFile()->getCommandLineParser()->profile()) {
        // m_profileInfo += "AST Walking: " + std::to_string
        // (tmr.elapsed_rounded ()) + "\n";
        tmr.reset();
      }

      ParseCache cache(this);
      if (!cache.save()) {
        return false;
      }
      
      if (getCompileSourceFile()->getCommandLineParser()->profile()) {
        m_profileInfo += "Cache saving: " + std::to_string(tmr.elapsed_rounded ()) + "\n";
        std::cout << "Cache saving: " + std::to_string(tmr.elapsed_rounded ()) + "\n" << std::flush;
        tmr.reset();
      }
    }

    if (m_children.size() != 0) {
      for (unsigned int i = 0; i < m_children.size(); i++) {
        if (m_children[i]->m_antlrParserHandler) {
          // Only visit the chunks that got re-parsed
          // TODO: Incrementally regenerate the FileContent
          m_children[i]->m_fileContent->setParent(m_fileContent);
          m_children[i]->m_listener = new SV3_1aTreeShapeListener(
              m_children[i], m_children[i]->m_antlrParserHandler->m_tokens,
              m_children[i]->m_offsetLine);

          Timer tmr;
          tree::ParseTreeWalker::DEFAULT.walk(
              m_children[i]->m_listener,
              m_children[i]->m_antlrParserHandler->m_tree);

          if (getCompileSourceFile()->getCommandLineParser()->profile()) {
            // m_profileInfo += "For file " + getSymbol
            // (m_children[i]->m_ppFileId) + ", AST Walking took" +
            // std::to_string (tmr.elapsed_rounded ()) + "\n";
            tmr.reset();
          }

          if (debug_AstModel && !precompiled)
            std::cout << m_children[i]->m_fileContent->printObjects();

          ParseCache cache(m_children[i]);
          if (!cache.save()) {
            return false;
          }
        }
      }
    }
  }
  return true;
}
