// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "garnet/lib/perfmon/controller_impl.h"

#include <fuchsia/perfmon/cpu/cpp/fidl.h>

#include "garnet/lib/perfmon/config_impl.h"
#include "garnet/lib/perfmon/device_reader.h"
#include "garnet/lib/perfmon/properties_impl.h"
#include "src/lib/fxl/logging.h"

namespace perfmon {
namespace internal {

ControllerImpl::ControllerImpl(ControllerSyncPtr controller_ptr, uint32_t num_traces,
                               uint32_t buffer_size_in_pages, Config config)
    : controller_ptr_(std::move(controller_ptr)),
      num_traces_(num_traces),
      buffer_size_in_pages_(buffer_size_in_pages),
      config_(std::move(config)),
      weak_ptr_factory_(this) {}

ControllerImpl::~ControllerImpl() { Reset(); }

bool ControllerImpl::Start() {
  if (started_) {
    FX_LOGS(ERROR) << "already started";
    return false;
  }

  if (!Stage()) {
    return false;
  }

  ::fuchsia::perfmon::cpu::Controller_Start_Result result;
  zx_status_t status = controller_ptr_->Start(&result);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Starting trace failed: status=" << status;
    return false;
  }
  if (result.is_err()) {
    FX_LOGS(ERROR) << "Starting trace failed: error=" << result.err();
    return false;
  }

  started_ = true;
  return true;
}

void ControllerImpl::Stop() {
  zx_status_t status = controller_ptr_->Stop();
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Stopping trace failed: status=" << status;
  } else {
    started_ = false;
  }
}

bool ControllerImpl::Stage() {
  FX_DCHECK(!started_);

  FidlPerfmonConfig fidl_config;
  internal::PerfmonToFidlConfig(config_, &fidl_config);

  ::fuchsia::perfmon::cpu::Controller_StageConfig_Result result;
  zx_status_t status = controller_ptr_->StageConfig(fidl_config, &result);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Staging config failed: status=" << status;
    return false;
  }
  if (result.is_err()) {
    FX_LOGS(ERROR) << "Staging config failed: error=" << result.err();
    return false;
  }

  return true;
}

void ControllerImpl::Terminate() {
  zx_status_t status = controller_ptr_->Terminate();
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Terminating trace failed: status=" << status;
  } else {
    started_ = false;
  }
}

void ControllerImpl::Reset() {
  Stop();
  Terminate();
}

bool ControllerImpl::GetBufferHandle(const std::string& name, uint32_t trace_num,
                                     zx::vmo* out_vmo) {
  uint32_t descriptor = trace_num;
  zx_status_t status = controller_ptr_->GetBufferHandle(descriptor, out_vmo);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Getting buffer handle failed: status=" << status;
    return false;
  }
  if (!*out_vmo) {
    FX_LOGS(ERROR) << "Getting buffer handle failed: no handle returned";
    return false;
  }
  return true;
}

std::unique_ptr<Reader> ControllerImpl::GetReader() {
  std::unique_ptr<Reader> reader;
  if (DeviceReader::Create(weak_ptr_factory_.GetWeakPtr(), buffer_size_in_pages_, &reader)) {
    return reader;
  }
  return nullptr;
}

}  // namespace internal
}  // namespace perfmon
