/*
 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:   ParseLibraryDef.cpp
 * Author: alain
 * 
 * Created on January 27, 2018, 5:05 PM
 */
#include "../Utils/StringUtils.h"
#include "../CommandLine/CommandLineParser.hpp"
#include "../SourceCompile/CompilationUnit.h"
#include "../SourceCompile/PreprocessFile.h"
#include "../SourceCompile/CompileSourceFile.h"
#include "../SourceCompile/Compiler.h"
#include "../SourceCompile/ParseFile.h"
#include "ParseLibraryDef.h"
#include "../Utils/FileUtils.h"
#include "antlr4-runtime.h"
#include "atn/ParserATNSimulator.h"
using namespace antlr4;
using namespace SURELOG;
#include "../parser/SV3_1aLexer.h"
#include "../parser/SV3_1aParser.h"
#include "SVLibShapeListener.h"
#include "AntlrLibParserErrorListener.h"


ParseLibraryDef::ParseLibraryDef (CommandLineParser* commandLineParser, ErrorContainer* errors, SymbolTable* symbolTable,
                                  LibrarySet* librarySet, ConfigSet* configSet) : m_fileId(0),
  m_commandLineParser(commandLineParser), m_errors(errors), m_symbolTable(symbolTable), m_librarySet(librarySet), 
        m_configSet(configSet), m_fileContent(NULL) { 
}

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

ParseLibraryDef::~ParseLibraryDef () { 
}

bool ParseLibraryDef::parseLibrariesDefinition() 
{

  // Get .map files from command line 
  std::vector<SymbolId> libraryMapFiles = m_commandLineParser->getLibraryMapFiles ();
  if (libraryMapFiles.empty ())
    {
      // or scan local dir
      libraryMapFiles = FileUtils::collectFiles ("./", ".map", m_symbolTable);
    }

  // If "work" library is not yet declared from command line, create it
  std::string workN = "work";
  if (m_librarySet->getLibrary (workN) == NULL)
    {
      Library work (workN, m_symbolTable);
      m_librarySet->addLibrary (work);
    }
  
  //Config files are parsed using the library top rule
  std::vector<SymbolId> cfgFiles = m_commandLineParser->getConfigFiles ();
  for (auto file : cfgFiles)
    {
      libraryMapFiles.push_back (file);
    }
  
  for (auto fileId : libraryMapFiles)
    {
      parseLibraryDefinition(fileId);
    }
  
  for (auto file : cfgFiles)
    {
      std::string fullPath = FileUtils::getFullPath (m_symbolTable->getSymbol (file));
      m_librarySet->getLibrary (m_symbolTable->registerSymbol (fullPath)); // Register configuration files in "work" library
    }
  
  unsigned int size = m_commandLineParser->getSourceFiles ().size ();
  for (unsigned int i = 0; i < size; i++)
    {
      SymbolId id = m_commandLineParser->getSourceFiles ()[i];
      std::string fullPath = FileUtils::getFullPath (m_symbolTable->getSymbol (id));
      m_librarySet->getLibrary (m_symbolTable->registerSymbol (fullPath)); // Register files in "work" library
    } 
  
  m_librarySet->checkErrors (m_symbolTable, m_errors);
  
   if (m_commandLineParser->getDebugLibraryDef ())
     {
       std::cout << m_librarySet->report (m_symbolTable) << std::endl;
     }
  return true;
}

bool ParseLibraryDef::parseLibraryDefinition(SymbolId fileId, Library* lib)
{
  m_fileId = fileId;
  std::string fileName = m_symbolTable->getSymbol (fileId);
  std::string relativePath = FileUtils::getPathName (fileName);
  std::ifstream stream;
  stream.open (fileName);
  
  if (!stream.good ())
    {
      Location ppfile (fileId);
      Error err (ErrorDefinition::PA_CANNOT_OPEN_FILE, ppfile);
      m_errors->addError (err);
      return false;
    }
  
  Location ppfile (fileId);
  Error err (ErrorDefinition::PP_PROCESSING_SOURCE_FILE, ppfile);
  m_errors->addError (err);
  m_errors->printMessage (err, m_commandLineParser->muteStdout ());
  
  AntlrLibParserErrorListener* errorListener = new AntlrLibParserErrorListener (this);
  antlr4::ANTLRInputStream* m_inputStream = new ANTLRInputStream (stream);
  SV3_1aLexer* m_lexer = new SV3_1aLexer (m_inputStream);
  m_lexer->removeErrorListeners ();
  m_lexer->addErrorListener (errorListener);
  antlr4::CommonTokenStream* m_tokens = new CommonTokenStream (m_lexer);
  m_tokens->fill ();
  SV3_1aParser* m_parser = new SV3_1aParser (m_tokens);
  m_parser->removeErrorListeners ();
  m_parser->addErrorListener (errorListener);
  antlr4::tree::ParseTree* m_tree = m_parser->top_level_library_rule ();

  SVLibShapeListener* m_listener = new SVLibShapeListener (this, m_tokens, relativePath);
  tree::ParseTreeWalker::DEFAULT.walk (m_listener, m_tree);
  m_fileContent = m_listener->getFileContent();

  if (m_fileContent->getLibrary () == NULL)
    {
      if (lib)
        {
          m_fileContent->setLibrary(lib);
        }
      else 
        {
          std::string fullPath = FileUtils::getFullPath (m_symbolTable->getSymbol (m_fileId));
          m_fileContent->setLibrary (m_librarySet->getLibrary (m_symbolTable->registerSymbol (fullPath)));
        }
    }
  
  if (m_commandLineParser->getDebugAstModel ())
    {
      std::cout << m_fileContent->printObjects ();
    }
  
  //delete m_tree;
  delete m_parser;
  delete m_tokens;
  delete m_lexer;
  delete m_inputStream;
  delete m_listener;
  return parseConfigDefinition();
}

