/*
 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:   SLAPI.cpp
 * Author: alain
 *
 * Created on May 13, 2017, 4:42 PM
 */

#include <string>
#include <vector>

#include "ErrorReporting/Waiver.h"
#include "ErrorReporting/ErrorDefinition.h"
#include "SourceCompile/SymbolTable.h"
#include "ErrorReporting/ErrorContainer.h"
#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 "SourceCompile/PythonListen.h"
#include "Design/FileContent.h"
#include "Testbench/ClassDefinition.h"
#include <cstdlib>
#include <iostream>
#include "antlr4-runtime.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 "API/SV3_1aPythonListener.h"
#include "Utils/ParseUtils.h"
#include "Utils/FileUtils.h"
#include "API/PythonAPI.h"

#include "API/SLAPI.h"

void SURELOG::SLsetWaiver(const char* messageId, const char* fileName,
                          unsigned int line, const char* objectName) {
  if (fileName == 0 && line == 0 && objectName == 0) {
    Waiver::setWaiver(messageId, "", 0, "");
  } else if (line == 0 && objectName == 0) {
    Waiver::setWaiver(messageId, "", 0, fileName);
  } else if (objectName == 0) {
    Waiver::setWaiver(messageId, fileName, line, "");
  } else {
    Waiver::setWaiver(messageId, fileName, line, objectName);
  }
}

void SURELOG::SLregisterNewErrorType(const char* messageId, const char* text,
                                     const char* secondLine) {
  //[WARNI:PP0103]
  std::string errorId = messageId;
  errorId = StringUtils::rtrim(errorId, ']');
  errorId = StringUtils::ltrim(errorId, '[');
  ErrorDefinition::ErrorType type = ErrorDefinition::getErrorType(messageId);
  ErrorDefinition::ErrorSeverity severity =
      ErrorDefinition::getErrorSeverity(errorId.substr(0, 5));
  ErrorDefinition::ErrorCategory category =
      ErrorDefinition::getCategory(errorId.substr(6, 2));
  ErrorDefinition::rec(type, severity, category, text, secondLine);
}

void SURELOG::SLoverrideSeverity(const char* messageId, const char* severity) {
  ErrorDefinition::setSeverity(ErrorDefinition::getErrorType(messageId),
                               ErrorDefinition::getErrorSeverity(severity));
}

void SURELOG::SLaddError(ErrorContainer* errors, const char* messageId,
                         const char* fileName, unsigned int line,
                         unsigned int col, const char* objectName) {
  if (errors == NULL) return;
  SymbolTable* symbolTable = errors->getSymbolTable();
  SymbolId fileId = 0;
  if (fileName && (strcmp(fileName, "")))
    fileId = symbolTable->registerSymbol(fileName);
  SymbolId objectId = 0;
  if (objectName && (strcmp(objectName, "")))
    objectId = symbolTable->registerSymbol(objectName);
  Location loc(fileId, line, col, objectId);

  ErrorDefinition::ErrorType type = ErrorDefinition::getErrorType(messageId);
  Error err(type, loc);
  errors->addError(err, false, false);
}

void SURELOG::SLaddMLError(ErrorContainer* errors, const char* messageId,
                           const char* fileName1, unsigned int line1,
                           unsigned int col1, const char* objectName1,
                           const char* fileName2, unsigned int line2,
                           unsigned int col2, const char* objectName2) {
  if (errors == NULL) return;
  SymbolTable* symbolTable = errors->getSymbolTable();
  SymbolId fileId1 = 0;
  if (fileName1 && (strcmp(fileName1, "")))
    fileId1 = symbolTable->registerSymbol(fileName1);
  SymbolId objectId1 = 0;
  if (objectName1 && (strcmp(objectName1, "")))
    objectId1 = symbolTable->registerSymbol(objectName1);
  Location loc1(fileId1, line1, col1, objectId1);

  SymbolId fileId2 = 0;
  if (fileName2 && (strcmp(fileName2, "")))
    fileId2 = symbolTable->registerSymbol(fileName2);
  SymbolId objectId2 = 0;
  if (objectName2 && (strcmp(objectName2, "")))
    objectId2 = symbolTable->registerSymbol(objectName2);
  Location loc2(fileId2, line2, col2, objectId2);

  ErrorDefinition::ErrorType type = ErrorDefinition::getErrorType(messageId);
  Error err(type, loc2, loc2);
  errors->addError(err, false, false);
}

