/*
 * Copyright (C) 2024 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.
 */

#pragma once

#include <json/json.h>

#include <chrono>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "cuttlefish/common/libs/fs/shared_fd.h"
#include "cuttlefish/host/commands/cvd/instances/cvd_persistent_data.pb.h"
#include "cuttlefish/host/libs/config/cuttlefish_config.h"
#include "cuttlefish/result/result.h"

namespace cuttlefish {

class LocalInstance {
 public:
  LocalInstance(const LocalInstance&) = default;
  LocalInstance(LocalInstance&&) = default;
  LocalInstance& operator=(const LocalInstance&) = default;

  uint32_t Id() const { return instance_proto_->id(); }
  const std::string& Name() const { return instance_proto_->name(); }
  cvd::InstanceState State() const { return instance_proto_->state(); }
  void SetState(cvd::InstanceState state);
  const std::string& WebRtcDeviceId() const {
    return instance_proto_->webrtc_device_id();
  }
  void SetWebRtcDeviceId(std::string webrtc_device_id) {
    instance_proto_->set_webrtc_device_id(std::move(webrtc_device_id));
  }
  std::string InstanceDirectory() const;
  int AdbPort() const;
  const std::string& HomeDirectory() const {
    return group_proto_->home_directory();
  }
  const std::string& HostArtifactsPath() const {
    return group_proto_->host_artifacts_path();
  }
  std::string AssemblyDirectory() const;

  bool IsActive() const;
  // Contacts run_cvd to query the instance status. Returns a JSON object with
  // a description of the instance properties. Waits for run_cvd to respond for
  // at most timeout seconds.
  Result<Json::Value> FetchStatus(
      std::chrono::seconds timeout = std::chrono::seconds(5));

  Result<void> PressPowerBtn();
  Result<void> PressPowerBtnLegacy();
  Result<void> Restart(std::chrono::seconds launcher_timeout,
                       std::chrono::seconds boot_timeout);
  Result<void> PowerWash(std::chrono::seconds launcher_timeout,
                         std::chrono::seconds boot_timeout);
  Result<std::vector<std::string>> ListRecordings();
  Result<void> StartRecording(std::chrono::seconds launcher_timeout);
  Result<void> StopRecording(std::chrono::seconds launcher_timeout);

  // Return list of filenames of instance-level log files.
  Result<std::vector<std::string>> LogsFilenames() const;

 private:
  LocalInstance(std::shared_ptr<cvd::InstanceGroup> group_proto,
                cvd::Instance* instance_proto);

  std::string config_file_path() const;
  Result<SharedFD> GetLauncherMonitor(std::chrono::seconds timeout) const;
  Result<Json::Value> ReadJsonConfig() const;
  Result<const CuttlefishConfig*> LoadConfig();
  Result<const CuttlefishConfig::InstanceSpecific> GetInstanceConfig();

  // Sharing ownership of the group proto ensures the instance proto reference
  // doesn't invalidate.
  std::shared_ptr<cvd::InstanceGroup> group_proto_;
  cvd::Instance* instance_proto_;
  // This may be null, access through LoadConfig() instead.
  std::shared_ptr<const CuttlefishConfig> UNSAFE_config_;
  friend class LocalInstanceGroup;
};

}  // namespace cuttlefish
