// 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_device.h"

#include <fcntl.h>
#include <linux/cec-funcs.h>
#include <poll.h>
#include <string.h>

#include <utility>

#include <base/bind.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <base/strings/string_util.h>

namespace cecservice {

namespace {
struct cec_msg CreateMessage(uint16_t destination_address) {
  struct cec_msg message;
  cec_msg_init(&message, CEC_LOG_ADDR_UNREGISTERED, destination_address);
  return message;
}

void SetMessageSourceAddress(uint16_t source_address, struct cec_msg* msg) {
  if (source_address == CEC_LOG_ADDR_INVALID) {
    source_address = CEC_LOG_ADDR_UNREGISTERED;
  }
  msg->msg[0] = (source_address << 4) | cec_msg_destination(msg);
}

TvPowerStatus GetPowerStatus(const struct cec_msg& msg) {
  uint8_t power_status;
  cec_ops_report_power_status(&msg, &power_status);
  switch (power_status) {
    case CEC_OP_POWER_STATUS_ON:
      return kTvPowerStatusOn;
    case CEC_OP_POWER_STATUS_STANDBY:
      return kTvPowerStatusStandBy;
    case CEC_OP_POWER_STATUS_TO_ON:
      return kTvPowerStatusToOn;
    case CEC_OP_POWER_STATUS_TO_STANDBY:
      return kTvPowerStatusToStandBy;
    default:
      return kTvPowerStatusUnknown;
  }
}
}  // namespace

CecDeviceImpl::CecDeviceImpl(std::unique_ptr<CecFd> fd,
                             const base::FilePath& device_path)
    : fd_(std::move(fd)), device_path_(device_path) {}

CecDeviceImpl::~CecDeviceImpl() = default;

bool CecDeviceImpl::Init() {
  if (!fd_->SetEventCallback(
          base::Bind(&CecDeviceImpl::OnFdEvent, weak_factory_.GetWeakPtr()))) {
    DisableDevice();
    return false;
  }
  return true;
}

void CecDeviceImpl::GetTvPowerStatus(GetTvPowerStatusCallback callback) {
  if (!fd_) {
    LOG(WARNING) << device_path_.value()
                 << ": device is disabled due to errors, unable to query";
    std::move(callback).Run(kTvPowerStatusError);
    return;
  }

  if (GetState() == State::kStart) {
    LOG(INFO) << device_path_.value()
              << ": not configured, not querying TV power state";
    std::move(callback).Run(kTvPowerStatusAdapterNotConfigured);
    return;
  }

  struct cec_msg message = CreateMessage(CEC_LOG_ADDR_TV);
  cec_msg_give_device_power_status(&message, 1);
  message_queue_.push_back(message);

  requests_.push_back({std::move(callback), 0});

  RequestWriteWatch();
}

void CecDeviceImpl::SetStandBy() {
  if (!fd_) {
    LOG(WARNING) << device_path_.value()
                 << ": device is disabled due to previous errors, ignoring "
                    "standby request";
    return;
  }

  if (GetState() == State::kStart) {
    LOG(INFO) << device_path_.value()
              << ": ignoring standby request, we are not connected";
    return;
  }

  active_source_ = false;

  struct cec_msg message = CreateMessage(CEC_LOG_ADDR_TV);
  cec_msg_standby(&message);
  message_queue_.push_back(message);

  RequestWriteWatch();
}

void CecDeviceImpl::SetWakeUp() {
  if (!fd_) {
    LOG(WARNING)
        << device_path_.value()
        << ": device in disabled due to previous errors, ignoring wake "
           "up request";
    return;
  }

  struct cec_msg image_view_on_message = CreateMessage(CEC_LOG_ADDR_TV);
  cec_msg_image_view_on(&image_view_on_message);

  switch (GetState()) {
    case State::kReady: {
      message_queue_.push_back(image_view_on_message);

      struct cec_msg active_source_message =
          CreateMessage(CEC_LOG_ADDR_BROADCAST);
      cec_msg_active_source(&active_source_message, physical_address_);
      message_queue_.push_back(active_source_message);
    } break;
    case State::kStart:
      if (SendMessage(&image_view_on_message) == CecFd::TransmitResult::kOk) {
        pending_active_source_broadcast_ = true;
      } else {
        LOG(WARNING) << device_path_.value()
                     << ": failed to send image view on message while in start "
                        "state, we are not able to wake up this TV";
        return;
      }
      break;
    case State::kNoLogicalAddress:
      message_queue_.push_back(image_view_on_message);
      pending_active_source_broadcast_ = true;
      break;
  }
  active_source_ = true;

  RequestWriteWatch();
}

void CecDeviceImpl::RequestWriteWatch() {
  if (message_queue_.empty()) {
    return;
  }

  if (!fd_->WriteWatch()) {
    LOG(ERROR) << device_path_.value()
               << ": failed to request write watch on fd, disabling device";
    DisableDevice();
  }
}

CecDeviceImpl::State CecDeviceImpl::GetState() const {
  if (physical_address_ == CEC_PHYS_ADDR_INVALID) {
    return State::kStart;
  }
  if (logical_address_ == CEC_LOG_ADDR_INVALID) {
    return State::kNoLogicalAddress;
  }
  return State::kReady;
}

CecDeviceImpl::State CecDeviceImpl::UpdateState(
    const struct cec_event_state_change& event) {
  physical_address_ = event.phys_addr;
  logical_address_ = CEC_LOG_ADDR_INVALID;

  if (event.log_addr_mask) {
    logical_address_ = ffs(event.log_addr_mask) - 1;
  }

  VLOG(1) << base::StringPrintf(
      "%s: state update, physical address: 0x%x logical address: 0x%x",
      device_path_.value().c_str(), static_cast<uint32_t>(physical_address_),
      static_cast<uint32_t>(logical_address_));

  return GetState();
}

bool CecDeviceImpl::ProcessMessagesLostEvent(
    const struct cec_event_lost_msgs& event) {
  LOG(WARNING) << device_path_.value() << ": received event lost message, lost "
               << event.lost_msgs << " messages";
  return true;
}

bool CecDeviceImpl::ProcessStateChangeEvent(
    const struct cec_event_state_change& event) {
  switch (UpdateState(event)) {
    case State::kNoLogicalAddress:
      return SetLogicalAddress();
    case State::kStart:
      RespondToAllPendingQueries(kTvPowerStatusAdapterNotConfigured);
      message_queue_.clear();
      return true;
    case State::kReady:
      if (pending_active_source_broadcast_) {
        struct cec_msg message = CreateMessage(CEC_LOG_ADDR_BROADCAST);
        cec_msg_active_source(&message, physical_address_);
        message_queue_.push_back(message);

        pending_active_source_broadcast_ = false;
      }
      return true;
  }
}

bool CecDeviceImpl::ProcessEvents() {
  struct cec_event event;

  if (!fd_->ReceiveEvent(&event)) {
    return false;
  }

  switch (event.event) {
    case CEC_EVENT_LOST_MSGS:
      return ProcessMessagesLostEvent(event.lost_msgs);
      break;
    case CEC_EVENT_STATE_CHANGE:
      return ProcessStateChangeEvent(event.state_change);
    default:
      LOG(WARNING) << base::StringPrintf("%s: unexpected cec event type: 0x%x",
                                         device_path_.value().c_str(),
                                         event.event);
      return true;
  }
}

bool CecDeviceImpl::ProcessRead() {
  struct cec_msg msg;
  if (!fd_->ReceiveMessage(&msg)) {
    return false;
  }

  if (msg.sequence) {
    ProcessSentMessage(msg);
  } else {
    ProcessIncomingMessage(&msg);
  }
  return true;
}

bool CecDeviceImpl::ProcessWrite() {
  if (message_queue_.empty()) {
    return true;
  }

  struct cec_msg message = message_queue_.front();
  const CecFd::TransmitResult ret = SendMessage(&message);
  if (ret == CecFd::TransmitResult::kWouldBlock) {
    return true;
  }

  if (cec_msg_opcode(&message) == CEC_MSG_GIVE_DEVICE_POWER_STATUS) {
    auto iterator = std::find_if(requests_.begin(), requests_.end(),
                                 [](const RequestInFlight& request) {
                                   return request.sequence_id == 0;
                                 });
    CHECK(iterator != requests_.end());

    if (ret == CecFd::TransmitResult::kOk) {
      iterator->sequence_id = message.sequence;
    } else {
      std::move(iterator->callback).Run(kTvPowerStatusError);
      requests_.erase(iterator);
    }
  }

  message_queue_.pop_front();
  return ret != CecFd::TransmitResult::kError;
}

bool CecDeviceImpl::ProcessPowerStatusResponse(const struct cec_msg& msg) {
  auto iterator = std::find_if(requests_.begin(), requests_.end(),
                               [&](const RequestInFlight& request) {
                                 return request.sequence_id == msg.sequence;
                               });
  if (iterator == requests_.end()) {
    return false;
  }

  TvPowerStatus status;
  if (cec_msg_status_is_ok(&msg)) {
    status = GetPowerStatus(msg);
  } else {
    VLOG(1) << base::StringPrintf(
        "%s: power status query failed, rx_status: 0x%x tx_status: 0x%x",
        device_path_.value().c_str(), static_cast<uint32_t>(msg.rx_status),
        static_cast<uint32_t>(msg.tx_status));
    if (msg.tx_status & CEC_TX_STATUS_NACK) {
      status = kTvPowerStatusNoTv;
    } else {
      status = kTvPowerStatusError;
    }
  }

  std::move(iterator->callback).Run(status);
  requests_.erase(iterator);

  return true;
}

void CecDeviceImpl::ProcessSentMessage(const struct cec_msg& msg) {
  if (ProcessPowerStatusResponse(msg)) {
    return;
  }

  if (cec_msg_status_is_ok(&msg)) {
    VLOG(1) << base::StringPrintf("%s: successfully sent message, opcode: 0x%x",
                                  device_path_.value().c_str(),
                                  cec_msg_opcode(&msg));
  } else {
    LOG(WARNING) << base::StringPrintf(
        "%s: failed to send message, opcode: 0x%x tx_status: 0x%x",
        device_path_.value().c_str(), cec_msg_opcode(&msg),
        static_cast<uint32_t>(msg.tx_status));
  }
}

void CecDeviceImpl::ProcessIncomingMessage(struct cec_msg* msg) {
  struct cec_msg reply;

  VLOG(1) << base::StringPrintf(
      "%s: received message, opcode:0x%x from:0x%x to:0x%x",
      device_path_.value().c_str(), cec_msg_opcode(msg),
      static_cast<unsigned>(cec_msg_initiator(msg)),
      static_cast<unsigned>(cec_msg_destination(msg)));

  switch (cec_msg_opcode(msg)) {
    case CEC_MSG_REQUEST_ACTIVE_SOURCE:
      if (active_source_) {
        cec_msg_init(&reply, logical_address_, CEC_LOG_ADDR_BROADCAST);
        cec_msg_active_source(&reply, physical_address_);
        message_queue_.push_back(std::move(reply));
      }
      break;
    case CEC_MSG_ACTIVE_SOURCE:
      if (active_source_) {
        VLOG(1) << device_path_.value() << ": we ceased to be active source";
        active_source_ = false;
      }
      break;
    case CEC_MSG_GIVE_DEVICE_POWER_STATUS:
      cec_msg_init(&reply, logical_address_, cec_msg_initiator(msg));
      cec_msg_report_power_status(&reply, CEC_OP_POWER_STATUS_ON);
      message_queue_.push_back(reply);
      break;
    case CEC_MSG_STANDBY:
      // Ignore standby.
      break;
    default:
      if (!cec_msg_is_broadcast(msg)) {
        cec_msg_reply_feature_abort(msg, CEC_OP_ABORT_UNRECOGNIZED_OP);
        message_queue_.push_back(std::move(*msg));
      }
      break;
  }
}

CecFd::TransmitResult CecDeviceImpl::SendMessage(struct cec_msg* msg) {
  VLOG(1) << base::StringPrintf(
      "%s: transmitting message, opcode:0x%x to:0x%x",
      device_path_.value().c_str(), cec_msg_opcode(msg),
      static_cast<unsigned>(cec_msg_destination(msg)));

  SetMessageSourceAddress(logical_address_, msg);
  return fd_->TransmitMessage(msg);
}

bool CecDeviceImpl::SetLogicalAddress() {
  struct cec_log_addrs addresses = {};

  if (!fd_->GetLogicalAddresses(&addresses)) {
    return false;
  }

  // The address has already been set, so we will reuse it.
  if (addresses.num_log_addrs) {
    return true;
  }

  memset(&addresses, 0, sizeof(addresses));
  addresses.cec_version = CEC_OP_CEC_VERSION_1_4;
  addresses.vendor_id = CEC_VENDOR_ID_NONE;
  base::strlcpy(addresses.osd_name, "Chrome OS", sizeof(addresses.osd_name));
  addresses.num_log_addrs = 1;
  addresses.log_addr_type[0] = CEC_LOG_ADDR_TYPE_PLAYBACK;
  addresses.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_PLAYBACK;
  addresses.all_device_types[0] = CEC_OP_ALL_DEVTYPE_PLAYBACK;
  addresses.flags = CEC_LOG_ADDRS_FL_ALLOW_UNREG_FALLBACK;

  return fd_->SetLogicalAddresses(&addresses);
}

void CecDeviceImpl::OnFdEvent(CecFd::EventType event) {
  if (!fd_) {
    return;
  }

  bool ret;
  switch (event) {
    case CecFd::EventType::kPriorityRead:
      ret = ProcessEvents();
      break;
    case CecFd::EventType::kRead:
      ret = ProcessRead();
      break;
    case CecFd::EventType::kWrite:
      ret = ProcessWrite();
      break;
  }

  if (!ret) {
    DisableDevice();
    return;
  }

  RequestWriteWatch();
}

void CecDeviceImpl::RespondToAllPendingQueries(TvPowerStatus response) {
  std::list<RequestInFlight> requests;
  requests.swap(requests_);

  for (auto& request : requests) {
    std::move(request.callback).Run(response);
  }
}

void CecDeviceImpl::DisableDevice() {
  fd_.reset();

  RespondToAllPendingQueries(kTvPowerStatusError);
}

CecDeviceFactoryImpl::CecDeviceFactoryImpl(const CecFdOpener* cec_fd_opener)
    : cec_fd_opener_(cec_fd_opener) {}

CecDeviceFactoryImpl::~CecDeviceFactoryImpl() = default;

std::unique_ptr<CecDevice> CecDeviceFactoryImpl::Create(
    const base::FilePath& path) const {
  std::unique_ptr<CecFd> fd = cec_fd_opener_->Open(path, O_NONBLOCK);
  if (!fd) {
    return nullptr;
  }

  struct cec_caps caps;
  if (!fd->GetCapabilities(&caps)) {
    return nullptr;
  }

  LOG(INFO) << base::StringPrintf(
      "CEC adapter: %s, driver:%s name:%s caps:0x%x", path.value().c_str(),
      caps.driver, caps.name, caps.capabilities);

  // At the moment the only adapters supported are the ones that:
  // - handle configuration of physical address on their own (i.e. don't have
  // CEC_CAP_PHYS_ADDR flag set)
  // - allow us to configure logical addrresses (i.e. have CEC_CAP_LOG_ADDRS
  // set)
  if ((caps.capabilities & CEC_CAP_PHYS_ADDR) ||
      !(caps.capabilities & CEC_CAP_LOG_ADDRS)) {
    LOG(WARNING) << path.value()
                 << ": device does not have required capabilities to function "
                    "with this service";
    return nullptr;
  }

  uint32_t mode = CEC_MODE_EXCL_INITIATOR | CEC_MODE_EXCL_FOLLOWER;
  if (!fd->SetMode(mode)) {
    LOG(ERROR) << path.value()
               << ": failed to set an exclusive initiator mode on the device";
    return nullptr;
  }

  auto device = std::make_unique<CecDeviceImpl>(std::move(fd), path);
  if (!device->Init()) {
    return nullptr;
  }

  return device;
}

}  // namespace cecservice
