#pragma once

#include "ml.h"

#include <unordered_map>
#include <deque>
#include <chrono>
#include <thread>
#include <mutex>


static const int method_name_print_len = 15;
static const int print_top_methods = 15;
static const int call_stack_max_methods = 10;

class MlPerfMon {

private:
    MlPerfMon() : perfOn(false) {
        main_thread_id = std::this_thread::get_id();
    };

public:

    // https://stackoverflow.com/questions/43523509/simple-singleton-example-in-c
    static MlPerfMon& instance(){
        static MlPerfMon instance;
        return instance;
    }

    void turnOn();

    void add_method_call(const std::string &method);
    void end_method_call();

    std::string callstack() const;

    size_t get_callstack_position();
    void restore_callstack_position(size_t to_position);
    void clear_callstack();
    
    void print_results();

private:
    bool perfOn;
    std::unordered_map<std::string, long> calls_counter;
    std::chrono::time_point<std::chrono::high_resolution_clock> start_time;
    std::deque<std::string> call_stack;
    std::thread::id main_thread_id;
};
