/*
 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:   ErrorContainer.cpp
 * Author: alain
 *
 * Created on March 5, 2017, 11:12 PM
 */
#include "Python.h"
#include "ErrorReporting/ErrorContainer.h"
#include <mutex>
#include <iostream>
#include <fstream>
#include "CommandLine/CommandLineParser.h"
#include "ErrorReporting/Waiver.h"

#include "antlr4-runtime.h"
using namespace antlr4;

#include "API/PythonAPI.h"

using namespace SURELOG;

ErrorContainer::ErrorContainer(SymbolTable* symbolTable)
    : m_clp(NULL),
      m_reportedFatalErrorLogFile(false),
      m_symbolTable(symbolTable),
      m_interpState(NULL) {
  m_interpState = PythonAPI::getMainInterp();
  /* Do nothing here */
}

void ErrorContainer::init() {
  if (ErrorDefinition::init()) {
    const std::string& logFileName =
        m_clp->getSymbolTable()->getSymbol(m_clp->getLogFileId());
    std::ofstream ofs;
    ofs.open(logFileName, std::fstream::out);
    if (!ofs.good()) {
      std::cerr << "[FATAL:LG0001] Cannot create log file \"" << logFileName
                << "\"" << std::endl;
      return;
    }
    ofs.close();
  }
}

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

ErrorContainer::~ErrorContainer() {}

Error& ErrorContainer::addError(Error& error, bool showDuplicates,
                                bool reentrantPython) {
  std::tuple<std::string, bool, bool> textStatus =
      createErrorMessage(error, reentrantPython);
  if (std::get<2>(textStatus))  // filter Message
    return error;

  std::multimap<ErrorDefinition::ErrorType, Waiver::WaiverData>& waivers =
      Waiver::getWaivers();
  std::pair<
      std::multimap<ErrorDefinition::ErrorType, Waiver::WaiverData>::iterator,
      std::multimap<ErrorDefinition::ErrorType, Waiver::WaiverData>::iterator>
      ret = waivers.equal_range(error.m_errorId);
  for (std::multimap<ErrorDefinition::ErrorType, Waiver::WaiverData>::iterator
           it = ret.first;
       it != ret.second; ++it) {
    if ((((*it).second.m_fileName == "") ||
         (m_symbolTable->getSymbol(error.m_locations[0].m_fileId) ==
          (*it).second.m_fileName)) &&
        (((*it).second.m_line == 0) ||
         (error.m_locations[0].m_line == (*it).second.m_line)) &&
        (((*it).second.m_objectId == "") ||
         (m_symbolTable->getSymbol(error.m_locations[0].m_object) ==
          (*it).second.m_objectId))) {
      error.m_waived = true;
      break;
    }
  }

  if (showDuplicates) {
    m_errors.push_back(error);
  } else {
    if (m_errorSet.find(std::get<0>(textStatus)) == m_errorSet.end()) {
      m_errors.push_back(error);
      m_errorSet.insert(std::get<0>(textStatus));
    }
  }
  return m_errors[m_errors.size() - 1];
}

void ErrorContainer::appendErrors(ErrorContainer& rhs) {
  for (unsigned int i = 0; i < rhs.m_errors.size(); i++) {
    Error err = rhs.m_errors[i];
    // Translate IDs to master symbol table
    for (unsigned int locItr = 0; locItr < err.m_locations.size(); locItr++) {
      Location& loc = err.m_locations[locItr];
      if (loc.m_fileId)
        loc.m_fileId = m_symbolTable->registerSymbol(
            rhs.m_symbolTable->getSymbol(loc.m_fileId));
      if (loc.m_object) {
        loc.m_object = m_symbolTable->registerSymbol(
            rhs.m_symbolTable->getSymbol(loc.m_object));
      }
    }
    if (!err.m_reported) addError(err);
  }
}

