// Copyright (c) 2013 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 "power_manager/powerd/system/audio_client.h"

#include <algorithm>
#include <map>
#include <memory>

#include <base/bind.h>
#include <base/files/file_util.h>
#include <base/time/time.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/message.h>

#include "power_manager/common/util.h"
#include "power_manager/powerd/system/audio_observer.h"

namespace power_manager {
namespace system {

namespace {

// Maximum amount of time to wait for a reply from CRAS.
constexpr base::TimeDelta kCrasDBusTimeout = base::TimeDelta::FromSeconds(3);

}  // namespace

// static
constexpr char AudioClient::kTypeKey[];
constexpr char AudioClient::kActiveKey[];
constexpr char AudioClient::kHeadphoneNodeType[];
constexpr char AudioClient::kHdmiNodeType[];
constexpr char AudioClient::kAudioSuspendedFile[];

AudioClient::AudioClient() : weak_ptr_factory_(this) {}

AudioClient::~AudioClient() {
  if (dbus_wrapper_)
    dbus_wrapper_->RemoveObserver(this);
}

void AudioClient::Init(DBusWrapperInterface* dbus_wrapper,
                       const base::FilePath& run_dir) {
  DCHECK(dbus_wrapper);
  dbus_wrapper_ = dbus_wrapper;
  dbus_wrapper_->AddObserver(this);
  audio_suspended_path_ = run_dir.Append(kAudioSuspendedFile);

  cras_proxy_ = dbus_wrapper_->GetObjectProxy(cras::kCrasServiceName,
                                              cras::kCrasServicePath);
  dbus_wrapper_->RegisterForServiceAvailability(
      cras_proxy_, base::Bind(&AudioClient::HandleCrasAvailableOrRestarted,
                              weak_ptr_factory_.GetWeakPtr()));

  typedef void (AudioClient::*SignalMethod)(dbus::Signal*);
  const std::map<const char*, SignalMethod> kSignalMethods = {
      {cras::kNodesChanged, &AudioClient::HandleNodesChangedSignal},
      {cras::kActiveOutputNodeChanged,
       &AudioClient::HandleActiveOutputNodeChangedSignal},
      {cras::kNumberOfActiveStreamsChanged,
       &AudioClient::HandleNumberOfActiveStreamsChangedSignal},
      {cras::kAudioOutputActiveStateChanged,
       &AudioClient::HandleAudioOutputActiveStateChangedSignal},
  };
  for (const auto& it : kSignalMethods) {
    dbus_wrapper_->RegisterForSignal(
        cras_proxy_, cras::kCrasControlInterface, it.first,
        base::Bind(it.second, weak_ptr_factory_.GetWeakPtr()));
  }

  if (base::PathExists(audio_suspended_path_))
    SetSuspended(false);
}

bool AudioClient::GetHeadphoneJackPlugged() const {
  return headphone_jack_plugged_;
}

bool AudioClient::GetHdmiActive() const {
  return hdmi_active_;
}

void AudioClient::AddObserver(AudioObserver* observer) {
  DCHECK(observer);
  observers_.AddObserver(observer);
}

void AudioClient::RemoveObserver(AudioObserver* observer) {
  DCHECK(observer);
  observers_.RemoveObserver(observer);
}

void AudioClient::SetSuspended(bool suspended) {
  dbus::MethodCall method_call(cras::kCrasControlInterface,
                               cras::kSetSuspendAudio);
  dbus::MessageWriter writer(&method_call);
  writer.AppendBool(suspended);
  dbus_wrapper_->CallMethodSync(cras_proxy_, &method_call, kCrasDBusTimeout);
  if (suspended) {
    if (base::WriteFile(audio_suspended_path_, nullptr, 0) < 0)
      PLOG(ERROR) << "Couldn't create " << audio_suspended_path_.value();
  } else {
    if (!base::DeleteFile(audio_suspended_path_))
      PLOG(ERROR) << "Couldn't delete " << audio_suspended_path_.value();
  }
}

void AudioClient::OnDBusNameOwnerChanged(const std::string& service_name,
                                         const std::string& old_owner,
                                         const std::string& new_owner) {
  if (service_name == cras::kCrasServiceName && !new_owner.empty()) {
    LOG(INFO) << "D-Bus " << service_name << " ownership changed to "
              << new_owner;
    HandleCrasAvailableOrRestarted(true);
  }
}

bool AudioClient::IsAudioActive() const {
  return num_output_streams_ > 0 && output_active_;
}

void AudioClient::CallGetNodes() {
  dbus::MethodCall method_call(cras::kCrasControlInterface, cras::kGetNodes);
  dbus_wrapper_->CallMethodAsync(
      cras_proxy_, &method_call, kCrasDBusTimeout,
      base::Bind(&AudioClient::HandleGetNodesResponse,
                 weak_ptr_factory_.GetWeakPtr()));
}

void AudioClient::HandleGetNodesResponse(dbus::Response* response) {
  if (!response)
    return;

  const bool old_headphone_jack_plugged = headphone_jack_plugged_;
  const bool old_hdmi_active = hdmi_active_;

  headphone_jack_plugged_ = false;
  hdmi_active_ = false;

  // At the outer level, there's a dictionary corresponding to each audio node.
  dbus::MessageReader response_reader(response);
  dbus::MessageReader node_reader(nullptr);
  while (response_reader.PopArray(&node_reader)) {
    std::string type;
    bool active = false;

    // Iterate over the dictionary's entries.
    dbus::MessageReader property_reader(nullptr);
    while (node_reader.PopDictEntry(&property_reader)) {
      std::string key;
      if (!property_reader.PopString(&key)) {
        LOG(WARNING) << "Skipping dictionary entry with non-string key";
        continue;
      }
      if (key == kTypeKey) {
        if (!property_reader.PopVariantOfString(&type))
          LOG(WARNING) << kTypeKey << " key has non-string value";
      } else if (key == kActiveKey) {
        if (!property_reader.PopVariantOfBool(&active))
          LOG(WARNING) << kActiveKey << " key has non-bool value";
      }
    }

    VLOG(1) << "Saw node: type=" << type << " active=" << active;

    // The D-Bus interface doesn't return unplugged nodes.
    if (type == kHeadphoneNodeType)
      headphone_jack_plugged_ = true;
    else if (type == kHdmiNodeType && active)
      hdmi_active_ = true;
  }

  if (headphone_jack_plugged_ != old_headphone_jack_plugged ||
      hdmi_active_ != old_hdmi_active) {
    LOG(INFO) << "Updated audio devices: headphones "
              << (headphone_jack_plugged_ ? "" : "un") << "plugged, "
              << "HDMI " << (hdmi_active_ ? "" : "in") << "active";
  }
}

void AudioClient::CallGetNumberOfActiveOutputStreams() {
  dbus::MethodCall method_call(cras::kCrasControlInterface,
                               cras::kGetNumberOfActiveOutputStreams);
  dbus_wrapper_->CallMethodAsync(
      cras_proxy_, &method_call, kCrasDBusTimeout,
      base::Bind(&AudioClient::HandleGetNumberOfActiveOutputStreamsResponse,
                 weak_ptr_factory_.GetWeakPtr()));
}

void AudioClient::HandleGetNumberOfActiveOutputStreamsResponse(
    dbus::Response* response) {
  if (!response)
    return;

  int num_output_streams = 0;
  if (!dbus::MessageReader(response).PopInt32(&num_output_streams)) {
    LOG(WARNING) << "Unable to read " << cras::kGetNumberOfActiveOutputStreams
                 << " args";
    return;
  }

  VLOG(1) << "Output stream count changed to " << num_output_streams;
  UpdateAudioState(num_output_streams, output_active_);
}

void AudioClient::CallIsAudioOutputActive() {
  dbus::MethodCall method_call(cras::kCrasControlInterface,
                               cras::kIsAudioOutputActive);
  dbus_wrapper_->CallMethodAsync(
      cras_proxy_, &method_call, kCrasDBusTimeout,
      base::Bind(&AudioClient::HandleIsAudioOutputActiveResponse,
                 weak_ptr_factory_.GetWeakPtr()));
}

void AudioClient::HandleIsAudioOutputActiveResponse(dbus::Response* response) {
  if (!response)
    return;

  int32_t output_active = 0;
  if (!dbus::MessageReader(response).PopInt32(&output_active)) {
    LOG(WARNING) << "Unable to read " << cras::kIsAudioOutputActive << " args";
    return;
  }

  VLOG(1) << "Output-active state is " << output_active;
  UpdateAudioState(num_output_streams_, output_active > 0);
}

void AudioClient::HandleCrasAvailableOrRestarted(bool available) {
  if (!available) {
    LOG(ERROR) << "Failed waiting for CRAS to become available";
    return;
  }
  CallGetNodes();
  CallGetNumberOfActiveOutputStreams();
  CallIsAudioOutputActive();
}

void AudioClient::HandleNodesChangedSignal(dbus::Signal* signal) {
  CallGetNodes();
}

void AudioClient::HandleActiveOutputNodeChangedSignal(dbus::Signal* signal) {
  CallGetNodes();
}

void AudioClient::HandleNumberOfActiveStreamsChangedSignal(
    dbus::Signal* signal) {
  // The signal only contains the total count of streams (i.e. both input and
  // output), so we need to call the method to get the output stream count.
  CallGetNumberOfActiveOutputStreams();
}

void AudioClient::HandleAudioOutputActiveStateChangedSignal(
    dbus::Signal* signal) {
  bool output_active = false;
  if (!dbus::MessageReader(signal).PopBool(&output_active)) {
    LOG(WARNING) << "Failed to read " << cras::kAudioOutputActiveStateChanged
                 << " args";
    return;
  }

  VLOG(1) << "Output-active state changed to " << output_active;
  UpdateAudioState(num_output_streams_, output_active);
}

void AudioClient::UpdateAudioState(int num_output_streams, bool output_active) {
  const bool was_active = IsAudioActive();
  num_output_streams_ = num_output_streams;
  output_active_ = output_active;
  const bool is_active = IsAudioActive();

  if (is_active != was_active) {
    for (AudioObserver& observer : observers_)
      observer.OnAudioStateChange(is_active);
  }
}

}  // namespace system
}  // namespace power_manager
