/*
 * SPDX-FileCopyrightText: Copyright 2022 Arm Limited and/or its affiliates <open-source-office@arm.com>
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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.
 */
#include "Profiler.hpp"
#include "log_macros.h"

#include <cstring>

namespace arm {
namespace app {
    Profiler::Profiler()
        : Profiler("Unknown")
    {}

    Profiler::Profiler(const char* name)
        : m_name(name)
    {}

    bool Profiler::StartProfiling(const char* name)
    {
        if (name) {
            this->SetName(name);
        }

        if (!this->m_started) {
            hal_pmu_reset();
            this->m_tstampSt.initialised = false;
            hal_pmu_get_counters(&this->m_tstampSt);
            if (this->m_tstampSt.initialised) {
                if (this->m_profStats.count(this->m_name) == 0) {
                    this->m_profStats.insert(
                            std::pair<std::string, std::vector<Statistics>>(
                                    this->m_name, std::vector<Statistics>(this->m_tstampSt.num_counters))
                                    );
                }
                this->m_started = true;
                return true;
            }
        }
        printf_err("Failed to start profiler %s\n", this->m_name.c_str());
        return false;
    }

    bool Profiler::StopProfiling()
    {
        if (this->m_started) {
            this->m_tstampEnd.initialised = false;
            hal_pmu_get_counters(&this->m_tstampEnd);
            this->m_started = false;
            if (this->m_tstampEnd.initialised) {
                this->UpdateRunningStats(
                    this->m_tstampSt,
                    this->m_tstampEnd,
                    this->m_name);
                return true;
            }
        }
        printf_err("Failed to stop profiler %s\n", this->m_name.c_str());
        return false;
    }

    bool Profiler::StopProfilingAndReset()
    {
        if (this->StopProfiling()) {
            this->Reset();
            return true;
        }
        printf_err("Failed to stop profiler %s\n", this->m_name.c_str());
        return false;
    }

    void Profiler::Reset()
    {
        this->m_started = false;
        this->m_profStats.clear();
        memset(&this->m_tstampSt, 0, sizeof(this->m_tstampSt));
        memset(&this->m_tstampEnd, 0, sizeof(this->m_tstampEnd));
    }

    void calcProfilingStat(uint64_t currentValue,
                           Statistics& data)
    {
        data.total += currentValue;
        data.min = std::min(data.min, currentValue);
        data.max = std::max(data.max, currentValue);
        data.avrg = (static_cast<double>(data.total) / data.samplesNum);
    }

    void Profiler::GetAllResultsAndReset(std::vector<ProfileResult>& results)
    {
        for (const auto& item: this->m_profStats) {
            auto name = item.first;
            std::vector<Statistics> series = item.second;
            ProfileResult result{};
            result.name = item.first;

            for (Statistics& stat : series) {
                result.samplesNum = stat.samplesNum;
                result.data.emplace_back(stat);
            }

            results.emplace_back(result);
        }

        this->Reset();
    }

    void printStatisticsHeader(uint32_t samplesNum) {
        info("Number of samples: %" PRIu32 "\n", samplesNum);
        info("%s\n", "Total / Avg./ Min / Max");
    }

    void Profiler::PrintProfilingResult(bool printFullStat) {
        std::vector<ProfileResult> results{};
        GetAllResultsAndReset(results);
        for(ProfileResult& result: results) {
            if (!result.data.empty()) {
                info("Profile for %s:\n", result.name.c_str());
                if (printFullStat) {
                    printStatisticsHeader(result.samplesNum);
                }
            }

            for (Statistics &stat: result.data) {
                if (printFullStat) {
                    info("%s %s: %" PRIu64 "/ %.0f / %" PRIu64 " / %" PRIu64 " \n",
                         stat.name.c_str(), stat.unit.c_str(),
                         stat.total, stat.avrg, stat.min, stat.max);
                } else {
                    info("%s: %.0f %s\n", stat.name.c_str(), stat.avrg, stat.unit.c_str());
                }
            }
        }
    }

    void Profiler::SetName(const char* str)
    {
        this->m_name = std::string(str);
    }

    void Profiler::UpdateRunningStats(pmu_counters start, pmu_counters end,
                                      const std::string& name)
    {
        struct ProfilingUnit unit = {
            .counters = end
        };

        if (end.num_counters != start.num_counters ||
            !end.initialised || !start.initialised) {
            printf_err("Invalid start or end counters\n");
            return;
        }

        for (size_t i = 0; i < unit.counters.num_counters; ++i) {
            if (unit.counters.counters[i].value < start.counters[i].value) {
                warn("Overflow detected for %s\n", unit.counters.counters[i].name);
                unit.counters.counters[i].value = 0;
            } else {
                unit.counters.counters[i].value -= start.counters[i].value;
            }
        }

        for (size_t i = 0; i < this->m_profStats[name].size(); ++i) {
            this->m_profStats[name][i].name = unit.counters.counters[i].name;
            this->m_profStats[name][i].unit = unit.counters.counters[i].unit;
            ++this->m_profStats[name][i].samplesNum;
            calcProfilingStat(
                    unit.counters.counters[i].value,
                    this->m_profStats[name][i]);
        }

        ProfileResult result{};
        result.name = this->m_name;
        result.samplesNum = this->m_profStats[name][0].samplesNum;

        for (Statistics& stat : this->m_profStats[name]) {
            result.data.emplace_back(stat);
        }
    }

} /* namespace app */
} /* namespace arm */
