/*
 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 "SymbolTable.h"
#include "../CommandLine/CommandLineParser.hpp"
#include "../ErrorReporting/ErrorContainer.h"
#include "CompilationUnit.h"
#include "PreprocessFile.h"
#include "CompileSourceFile.h"
#include "Compiler.h"
#include "ParseFile.h"
#include "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 "SV3_1aTreeShapeListener.h"
#include "../API/SV3_1aPythonListener.h"
using namespace antlr4;
#include "../Utils/ParseUtils.h"
#include "../Utils/FileUtils.h"
#include "../Cache/ParseCache.h"
#include "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 += "SSL 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 (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;
}