void SURELOG::SLaddErrorContext(SV3_1aPythonListener* prog,
                                ParserRuleContext* context,
                                const char* messageId, const char* objectName,
                                bool printColumn) {
  SV3_1aPythonListener* listener = (SV3_1aPythonListener*)prog;
  ParserRuleContext* ctx = (ParserRuleContext*)context;
  ErrorContainer* errors =
      listener->getPythonListen()->getCompileSourceFile()->getErrorContainer();
  std::pair<int, int> lineCol =
      ParseUtils::getLineColumn(listener->getTokenStream(), ctx);
  ErrorDefinition::ErrorType type = ErrorDefinition::getErrorType(messageId);

  Location loc(
      listener->getPythonListen()->getParseFile()->getFileId(lineCol.first),
      listener->getPythonListen()->getParseFile()->getLineNb(lineCol.first),
      printColumn ? lineCol.second : 0,
      listener->getPythonListen()
          ->getCompileSourceFile()
          ->getSymbolTable()
          ->registerSymbol(objectName));
  Error err(type, loc);
  errors->addError(err, false, false);
}

void SURELOG::SLaddMLErrorContext(SV3_1aPythonListener* prog,
                                  ParserRuleContext* context1,
                                  ParserRuleContext* context2,
                                  const char* messageId,
                                  const char* objectName1,
                                  const char* objectName2, bool printColumn) {
  SV3_1aPythonListener* listener = (SV3_1aPythonListener*)prog;
  ParserRuleContext* ctx1 = (ParserRuleContext*)context1;
  ParserRuleContext* ctx2 = (ParserRuleContext*)context2;
  ErrorContainer* errors =
      listener->getPythonListen()->getCompileSourceFile()->getErrorContainer();
  std::pair<int, int> lineCol1 =
      ParseUtils::getLineColumn(listener->getTokenStream(), ctx1);
  std::pair<int, int> lineCol2 =
      ParseUtils::getLineColumn(listener->getTokenStream(), ctx2);
  ErrorDefinition::ErrorType type = ErrorDefinition::getErrorType(messageId);

  Location loc1(
      listener->getPythonListen()->getParseFile()->getFileId(lineCol1.first),
      listener->getPythonListen()->getParseFile()->getLineNb(lineCol1.first),
      printColumn ? lineCol1.second : 0,
      listener->getPythonListen()
          ->getCompileSourceFile()
          ->getSymbolTable()
          ->registerSymbol(objectName1));

  Location loc2(
      listener->getPythonListen()->getParseFile()->getFileId(lineCol2.first),
      listener->getPythonListen()->getParseFile()->getLineNb(lineCol2.first),
      printColumn ? lineCol2.second : 0,
      listener->getPythonListen()
          ->getCompileSourceFile()
          ->getSymbolTable()
          ->registerSymbol(objectName2));
  Error err(type, loc1, loc2);
  errors->addError(err, false, false);
}

std::string SURELOG::SLgetFile(SV3_1aPythonListener* prog,
                               ParserRuleContext* context) {
  SV3_1aPythonListener* listener = (SV3_1aPythonListener*)prog;
  std::string file =
      listener->getPythonListen()->getParseFile()->getFileName(0);
  return file;
}

int SURELOG::SLgetLine(SV3_1aPythonListener* prog, ParserRuleContext* context) {
  SV3_1aPythonListener* listener = (SV3_1aPythonListener*)prog;
  ParserRuleContext* ctx = (ParserRuleContext*)context;
  std::pair<int, int> lineCol =
      ParseUtils::getLineColumn(listener->getTokenStream(), ctx);
  return lineCol.first;
}

int SURELOG::SLgetColumn(SV3_1aPythonListener* prog,
                         ParserRuleContext* context) {
  SV3_1aPythonListener* listener = (SV3_1aPythonListener*)prog;
  ParserRuleContext* ctx = (ParserRuleContext*)context;
  std::pair<int, int> lineCol =
      ParseUtils::getLineColumn(listener->getTokenStream(), ctx);
  return lineCol.second;
}

std::string SURELOG::SLgetText(SV3_1aPythonListener* /*prog*/,
                               ParserRuleContext* context) {
  ParserRuleContext* ctx = (ParserRuleContext*)context;
  std::vector<Token*> tokens = ParseUtils::getFlatTokenList(ctx);
  std::string text;
  for (auto token : tokens) {
    text += token->getText() + " ";
  }
  return text;
}

std::vector<std::string> SURELOG::SLgetTokens(SV3_1aPythonListener* prog,
                                              ParserRuleContext* context) {
  ParserRuleContext* ctx = (ParserRuleContext*)context;
  std::vector<Token*> tokens = ParseUtils::getFlatTokenList(ctx);
  std::vector<std::string> body_tokens;
  for (auto token : tokens) {
    body_tokens.push_back(token->getText());
  }
  return body_tokens;
}