std::tuple<std::string, bool, bool> ErrorContainer::createErrorMessage(
    Error& msg, bool reentrantPython) {
  const std::map<ErrorDefinition::ErrorType, ErrorDefinition::ErrorInfo>&
      infoMap = ErrorDefinition::getErrorInfoMap();
  std::string tmp;
  bool reportFatalError = false;
  bool filterMessage = false;
  if ((!msg.m_reported) && (!msg.m_waived)) {
    ErrorDefinition::ErrorType type = msg.m_errorId;
    std::map<ErrorDefinition::ErrorType,
             ErrorDefinition::ErrorInfo>::const_iterator itr =
        infoMap.find(type);
    if (itr != infoMap.end()) {
      ErrorDefinition::ErrorInfo info = (*itr).second;
      std::string severity;
      switch (info.m_severity) {
        case ErrorDefinition::FATAL:
          severity = "FATAL";
          reportFatalError = true;
          break;
        case ErrorDefinition::SYNTAX:
          severity = "SYNTX";
          break;
        case ErrorDefinition::ERROR:
          severity = "ERROR";
          break;
        case ErrorDefinition::WARNING:
          severity = "WARNI";
          if (m_clp->filterWarning()) filterMessage = true;
          break;
        case ErrorDefinition::INFO:
          severity = "INFO ";
          if (m_clp->filterInfo() &&
              (type != ErrorDefinition::PP_PROCESSING_SOURCE_FILE))
            filterMessage = true;
          break;
        case ErrorDefinition::NOTE:
          severity = "NOTE ";
          if (m_clp->filterNote()) filterMessage = true;
          break;
      }
      std::string category = ErrorDefinition::getCategoryName(info.m_category);

      Location& loc = msg.m_locations[0];
      /* Object */
      std::string text = info.m_errorText;
      const std::string& objectName = m_symbolTable->getSymbol(loc.m_object);
      if (objectName != m_symbolTable->getBadSymbol()) {
        size_t objectOffset = text.find("%s");
        if (objectOffset != std::string::npos) {
          text = text.replace(objectOffset, 2, objectName);
        }
      }

      /* Location */
      std::string location;
      if (loc.m_fileId == 0) {
      } else {
        const std::string& fileName = m_symbolTable->getSymbol(loc.m_fileId);
        location = fileName;
        if (loc.m_line > 0) {
          location += ":" + std::to_string(loc.m_line);
          // Emacs does not like column
          // if (loc.m_column > 0)
          //  location += ":" + std::to_string (loc.m_column);
        }
        location += " ";
      }

      /* Extra locations */
      unsigned int nbExtraLoc = msg.m_locations.size();
      for (unsigned int i = 1; i < nbExtraLoc; i++) {
        Location& extraLoc = msg.m_locations[i];
        if (extraLoc.m_fileId) {
          std::string extraLocation;
          const std::string& fileName =
              m_symbolTable->getSymbol(extraLoc.m_fileId);
          extraLocation = fileName;
          if (extraLoc.m_line > 0) {
            extraLocation += ":" + std::to_string(extraLoc.m_line);
            // Emacs does not like column
            // if (extraLoc.m_column > 0)
            //  extraLocation += ":" + std::to_string (extraLoc.m_column);
          }
          size_t objectOffset = text.find("%exloc");
          if (objectOffset != std::string::npos) {
            text = text.replace(objectOffset, 6, extraLocation);
          } else if (info.m_extraText != "") {
            text += ",\n               " + info.m_extraText;
            // text += ",\n" + info.m_extraText;
            size_t objectOffset = text.find("%exloc");
            if (objectOffset != std::string::npos) {
              text = text.replace(objectOffset, 6, extraLocation);
            }
          }
        } else {
          if (info.m_extraText != "") {
            if ((nbExtraLoc == 2) && (extraLoc.m_fileId == 0))
              text += ",\n" + info.m_extraText;
            else
              text += ",\n               " + info.m_extraText;
          }
        }
        if (extraLoc.m_object) {
          const std::string& objString =
              m_symbolTable->getSymbol(extraLoc.m_object);
          size_t objectOffset = text.find("%exobj");
          if (objectOffset != std::string::npos) {
            text = text.replace(objectOffset, 6, objString);
          }
        }
      }
      text += ".";
      std::string padding;
      if (msg.m_errorId < 10)
        padding = "000";
      else if (msg.m_errorId < 100)
        padding = "00";
      else if (msg.m_errorId < 1000)
        padding = "0";
      if ((reentrantPython == false) || (!m_clp->pythonAllowed())) {
        tmp = "[" + severity + ":" + category + padding +
              std::to_string(msg.m_errorId) + "] " + location + text + "\n\n";
      } else {
        std::vector<std::string> args;
        args.push_back(severity);
        args.push_back(category);
        args.push_back(padding + std::to_string(msg.m_errorId));
        args.push_back(location);
        args.push_back(text);
        tmp = PythonAPI::evalScript("__main__", "SLformatMsg", args,
                                    (PyThreadState*) m_interpState);
      }
    }
  }
  return std::make_tuple(tmp, reportFatalError, filterMessage);
}

bool ErrorContainer::hasFatalErrors() {
  const std::map<ErrorDefinition::ErrorType, ErrorDefinition::ErrorInfo>&
      infoMap = ErrorDefinition::getErrorInfoMap();
  bool reportFatalError = false;
  for (unsigned int i = 0; i < m_errors.size(); i++) {
    Error& msg = m_errors[i];
    ErrorDefinition::ErrorType type = msg.m_errorId;
    std::map<ErrorDefinition::ErrorType,
             ErrorDefinition::ErrorInfo>::const_iterator itr =
        infoMap.find(type);
    if (itr != infoMap.end()) {
      ErrorDefinition::ErrorInfo info = (*itr).second;
      std::string severity;
      switch (info.m_severity) {
        case ErrorDefinition::FATAL:
          reportFatalError = true;
          break;
        default:
          break;
      }
    }
  }
  return reportFatalError;
}

