//
// Copyright (C) 2022 The Android Open Source Project
//
// 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 "cuttlefish/host/commands/metrics/host_receiver.h"

#include <string>

#include "absl/log/check.h"
#include "absl/log/log.h"

#include "cuttlefish/host/commands/metrics/events.h"
#include "cuttlefish/host/libs/config/cuttlefish_config.h"
#include "cuttlefish/host/libs/config/vmm_mode.h"
#include "cuttlefish/host/libs/metrics/metrics_configs.h"
#include "cuttlefish/host/libs/metrics/metrics_defs.h"
#include "cuttlefish/host/libs/msg_queue/msg_queue.h"
#include "external_proto/cf_log.pb.h"

namespace cuttlefish {

using logs::proto::wireless::android::cuttlefish::CuttlefishLogEvent;

MetricsHostReceiver::MetricsHostReceiver(bool is_metrics_enabled)
    : is_metrics_enabled_(is_metrics_enabled) {}

MetricsHostReceiver::~MetricsHostReceiver() {}

void MetricsHostReceiver::ServerLoop() {
  auto msg_queue = SysVMessageQueue::Create(metrics_queue_name_);
  if (msg_queue == NULL) {
    LOG(FATAL) << "create: failed to create" << metrics_queue_name_;
  }

  struct msg_buffer msg = {0, {0}};
  while (true) {
    int rc = msg_queue->Receive(&msg, MAX_MSG_SIZE, 1, true);
    if (rc == -1) {
      LOG(FATAL) << "receive: failed to receive any messages";
    }

    std::string text(msg.mesg_text);
    LOG(INFO) << "Metrics host received: " << text;

    // Process the received message
    ProcessMessage(text);

    sleep(1);
  }
}

void MetricsHostReceiver::Join() { thread_.join(); }

bool MetricsHostReceiver::Initialize(const std::string& metrics_queue_name) {
  metrics_queue_name_ = metrics_queue_name;
  if (!is_metrics_enabled_) {
    LOG(ERROR) << "init: metrics not enabled";
    return false;
  }

  // Start the server loop in a separate thread
  thread_ = std::thread(&MetricsHostReceiver::ServerLoop, this);
  return true;
}

void MetricsHostReceiver::ProcessMessage(const std::string& text) {
  int rc = MetricsExitCodes::kSuccess;

  const CuttlefishConfig* config = CuttlefishConfig::Get();
  CHECK(config) << "Could not open cuttlefish config";
  VmmMode vmm_mode = config->vm_manager();

  if (text == "VMStart") {
    rc = metrics::SendVMStart(vmm_mode);
  } else if (text == "VMStop") {
    rc = metrics::SendVMStop(vmm_mode);
  } else if (text == "DeviceBoot") {
    rc = metrics::SendDeviceBoot(vmm_mode);
  } else if (text == "LockScreen") {
    rc = metrics::SendLockScreen(vmm_mode);
  } else {
    LOG(ERROR) << "Message not recognized: " << text;
    rc = MetricsExitCodes::kMetricsError;
  }

  if (rc != MetricsExitCodes::kSuccess) {
    LOG(ERROR) << "Message failed to send to ClearCut: " << text;
  }
}

}  // namespace cuttlefish
