/*
 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 "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::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,
                                    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 += "[  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));
}

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::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));
}