std::pair<std::string, bool> ErrorContainer::createReport_() {
  std::string report;
  bool reportFatalError = false;
  for (unsigned int i = 0; i < m_errors.size(); i++) {
    Error& msg = m_errors[i];
    std::tuple<std::string, bool, bool> textStatus = createErrorMessage(msg);
    if (std::get<1>(textStatus)) reportFatalError = true;
    if (std::get<2>(textStatus))  // Filtered
      continue;
    report += std::get<0>(textStatus);
    msg.m_reported = true;
  }
  return std::make_pair(report, reportFatalError);
}

std::pair<std::string, bool> ErrorContainer::createReport_(Error& error) {
  std::string report;
  bool reportFatalError = false;
  Error& msg = error;
  std::tuple<std::string, bool, bool> textStatus = createErrorMessage(msg);
  if (std::get<1>(textStatus)) reportFatalError = true;
  if (!std::get<2>(textStatus))  // Filtered
    report += std::get<0>(textStatus);
  msg.m_reported = true;
  return std::make_pair(report, reportFatalError);
}

bool ErrorContainer::printStats(ErrorContainer::Stats stats, bool muteStdout) {
  std::string report;
  report += "[  FATAL] : " + std::to_string(stats.nbFatal) + "\n";
  report += "[ SYNTAX] : " + std::to_string(stats.nbSyntax) + "\n";
  report += "[  ERROR] : " + std::to_string(stats.nbError) + "\n";
  report += "[WARNING] : " + std::to_string(stats.nbWarning) + "\n";
  // BOGUS NUMBER IN CACHED MODE  report += "[   INFO] : " +
  // std::to_string(stats.nbInfo) + "\n";
  report += "[   NOTE] : " + std::to_string(stats.nbNote) + "\n";
  if (!muteStdout) {
    std::cout << report << std::flush;
  }
  bool successLogFile = printToLogFile(report);
  return (successLogFile && (!stats.nbFatal) && (!stats.nbSyntax));
}

ErrorContainer::Stats ErrorContainer::getErrorStats() {
  const std::map<ErrorDefinition::ErrorType, ErrorDefinition::ErrorInfo>&
      infoMap = ErrorDefinition::getErrorInfoMap();
  ErrorContainer::Stats stats;
  for (auto msg : m_errors) {
    if (!msg.m_waived) {
      ErrorDefinition::ErrorType type = msg.m_errorId;
      std::map<ErrorDefinition::ErrorType,
               ErrorDefinition::ErrorInfo>::const_iterator itr =
          infoMap.find(type);
      if (itr != infoMap.end()) {
        ErrorDefinition::ErrorInfo info = (*itr).second;
        switch (info.m_severity) {
          case ErrorDefinition::FATAL:
            stats.nbFatal++;
            break;
          case ErrorDefinition::SYNTAX:
            stats.nbSyntax++;
            break;
          case ErrorDefinition::ERROR:
            stats.nbError++;
            break;
          case ErrorDefinition::WARNING:
            stats.nbWarning++;
            break;
          case ErrorDefinition::INFO:
            stats.nbInfo++;
            break;
          case ErrorDefinition::NOTE:
            stats.nbNote++;
            break;
        }
      }
    }
  }
  return stats;
}

static std::mutex m;
bool ErrorContainer::printToLogFile(std::string report) {
  m.lock();
  const std::string& logFileName =
      m_clp->getSymbolTable()->getSymbol(m_clp->getLogFileId());
  std::ofstream ofs;
  ofs.open(logFileName, std::fstream::app);
  if (!ofs.good()) {
    if (!m_reportedFatalErrorLogFile) {
      std::cerr << "[FATAL:LG0002] Cannot open log file \"" << logFileName
                << "\" in append mode" << std::endl;
      m_reportedFatalErrorLogFile = true;
    }
    m.unlock();
    return false;
  } else {
    ofs << report << std::flush;
    ofs.close();
  }
  m.unlock();
  return true;
}

bool ErrorContainer::printMessage(Error& error, bool muteStdout) {
  if (error.m_reported) return false;
  std::pair<std::string, bool> report = createReport_(error);

  if (!muteStdout) {
    std::cout << report.first << std::flush;
  }
  bool successLogFile = printToLogFile(report.first);
  error.m_reported = true;
  return (successLogFile && (!report.second));
}

bool ErrorContainer::printMessages(bool muteStdout) {
  std::pair<std::string, bool> report = createReport_();

  if (!muteStdout) {
    std::cout << report.first << std::flush;
  }
  bool successLogFile = printToLogFile(report.first);
  return (successLogFile && (!report.second));
}