ParserRuleContext* SURELOG::SLgetParentContext(SV3_1aPythonListener* prog,
                                               ParserRuleContext* context) {
  ParserRuleContext* ctx = (ParserRuleContext*)context;
  return (ParserRuleContext*)ctx->parent;
}

std::vector<ParserRuleContext*> SURELOG::SLgetChildrenContext(
    SV3_1aPythonListener* prog, ParserRuleContext* context) {
  ParserRuleContext* ctx = (ParserRuleContext*)context;
  std::vector<ParserRuleContext*> children;

  for (unsigned int i = 0; i < ctx->children.size(); i++) {
    // Get the i-th child node of `parent`.
    tree::ParseTree* child = ctx->children[i];
    tree::TerminalNode* node = dynamic_cast<tree::TerminalNode*>(child);
    if (node) {
      // Terminal node
    } else {
      // Rule
      children.push_back((ParserRuleContext*)child);
    }
  }
  return children;
}

NodeId SURELOG::SLgetRootNode(FileContent* fC) {
  if (!fC) return 0;
  return fC->getRootNode();
}

std::string SURELOG::SLgetFile(FileContent* fC, NodeId id) {
  if (!fC) return "";
  return fC->getSymbolTable()->getSymbol(fC->getFileId(id));
}

unsigned int SURELOG::SLgetType(FileContent* fC, NodeId id) {
  if (!fC) return 0;
  return fC->Type(id);
}

NodeId SURELOG::SLgetChild(FileContent* fC, NodeId index) {
  if (!fC) return 0;
  return fC->Child(index);
}

NodeId SURELOG::SLgetSibling(FileContent* fC, NodeId index) {
  if (!fC) return 0;
  return fC->Sibling(index);
}

NodeId SURELOG::SLgetParent(FileContent* fC, NodeId index) {
  if (!fC) return 0;
  return fC->Parent(index);
}

unsigned int SURELOG::SLgetLine(FileContent* fC, NodeId index) {
  if (!fC) return 0;
  return fC->Line(index);
}

std::string SURELOG::SLgetName(FileContent* fC, NodeId index) {
  if (!fC) return "";
  return fC->SymName(index);
}

NodeId SURELOG::SLgetChild(FileContent* fC, NodeId parent, unsigned int type) {
  if (!fC) return 0;
  return fC->sl_get(parent, (VObjectType)type);
}

NodeId SURELOG::SLgetParent(FileContent* fC, NodeId parent, unsigned int type) {
  if (!fC) return 0;
  return fC->sl_parent(parent, (VObjectType)type);
}

std::vector<unsigned int> SURELOG::SLgetAll(FileContent* fC, NodeId parent,
                                            unsigned int type) {
  if (!fC) return {};
  return fC->sl_get_all(parent, (VObjectType)type);
}

std::vector<unsigned int> SURELOG::SLgetAll(FileContent* fC, NodeId parent,
                                            std::vector<unsigned int> types) {
  if (!fC) return {};
  std::vector<VObjectType> vtypes;
  for (auto type : types) vtypes.push_back((VObjectType)type);
  return fC->sl_get_all(parent, vtypes);
}

NodeId SURELOG::SLcollect(FileContent* fC, NodeId parent, unsigned int type) {
  if (!fC) return {};
  return fC->sl_collect(parent, (VObjectType)type);
}

std::vector<unsigned int> SURELOG::SLcollectAll(FileContent* fC, NodeId parent,
                                                unsigned int type, bool first) {
  if (fC)
    return fC->sl_collect_all(parent, (VObjectType)type, first);
  else
    return {};
}

std::vector<unsigned int> SURELOG::SLcollectAll(FileContent* fC, NodeId parent,
                                                std::vector<unsigned int> types,
                                                bool first) {
  if (!fC) return {};
  std::vector<VObjectType> vtypes;
  for (auto type : types) vtypes.push_back((VObjectType)type);
  return fC->sl_collect_all(parent, vtypes, first);
}

std::vector<unsigned int> SURELOG::SLcollectAll(
    FileContent* fC, NodeId parent, std::vector<unsigned int> types,
    std::vector<unsigned int> stopPoints, bool first) {
  if (!fC) return {};
  std::vector<VObjectType> vtypes;
  for (auto type : types) vtypes.push_back((VObjectType)type);
  std::vector<VObjectType> vstops;
  for (auto type : stopPoints) vstops.push_back((VObjectType)type);
  return fC->sl_collect_all(parent, vtypes, vstops, first);
}

