/*
 * Copyright 2018 Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include <fstream>
#include <map>
#include <sstream>
#include <string>

#include "base/cprintf.hh"
#include "systemc/core/process.hh"
#include "systemc/core/scheduler.hh"
#include "systemc/ext/core/sc_main.hh"
#include "systemc/ext/utils/messages.hh"
#include "systemc/ext/utils/sc_report_handler.hh"
#include "systemc/utils/report.hh"

namespace sc_core
{

namespace
{

std::unique_ptr<std::string> logFileName;
std::unique_ptr<std::ofstream> logFile;

} // anonymous namespace

void
sc_report_handler::report(sc_severity severity, const char *msg_type,
                          const char *msg, const char *file, int line)
{
    report(severity, msg_type, msg, SC_MEDIUM, file, line);
}

void
sc_report_handler::report(sc_severity severity, const char *msg_type,
                          const char *msg, int verbosity, const char *file,
                          int line)
{
    if (!msg_type)
        msg_type = SC_ID_UNKNOWN_ERROR_;

    if (severity == SC_INFO && verbosity > sc_gem5::reportVerbosityLevel)
        return;

    sc_gem5::ReportSevInfo &sevInfo = sc_gem5::reportSevInfos[severity];
    sc_gem5::ReportMsgInfo &msgInfo = sc_gem5::reportMsgInfoMap()[msg_type];

    sevInfo.count++;
    msgInfo.count++;
    msgInfo.sevCounts[severity]++;

    sc_actions actions = SC_UNSPECIFIED;
    if (msgInfo.sevActions[severity] != SC_UNSPECIFIED)
        actions = msgInfo.sevActions[severity];
    else if (msgInfo.actions != SC_UNSPECIFIED)
        actions = msgInfo.actions;
    else if (sevInfo.actions != SC_UNSPECIFIED)
        actions = sevInfo.actions;

    actions &= ~sc_gem5::reportSuppressedActions;
    actions |= sc_gem5::reportForcedActions;

    msgInfo.checkLimits(severity, actions);
    sevInfo.checkLimit(actions);

    ::sc_gem5::Process *current = ::sc_gem5::scheduler.current();
    sc_report report(severity, msg_type, msg, verbosity, file, line,
            sc_time::from_value(::sc_gem5::scheduler.getCurTick()),
            current ? current->name() : nullptr, msgInfo.id);

    if (actions & SC_CACHE_REPORT) {
        if (current) {
            current->lastReport(&report);
        } else {
            sc_gem5::globalReportCache =
                std::unique_ptr<sc_report>(new sc_report(report));
        }
    }

    sc_gem5::reportHandlerProc(report, actions);
}

void
sc_report_handler::report(sc_severity severity, int id, const char *msg,
                          const char *file, int line)
{
    std::string &msg_type = sc_gem5::reportIdToMsgMap()[id];

    if (sc_gem5::reportWarningsAsErrors && severity == SC_WARNING)
        severity = SC_ERROR;

    report(severity, msg_type.c_str(), msg, file, line);
}

sc_actions
sc_report_handler::set_actions(sc_severity severity, sc_actions actions)
{
    sc_gem5::ReportSevInfo &info = sc_gem5::reportSevInfos[severity];
    sc_actions previous = info.actions;
    info.actions = actions;
    return previous;
}

sc_actions
sc_report_handler::set_actions(const char *msg_type, sc_actions actions)
{
    if (!msg_type)
        msg_type = SC_ID_UNKNOWN_ERROR_;

    sc_gem5::ReportMsgInfo &info = sc_gem5::reportMsgInfoMap()[msg_type];
    sc_actions previous = info.actions;
    info.actions = actions;
    return previous;
}

sc_actions
sc_report_handler::set_actions(
        const char *msg_type, sc_severity severity, sc_actions actions)
{
    if (!msg_type)
        msg_type = SC_ID_UNKNOWN_ERROR_;

    sc_gem5::ReportMsgInfo &info = sc_gem5::reportMsgInfoMap()[msg_type];
    sc_actions previous = info.sevActions[severity];
    info.sevActions[severity] = actions;
    return previous;
}

int
sc_report_handler::stop_after(sc_severity severity, int limit)
{
    sc_gem5::ReportSevInfo &info = sc_gem5::reportSevInfos[severity];
    int previous = info.limit;
    info.limit = limit;
    return previous;
}

int
sc_report_handler::stop_after(const char *msg_type, int limit)
{
    if (!msg_type)
        msg_type = SC_ID_UNKNOWN_ERROR_;

    sc_gem5::ReportMsgInfo &info = sc_gem5::reportMsgInfoMap()[msg_type];
    int previous = info.limit;
    info.limit = limit;
    return previous;
}

int
sc_report_handler::stop_after(
        const char *msg_type, sc_severity severity, int limit)
{
    if (!msg_type)
        msg_type = SC_ID_UNKNOWN_ERROR_;

    sc_gem5::ReportMsgInfo &info = sc_gem5::reportMsgInfoMap()[msg_type];
    int previous = info.sevLimits[severity];
    info.sevLimits[severity] = limit;
    return previous;
}

int
sc_report_handler::get_count(sc_severity severity)
{
    return sc_gem5::reportSevInfos[severity].count;
}

int
sc_report_handler::get_count(const char *msg_type)
{
    if (!msg_type)
        msg_type = SC_ID_UNKNOWN_ERROR_;

    return sc_gem5::reportMsgInfoMap()[msg_type].count;
}

int
sc_report_handler::get_count(const char *msg_type, sc_severity severity)
{
    if (!msg_type)
        msg_type = SC_ID_UNKNOWN_ERROR_;

    return sc_gem5::reportMsgInfoMap()[msg_type].sevCounts[severity];
}

int
sc_report_handler::set_verbosity_level(int vl)
{
    int previous = sc_gem5::reportVerbosityLevel;
    sc_gem5::reportVerbosityLevel = vl;
    return previous;
}

int
sc_report_handler::get_verbosity_level()
{
    return sc_gem5::reportVerbosityLevel;
}


sc_actions
sc_report_handler::suppress(sc_actions actions)
{
    sc_actions previous = sc_gem5::reportSuppressedActions;
    sc_gem5::reportSuppressedActions = actions;
    return previous;
}

sc_actions
sc_report_handler::suppress()
{
    return suppress(SC_UNSPECIFIED);
}

sc_actions
sc_report_handler::force(sc_actions actions)
{
    sc_actions previous = sc_gem5::reportForcedActions;
    sc_gem5::reportForcedActions = actions;
    return previous;
}

sc_actions
sc_report_handler::force()
{
    return force(SC_UNSPECIFIED);
}


sc_actions
sc_report_handler::set_catch_actions(sc_actions actions)
{
    sc_actions previous = sc_gem5::reportCatchActions;
    sc_gem5::reportCatchActions = actions;
    return previous;
}

sc_actions
sc_report_handler::get_catch_actions()
{
    return sc_gem5::reportCatchActions;
}


void
sc_report_handler::set_handler(sc_report_handler_proc proc)
{
    sc_gem5::reportHandlerProc = proc;
}

void
sc_report_handler::default_handler(
        const sc_report &report, const sc_actions &actions)
{
    if (actions & SC_DISPLAY)
        cprintf("\n%s\n", sc_report_compose_message(report));

    if ((actions & SC_LOG) && logFile) {
        ccprintf(*logFile, "%s: %s\n", report.get_time().to_string(),
                 sc_report_compose_message(report));
    }
    if (actions & SC_STOP) {
        sc_stop_here(report.get_msg_type(), report.get_severity());
        sc_stop();
    }
    if (actions & SC_INTERRUPT)
        sc_interrupt_here(report.get_msg_type(), report.get_severity());
    if (actions & SC_ABORT)
        sc_abort();
    if (actions & SC_THROW) {
        ::sc_gem5::Process *current = ::sc_gem5::scheduler.current();
        if (current)
            current->isUnwinding(false);
        throw report;
    }
}

sc_actions
sc_report_handler::get_new_action_id()
{
    static sc_actions maxAction = SC_ABORT;
    maxAction = maxAction << 1;
    return maxAction;
}

sc_report *
sc_report_handler::get_cached_report()
{
    ::sc_gem5::Process *current = ::sc_gem5::scheduler.current();
    if (current)
        return current->lastReport();
    return ::sc_gem5::globalReportCache.get();
}

void
sc_report_handler::clear_cached_report()
{
    ::sc_gem5::Process *current = ::sc_gem5::scheduler.current();
    if (current) {
        current->lastReport(nullptr);
    } else {
        ::sc_gem5::globalReportCache = nullptr;
    }
}

bool
sc_report_handler::set_log_file_name(const char *new_name)
{
    if (!new_name) {
        logFile = nullptr;
        logFileName = nullptr;
        return false;
    } else {
        if (logFileName)
            return false;
        logFileName = std::unique_ptr<std::string>(new std::string(new_name));
        logFile = std::unique_ptr<std::ofstream>(new std::ofstream(new_name));
        return true;
    }
}

const char *
sc_report_handler::get_log_file_name()
{
    if (!logFileName)
        return nullptr;
    else
        return logFileName->c_str();
}

void
sc_interrupt_here(const char *msg_type, sc_severity)
{
    // Purposefully empty, for setting breakpoints supposedly.
}

void
sc_stop_here(const char *msg_type, sc_severity)
{
    // Purposefully empty, for setting breakpoints supposedly.
}

const std::string
sc_report_compose_message(const sc_report &report)
{
    std::ostringstream str;

    const char *sevName = sc_gem5::reportSeverityNames[report.get_severity()];
    int id = report.get_id();

    str << sevName << ": ";
    if (id >= 0) {
        ccprintf(str, "(%c%d) ", sevName[0], id);
    }
    str << report.get_msg_type();

    const char *msg = report.get_msg();
    if (msg && msg[0])
        str << ": " << msg;

    if (report.get_severity() > SC_INFO) {
        ccprintf(str, "\nIn file: %s:%d", report.get_file_name(),
                 report.get_line_number());

        ::sc_gem5::Process *current = ::sc_gem5::scheduler.current();
        const char *name = report.get_process_name();
        if (current && sc_is_running() && name) {
            ccprintf(str, "\nIn process: %s @ %s", name,
                    report.get_time().to_string());
        }
    }

    return str.str();
}

bool
sc_report_close_default_log()
{
    if (logFile) {
        logFile = nullptr;
        logFileName = nullptr;
        return false;
    }
    return true;
}

} // namespace sc_core