bool
ParseLibraryDef::parseConfigDefinition ()
{
  FileContent* fC = m_fileContent;
  if (!fC)
    return false;

  std::vector<VObjectType> types = {VObjectType::slConfig_declaration};
  std::vector<NodeId> configs = fC->sl_collect_all (0, types);
  for (auto config : configs)
    {
      NodeId ident = fC->Child (config);
      std::string name = fC->getLibrary ()->getName () + "@" + fC->SymName (ident);
      m_symbolTable->registerSymbol (name);
      Config conf (name, fC, config);

      // Design clause
      std::vector<VObjectType> designStmt = {VObjectType::slDesign_statement};
      std::vector<NodeId> designs = fC->sl_collect_all (config, designStmt);
      if (designs.size () == 0)
        {
          // TODO: Error
        }
      else if (designs.size () > 1)
        {
          // TODO: Error
        }
      else
        {
          NodeId design = designs[0];
          NodeId libName = fC->Child (design);
          NodeId topName = fC->Sibling (libName);
          if (topName == 0)
            {
              conf.setDesignLib (fC->getLibrary ()->getName ());
              conf.setDesignTop (fC->SymName (libName));
            }
          else
            {
              conf.setDesignLib (fC->SymName (libName));
              conf.setDesignTop (fC->SymName (topName));
            }
        }

      // Default clause
      std::vector<VObjectType> defaultStmt = {VObjectType::slDefault_clause};
      std::vector<NodeId> defaults = fC->sl_collect_all (config, defaultStmt);
      if (defaults.size () > 0)
        {
          NodeId defaultClause = defaults[0];
          NodeId libList = fC->Sibling (defaultClause);
          if (fC->Type (libList) == VObjectType::slLiblist_clause)
            {
              NodeId lib = fC->Child (libList);
              while (lib)
                {
                  conf.addDefaultLib (fC->SymName (lib));
                  lib = fC->Sibling (lib);
                }
            }
        }

      // Instance and Cell clauses 
      std::vector<VObjectType> instanceStmt = {VObjectType::slInst_clause,
        VObjectType::slCell_clause};
      std::vector<NodeId> instances = fC->sl_collect_all (config, instanceStmt);
      for (auto inst : instances)
        {
          VObjectType type = fC->Type (inst);
          NodeId instName = fC->Child (inst);
          if (type == slInst_clause)
            instName = fC->Child (instName);
          std::string instNameS;
          while (instName)
            {
              if (instNameS == "")
                instNameS = fC->SymName (instName);
              else
                instNameS += "." + fC->SymName (instName);
              instName = fC->Sibling (instName);
            }
          NodeId instClause = fC->Sibling (inst);
          if (fC->Type (instClause) == VObjectType::slLiblist_clause)
            {
              NodeId libList = fC->Child (instClause);
              std::vector<std::string> libs;
              while (libList)
                {
                  libs.push_back(fC->SymName (libList));
                  libList = fC->Sibling(libList);
                }
              
              UseClause usec (UseClause::UseLib, libs, fC, instClause);
              if (type == slInst_clause)
                conf.addInstanceUseClause (instNameS, usec);
              else
                conf.addCellUseClause (instNameS, usec);
            }
          else if (fC->Type (instClause) == VObjectType::slUse_clause)
            {
              NodeId use = fC->Child (instClause);
              std::string useName;
              VObjectType useType = fC->Type (use);
              if (useType == slParameter_value_assignment)
                {
                  UseClause usec (UseClause::UseParam, fC, use);
                  conf.addInstanceUseClause (instNameS, usec);
                }
              else
                {
                  NodeId mem = use;
                  while (use)
                    {
                      if (useName == "")
                        useName = fC->SymName (use);
                      else
                        useName += "." + fC->SymName (use);
                      use = fC->Sibling (use);
                    }
                  useName = StringUtils::replaceAll (useName, ".", "@");
                  UseClause usec (UseClause::UseModule, useName, fC, mem);
                  if (type == slInst_clause)
                    conf.addInstanceUseClause (instNameS, usec);
                  else
                    conf.addCellUseClause (instNameS, usec);
                }
            }
          else if (fC->Type (instClause) == VObjectType::slUse_clause_config)
            {
              NodeId use = fC->Child (instClause);
              std::string useName;
              NodeId mem = use;
              while (use)
                {
                  if (useName == "")
                    useName = fC->SymName (use);
                  else
                    useName += "@" + fC->SymName (use);
                  use = fC->Sibling (use);
                }
              UseClause usec (UseClause::UseConfig, useName, fC, mem);
              if (type == slInst_clause)
                conf.addInstanceUseClause (instNameS, usec);
              else
                conf.addCellUseClause (instNameS, usec);

            }
        }


      m_configSet->addConfig (conf);
    }

  return true;
}

