// Copyright 2018 The Chromium OS 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 "cecservice/cec_manager.h"

#include <algorithm>
#include <string>
#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/strings/string_util.h>

namespace cecservice {

namespace {
std::string PowerStatusToString(TvPowerStatus status) {
  switch (status) {
    case kTvPowerStatusError:
      return "error";
    case kTvPowerStatusAdapterNotConfigured:
      return "adapter not configured";
    case kTvPowerStatusNoTv:
      return "no TV";
    case kTvPowerStatusOn:
      return "on";
    case kTvPowerStatusStandBy:
      return "standby";
    case kTvPowerStatusToOn:
      return "to on";
    case kTvPowerStatusToStandBy:
      return "to standby";
    case kTvPowerStatusUnknown:
      return "unknown";
  }
}

std::string PowerStatusVectorToString(
    const std::vector<TvPowerStatus>& vector) {
  std::vector<std::string> strings;
  std::transform(vector.begin(), vector.end(), std::back_inserter(strings),
                 PowerStatusToString);
  return "[" + base::JoinString(strings, ", ") + "]";
}
}  // namespace

struct CecManager::TvPowerStatusResult {
  // Set to true if the response has been received from the device.
  bool received = false;

  // The actual power status received.
  TvPowerStatus power_status = kTvPowerStatusUnknown;
};

struct CecManager::TvsPowerStatusQuery {
  // Callback to invoke when all responses have been received.
  GetTvsPowerStatusCallback callback;
  // Device nodes the request has been sent to.
  std::map<base::FilePath, TvPowerStatusResult> responses;
};

CecManager::CecManager(const UdevFactory& udev_factory,
                       const CecDeviceFactory& cec_factory)
    : cec_factory_(cec_factory) {
  udev_ = udev_factory.Create(
      base::Bind(&CecManager::OnDeviceAdded, weak_factory_.GetWeakPtr()),
      base::Bind(&CecManager::OnDeviceRemoved, weak_factory_.GetWeakPtr()));
  LOG_IF(FATAL, !udev_) << "Failed to create udev";

  EnumerateAndAddExistingDevices();
}

CecManager::~CecManager() = default;

void CecManager::GetTvsPowerStatus(GetTvsPowerStatusCallback callback) {
  LOG(INFO) << "Received get TVs power status request";
  if (devices_.empty()) {
    std::move(callback).Run({});
    return;
  }

  TvsPowerStatusQuery query{std::move(callback)};

  for (auto& kv : devices_) {
    query.responses.insert(std::make_pair(kv.first, TvPowerStatusResult()));
  }

  QueryId id = next_query_id_++;
  tv_power_status_queries_.insert(std::make_pair(id, std::move(query)));

  for (auto& kv : devices_) {
    kv.second->GetTvPowerStatus(base::Bind(&CecManager::OnTvPowerResponse,
                                           weak_factory_.GetWeakPtr(), id,
                                           kv.first));
  }
}

void CecManager::SetWakeUp() {
  LOG(INFO) << "Received wake up request";
  for (auto& kv : devices_) {
    kv.second->SetWakeUp();
  }
}

void CecManager::SetStandBy() {
  LOG(INFO) << "Received standby request";
  for (auto& kv : devices_) {
    kv.second->SetStandBy();
  }
}

void CecManager::OnTvPowerResponse(QueryId id,
                                   base::FilePath device_path,
                                   TvPowerStatus result) {
  auto iterator = tv_power_status_queries_.find(id);
  CHECK(iterator != tv_power_status_queries_.end());

  TvsPowerStatusQuery& query = iterator->second;
  query.responses[device_path] = {true, result};

  if (MaybeRespondToTvsPowerStatusQuery(query)) {
    tv_power_status_queries_.erase(iterator);
  }
}

bool CecManager::MaybeRespondToTvsPowerStatusQuery(
    const TvsPowerStatusQuery& query) {
  std::vector<TvPowerStatus> result;
  for (auto& response : query.responses) {
    const TvPowerStatusResult& status = response.second;
    if (!status.received) {
      return false;
    }

    result.push_back(status.power_status);
  }

  LOG(INFO) << "Responding to power status request with: "
            << PowerStatusVectorToString(result);

  std::move(query.callback).Run(result);

  return true;
}

void CecManager::OnDeviceAdded(const base::FilePath& device_path) {
  LOG(INFO) << "New device: " << device_path.value();
  AddNewDevice(device_path);
}

void CecManager::OnDeviceRemoved(const base::FilePath& device_path) {
  LOG(INFO) << "Removing device: " << device_path.value();
  devices_.erase(device_path);

  auto iterator = tv_power_status_queries_.begin();
  while (iterator != tv_power_status_queries_.end()) {
    TvsPowerStatusQuery& query = iterator->second;
    query.responses.erase(device_path);

    if (MaybeRespondToTvsPowerStatusQuery(query)) {
      iterator = tv_power_status_queries_.erase(iterator);
    } else {
      ++iterator;
    }
  }
}

void CecManager::EnumerateAndAddExistingDevices() {
  std::vector<base::FilePath> paths;
  if (!udev_->EnumerateDevices(&paths)) {
    LOG(FATAL) << "Failed to enumerate devices.";
  }
  for (const auto& path : paths) {
    AddNewDevice(path);
  }
}

void CecManager::AddNewDevice(const base::FilePath& path) {
  std::unique_ptr<CecDevice> device = cec_factory_.Create(path);
  if (device) {
    LOG(INFO) << "Added new device: " << path.value();
    devices_[path] = std::move(device);
  } else {
    LOG(WARNING) << "Failed to add device: " << path.value();
  }
}

}  // namespace cecservice