unsigned int SURELOG::SLgetnModuleDefinition(Design* design) {
  if (!design) return 0;
  return design->getModuleDefinitions().size();
}

unsigned int SURELOG::SLgetnProgramDefinition(Design* design) {
  if (!design) return 0;
  return design->getProgramDefinitions().size();
}

unsigned int SURELOG::SLgetnPackageDefinition(Design* design) {
  if (!design) return 0;
  return design->getPackageDefinitions().size();
}

unsigned int SURELOG::SLgetnClassDefinition(Design* design) {
  if (!design) return 0;
  return design->getUniqueClassDefinitions().size();
}

unsigned int SURELOG::SLgetnTopModuleInstance(Design* design) {
  if (!design) return 0;
  return design->getTopLevelModuleInstances().size();
}

ModuleDefinition* SURELOG::SLgetModuleDefinition(Design* design,
                                                 unsigned int index) {
  if (!design) return 0;
  ModuleNameModuleDefinitionMap::iterator itr =
      design->getModuleDefinitions().begin();
  for (unsigned int i = 0; i < index; i++) itr++;
  return (*itr).second;
}

Program* SURELOG::SLgetProgramDefinition(Design* design, unsigned int index) {
  if (!design) return 0;
  ProgramNameProgramDefinitionMap::iterator itr =
      design->getProgramDefinitions().begin();
  for (unsigned int i = 0; i < index; i++) itr++;
  return (*itr).second;
}

Package* SURELOG::SLgetPackageDefinition(Design* design, unsigned int index) {
  if (!design) return 0;
  PackageNamePackageDefinitionMultiMap::iterator itr =
      design->getPackageDefinitions().begin();
  for (unsigned int i = 0; i < index; i++) itr++;
  return (*itr).second;
}

ClassDefinition* SURELOG::SLgetClassDefinition(Design* design,
                                               unsigned int index) {
  if (!design) return 0;
  ClassNameClassDefinitionMap::iterator itr =
      design->getUniqueClassDefinitions().begin();
  for (unsigned int i = 0; i < index; i++) itr++;
  return (*itr).second;
}

ModuleInstance* SURELOG::SLgetTopModuleInstance(Design* design,
                                                unsigned int index) {
  if (!design) return 0;
  return design->getTopLevelModuleInstances()[index];
}

std::string SURELOG::SLgetModuleName(ModuleDefinition* module) {
  if (!module) return "";
  return module->getName();
}

std::string SURELOG::SLgetModuleFile(ModuleDefinition* module) {
  if (!module) return "";
  if (module->getFileContents().size())
    return module->getFileContents()[0]->getFileName(module->getNodeIds()[0]);
  else
    return "";
}

unsigned int SURELOG::SLgetModuleLine(ModuleDefinition* module) {
  if (!module) return 0;
  if (module->getFileContents().size())
    return module->getFileContents()[0]->Line(module->getNodeIds()[0]);
  else
    return 0;
}

VObjectType SURELOG::SLgetModuleType(ModuleDefinition* module) {
  if (!module) return VObjectType::slNoType;
  return module->getType();
}

FileContent* SURELOG::SLgetModuleFileContent(ModuleDefinition* module) {
  if (!module) return NULL;
  if (module->getFileContents().size())
    return module->getFileContents()[0];
  else
    return NULL;
}

NodeId SURELOG::SLgetModuleRootNode(ModuleDefinition* module) {
  if (!module) return 0;
  if (module->getFileContents().size())
    return module->getNodeIds()[0];
  else
    return 0;
}

std::string SURELOG::SLgetClassName(ClassDefinition* module) {
  if (!module) return "";
  return module->getName();
}

std::string SURELOG::SLgetClassFile(ClassDefinition* module) {
  if (!module) return "";
  if (module->getFileContents().size() && module->getFileContents()[0])
    return module->getFileContents()[0]->getFileName(module->getNodeIds()[0]);
  else
    return "";
}

unsigned int SURELOG::SLgetClassLine(ClassDefinition* module) {
  if (!module) return 0;
  if (module->getFileContents().size() && module->getFileContents()[0])
    return module->getFileContents()[0]->Line(module->getNodeIds()[0]);
  else
    return 0;
}

VObjectType SURELOG::SLgetClassType(ClassDefinition* module) {
  if (!module) return VObjectType::slNoType;
  return module->getType();
}

FileContent* SURELOG::SLgetClassFileContent(ClassDefinition* module) {
  if (!module) return 0;
  if (module->getFileContents().size() && module->getFileContents()[0])
    return module->getFileContents()[0];
  else
    return NULL;
}

