// Copyright 2021 Google LLC
//
// 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.

#pragma once

#include "histogram.hpp"

#include <systemd/sd-bus.h>

#include <atomic>
#include <map>
#include <mutex>
#include <string>
#include <vector>

class DBusConnectionSnapshot;
class SensorSnapshot;

enum DBusTopSortField
{
    // DBus Message properties
    kSender,
    kDestination,
    kInterface,
    kPath,
    kMember,
    kSenderPID,
    kSenderCMD,
    // Computed metrics
    kMsgPerSec,
    kAverageLatency,
};

const std::string FieldNames[] = {"Sender",     "Destination", "Interface",
                                  "Path",       "Member",      "Sender PID",
                                  "Sender CMD", "Msg/s",       "Avg Latency"};
const int FieldPreferredWidths[] = {18, 20, 12, 10, 10, 10, 25, 8, 12};
bool DBusTopSortFieldIsNumeric(DBusTopSortField field);

struct DBusTopComputedMetrics
{
    DBusTopComputedMetrics()
    {
        num_signals = 0;
        num_errors = 0;
        num_method_returns = 0;
        num_method_calls = 0;
        total_latency_usec = 0;
    }
    int num_method_returns = 0;
    int num_errors = 0;
    int num_signals = 0;
    int num_method_calls;
    uint64_t total_latency_usec;
};

class DBusTopStatistics
{
  public:
    int num_messages_;
    int num_mc_, num_mr_, num_sig_, num_error_;
    float seconds_since_last_sample_;
    std::vector<DBusTopSortField> fields_;
    std::map<std::vector<std::string>, DBusTopComputedMetrics> stats_;
    DBusTopStatistics() :
        num_messages_(0), num_mc_(0), num_mr_(0), num_sig_(0), num_error_(0),
        seconds_since_last_sample_(0)
    {
        fields_ = {kSender, kDestination, kSenderPID, kSenderCMD};
        stats_.clear();
    }

    std::vector<DBusTopSortField> GetFields()
    {
        return fields_;
    }

    std::vector<std::string> GetFieldNames()
    {
        const int N = fields_.size();
        std::vector<std::string> ret(N);
        for (int i = 0; i < static_cast<int>(fields_.size()); i++)
        {
            ret[i] = FieldNames[static_cast<int>(fields_[i])];
        }
        return ret;
    }

    std::vector<int> GetFieldPreferredWidths()
    {
        const int N = fields_.size();
        std::vector<int> ret(N);
        for (int i = 0; i < static_cast<int>(fields_.size()); i++)
        {
            ret[i] = FieldPreferredWidths[static_cast<int>(fields_[i])];
        }
        return ret;
    }

    void Reset()
    {
        num_messages_ = 0;
        num_mc_ = 0;
        num_mr_ = 0;
        num_sig_ = 0;
        num_error_ = 0;
        stats_.clear();
    }

    void SetSortFieldsAndReset(const std::vector<DBusTopSortField>& f)
    {
        num_messages_ = 0;
        num_mc_ = 0;
        num_mr_ = 0;
        num_sig_ = 0;
        num_error_ = 0;
        stats_.clear();
        fields_ = f;
    }

    void Assign(DBusTopStatistics* out)
    {
        out->num_messages_ = this->num_messages_;
        out->num_mc_ = this->num_mc_;
        out->num_mr_ = this->num_mr_;
        out->num_sig_ = this->num_sig_;
        out->num_error_ = this->num_error_;
        out->seconds_since_last_sample_ = this->seconds_since_last_sample_;
        out->fields_ = this->fields_;
        out->stats_ = this->stats_;
    }

    void OnNewDBusMessage(const char* sender, const char* destination,
                          const char* interface, const char* path,
                          const char* message, const char type,
                          sd_bus_message* m);
    std::string CheckAndFixNullString(const char* x)
    {
        if (x == nullptr)
            return "(null)";
        else
            return std::string(x);
    }

    std::map<std::vector<std::string>, DBusTopComputedMetrics> StatsSnapshot()
    {
        std::map<std::vector<std::string>, DBusTopComputedMetrics> ret;
        ret = stats_;
        return ret;
    }

  private:
    std::mutex mtx_;
};

int GetSummaryIntervalInMillises();
// Monitor sensor details-related DBus method calls/replies
// typedef void (*SetDBusTopConnection)(const char* conn);
namespace dbus_top_analyzer
{
void Process();
void Finish();
typedef void (*DBusTopStatisticsCallback)(DBusTopStatistics*,
                                          Histogram<float>*);
void SetDBusTopStatisticsCallback(DBusTopStatisticsCallback cb);
void AnalyzerThread();
// Methods for sending Object Mapper queries
void ListAllSensors(sd_bus*, DBusConnectionSnapshot**, SensorSnapshot**);
} // namespace dbus_top_analyzer