NodeId SURELOG::SLgetClassRootNode(ClassDefinition* module) {
  if (!module) return 0;
  if (module->getFileContents().size() && module->getFileContents()[0])
    return module->getNodeIds()[0];
  else
    return 0;
}

std::string SURELOG::SLgetPackageName(Package* module) {
  if (!module) return "";
  return module->getName();
}

std::string SURELOG::SLgetPackageFile(Package* module) {
  if (!module) return "";
  if (module->getFileContents().size())
    return module->getFileContents()[0]->getFileName(module->getNodeIds()[0]);
  else
    return "";
}

unsigned int SURELOG::SLgetPackageLine(Package* module) {
  if (!module) return 0;
  if (module->getFileContents().size())
    return module->getFileContents()[0]->Line(module->getNodeIds()[0]);
  else
    return 0;
}

VObjectType SURELOG::SLgetPackageType(Package* module) {
  if (!module) return VObjectType::slNoType;
  return module->getType();
}

FileContent* SURELOG::SLgetPackageFileContent(Package* module) {
  if (!module) return 0;
  if (module->getFileContents().size())
    return module->getFileContents()[0];
  else
    return NULL;
}

NodeId SURELOG::SLgetPackageRootNode(Package* module) {
  if (!module) return 0;
  if (module->getFileContents().size())
    return module->getNodeIds()[0];
  else
    return 0;
}

std::string SURELOG::SLgetProgramName(Program* module) {
  if (!module) return "";
  return module->getName();
}

std::string SURELOG::SLgetProgramFile(Program* module) {
  if (!module) return "";
  if (module->getFileContents().size())
    return module->getFileContents()[0]->getFileName(module->getNodeIds()[0]);
  else
    return "";
}

unsigned int SURELOG::SLgetProgramLine(Program* module) {
  if (!module) return 0;
  if (module->getFileContents().size())
    return module->getFileContents()[0]->Line(module->getNodeIds()[0]);
  else
    return 0;
}

VObjectType SURELOG::SLgetProgramType(Program* module) {
  if (!module) return VObjectType::slNoType;
  return module->getType();
}

FileContent* SURELOG::SLgetProgramFileContent(Program* module) {
  if (!module) return 0;
  if (module->getFileContents().size())
    return module->getFileContents()[0];
  else
    return NULL;
}

NodeId SURELOG::SLgetProgramRootNode(Program* module) {
  if (!module) return 0;
  if (module->getFileContents().size())
    return module->getNodeIds()[0];
  else
    return 0;
}

VObjectType SURELOG::SLgetInstanceType(ModuleInstance* instance) {
  if (!instance) return VObjectType::slNoType;
  return instance->getType();
}

VObjectType SURELOG::SLgetInstanceModuleType(ModuleInstance* instance) {
  if (!instance) return VObjectType::slNoType;
  return instance->getModuleType();
}

std::string SURELOG::SLgetInstanceName(ModuleInstance* instance) {
  if (!instance) return "";
  return instance->getInstanceName();
}

std::string SURELOG::SLgetInstanceFullPathName(ModuleInstance* instance) {
  if (!instance) return "";
  return instance->getFullPathName();
}

std::string SURELOG::SLgetInstanceModuleName(ModuleInstance* instance) {
  if (!instance) return "";
  return instance->getModuleName();
}

DesignComponent* SURELOG::SLgetInstanceDefinition(ModuleInstance* instance) {
  if (!instance) return NULL;
  return instance->getDefinition();
}

std::string SURELOG::SLgetInstanceFileName(ModuleInstance* instance) {
  if (!instance) return "";
  return instance->getFileContent()->getFileName(instance->getNodeId());
}

FileContent* SURELOG::SLgetInstanceFileContent(ModuleInstance* instance) {
  if (!instance) return NULL;
  return instance->getFileContent();
}

NodeId SURELOG::SLgetInstanceNodeId(ModuleInstance* instance) {
  if (!instance) return 0;
  return instance->getNodeId();
}

unsigned int SURELOG::SLgetInstanceLine(ModuleInstance* instance) {
  if (!instance) return 0;
  return instance->getLineNb();
}

unsigned int SURELOG::SLgetnInstanceChildren(ModuleInstance* instance) {
  if (!instance) return 0;
  return instance->getNbChildren();
}

ModuleInstance* SURELOG::SLgetInstanceChildren(ModuleInstance* instance,
                                               unsigned int i) {
  if (!instance) return NULL;
  return instance->getChildren(i);
}

ModuleInstance* SURELOG::SLgetInstanceParent(ModuleInstance* instance) {
  if (!instance) return NULL;
  return instance->getParent();
}
