// Copyright 2013 The Chromium 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 "chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.h"

#include "base/lazy_instance.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/strings/string_number_conversions.h"
#include "base/task_runner_util.h"
#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "content/public/browser/media_device_id.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/event_router.h"
#include "extensions/common/error_utils.h"
#include "media/audio/audio_manager_base.h"
#include "media/audio/audio_output_controller.h"

namespace extensions {

using content::BrowserThread;
using content::RenderViewHost;
using media::AudioDeviceNames;
using media::AudioManager;

namespace wap = api::webrtc_audio_private;

static base::LazyInstance<
    ProfileKeyedAPIFactory<WebrtcAudioPrivateEventService> > g_factory =
        LAZY_INSTANCE_INITIALIZER;

WebrtcAudioPrivateEventService::WebrtcAudioPrivateEventService(
    Profile* profile) : profile_(profile) {
  // In unit tests, the SystemMonitor may not be created.
  base::SystemMonitor* system_monitor = base::SystemMonitor::Get();
  if (system_monitor)
    system_monitor->AddDevicesChangedObserver(this);
}

WebrtcAudioPrivateEventService::~WebrtcAudioPrivateEventService() {
}

void WebrtcAudioPrivateEventService::Shutdown() {
  // In unit tests, the SystemMonitor may not be created.
  base::SystemMonitor* system_monitor = base::SystemMonitor::Get();
  if (system_monitor)
    system_monitor->RemoveDevicesChangedObserver(this);
}

// static
ProfileKeyedAPIFactory<WebrtcAudioPrivateEventService>*
WebrtcAudioPrivateEventService::GetFactoryInstance() {
  return &g_factory.Get();
}

// static
const char* WebrtcAudioPrivateEventService::service_name() {
  return "WebrtcAudioPrivateEventService";
}

void WebrtcAudioPrivateEventService::OnDevicesChanged(
    base::SystemMonitor::DeviceType device_type) {
  switch (device_type) {
    case base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE:
    case base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE:
      SignalEvent();
      break;

    default:
      // No action needed.
      break;
  }
}

void WebrtcAudioPrivateEventService::SignalEvent() {
  using api::webrtc_audio_private::OnSinksChanged::kEventName;

  EventRouter* router =
      ExtensionSystem::Get(profile_)->event_router();
  if (!router || !router->HasEventListener(kEventName))
    return;
  ExtensionService* extension_service =
      ExtensionSystem::Get(profile_)->extension_service();
  const ExtensionSet* extensions = extension_service->extensions();
  for (ExtensionSet::const_iterator it = extensions->begin();
       it != extensions->end(); ++it) {
    const std::string& extension_id = (*it)->id();
    if (router->ExtensionHasEventListener(extension_id, kEventName) &&
        (*it)->HasAPIPermission("webrtcAudioPrivate")) {
      scoped_ptr<Event> event(
          new Event(kEventName, make_scoped_ptr(new ListValue()).Pass()));
      router->DispatchEventToExtension(extension_id, event.Pass());
    }
  }
}

bool WebrtcAudioPrivateGetSinksFunction::RunImpl() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  AudioManager::Get()->GetMessageLoop()->PostTaskAndReply(
      FROM_HERE,
      base::Bind(&WebrtcAudioPrivateGetSinksFunction::DoQuery, this),
      base::Bind(&WebrtcAudioPrivateGetSinksFunction::DoneOnUIThread, this));
  return true;
}

void WebrtcAudioPrivateGetSinksFunction::DoQuery() {
  DCHECK(AudioManager::Get()->GetMessageLoop()->BelongsToCurrentThread());

  AudioDeviceNames device_names;
  AudioManager::Get()->GetAudioOutputDeviceNames(&device_names);

  std::vector<linked_ptr<wap::SinkInfo> > results;
  for (AudioDeviceNames::const_iterator it = device_names.begin();
       it != device_names.end();
       ++it) {
    linked_ptr<wap::SinkInfo> info(new wap::SinkInfo);
    info->sink_id = it->unique_id;
    info->sink_label = it->device_name;
    // TODO(joi): Add other parameters.
    results.push_back(info);
  }

  // It's safe to directly set the results here (from a thread other
  // than the UI thread, on which an AsyncExtensionFunction otherwise
  // normally runs) because there is one instance of this object per
  // function call, no actor outside of this object is modifying the
  // results_ member, and the different method invocations on this
  // object run strictly in sequence; first RunImpl on the UI thread,
  // then DoQuery on the audio IO thread, then DoneOnUIThread on the
  // UI thread.
  results_.reset(wap::GetSinks::Results::Create(results).release());
}

void WebrtcAudioPrivateGetSinksFunction::DoneOnUIThread() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  SendResponse(true);
}

bool WebrtcAudioPrivateTabIdFunction::DoRunImpl(int tab_id) {
  content::WebContents* contents = NULL;
  if (!ExtensionTabUtil::GetTabById(
           tab_id, GetProfile(), true, NULL, NULL, &contents, NULL)) {
    error_ = extensions::ErrorUtils::FormatErrorMessage(
        extensions::tabs_constants::kTabNotFoundError,
        base::IntToString(tab_id));
    return false;
  }

  RenderViewHost* rvh = contents->GetRenderViewHost();
  if (!rvh)
    return false;

  rvh->GetAudioOutputControllers(base::Bind(
      &WebrtcAudioPrivateTabIdFunction::OnControllerList, this));
  return true;
}

bool WebrtcAudioPrivateGetActiveSinkFunction::RunImpl() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  scoped_ptr<wap::GetActiveSink::Params> params(
      wap::GetActiveSink::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  return DoRunImpl(params->tab_id);
}

void WebrtcAudioPrivateGetActiveSinkFunction::OnControllerList(
    const RenderViewHost::AudioOutputControllerList& controllers) {
  if (controllers.empty()) {
    // If there is no current audio stream for the rvh, we return an
    // empty string as the sink ID.
    DVLOG(2) << "chrome.webrtcAudioPrivate.getActiveSink: No controllers.";
    results_.reset(
        wap::GetActiveSink::Results::Create(std::string()).release());
    SendResponse(true);
  } else {
    DVLOG(2) << "chrome.webrtcAudioPrivate.getActiveSink: "
             << controllers.size() << " controllers.";
    // TODO(joi): Debug-only, DCHECK that all items have the same ID.
    (*controllers.begin())->GetOutputDeviceId(
        base::Bind(&WebrtcAudioPrivateGetActiveSinkFunction::OnSinkId, this));
  }
}

void WebrtcAudioPrivateGetActiveSinkFunction::OnSinkId(const std::string& id) {
  std::string result = id;
  if (result.empty()) {
    DVLOG(2) << "Received empty ID, replacing with default ID.";
    result = media::AudioManagerBase::kDefaultDeviceId;
  }
  results_.reset(wap::GetActiveSink::Results::Create(result).release());
  SendResponse(true);
}

WebrtcAudioPrivateSetActiveSinkFunction::
WebrtcAudioPrivateSetActiveSinkFunction()
    : message_loop_(base::MessageLoopProxy::current()),
      tab_id_(0),
      num_remaining_sink_ids_(0) {
}

WebrtcAudioPrivateSetActiveSinkFunction::
~WebrtcAudioPrivateSetActiveSinkFunction() {
}

bool WebrtcAudioPrivateSetActiveSinkFunction::RunImpl() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  scoped_ptr<wap::SetActiveSink::Params> params(
      wap::SetActiveSink::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  tab_id_ = params->tab_id;
  sink_id_ = params->sink_id;

  if (sink_id_ == media::AudioManagerBase::kDefaultDeviceId) {
    DVLOG(2) << "Received default ID, replacing with empty ID.";
    sink_id_ = "";
  }

  return DoRunImpl(tab_id_);
}

void WebrtcAudioPrivateSetActiveSinkFunction::OnControllerList(
    const RenderViewHost::AudioOutputControllerList& controllers) {
  num_remaining_sink_ids_ = controllers.size();
  if (num_remaining_sink_ids_ == 0) {
    error_ = extensions::ErrorUtils::FormatErrorMessage(
        "No active stream for tab with id: *.",
        base::IntToString(tab_id_));
    SendResponse(false);
  } else {
    RenderViewHost::AudioOutputControllerList::const_iterator it =
        controllers.begin();
    for (; it != controllers.end(); ++it) {
      (*it)->SwitchOutputDevice(sink_id_, base::Bind(
          &WebrtcAudioPrivateSetActiveSinkFunction::SwitchDone, this));
    }
  }
}

void WebrtcAudioPrivateSetActiveSinkFunction::SwitchDone() {
  if (--num_remaining_sink_ids_ == 0) {
    message_loop_->PostTask(
        FROM_HERE,
        base::Bind(&WebrtcAudioPrivateSetActiveSinkFunction::DoneOnUIThread,
                   this));
  }
}

void WebrtcAudioPrivateSetActiveSinkFunction::DoneOnUIThread() {
  SendResponse(true);
}

WebrtcAudioPrivateGetAssociatedSinkFunction::
WebrtcAudioPrivateGetAssociatedSinkFunction() {
}

WebrtcAudioPrivateGetAssociatedSinkFunction::
~WebrtcAudioPrivateGetAssociatedSinkFunction() {
}

bool WebrtcAudioPrivateGetAssociatedSinkFunction::RunImpl() {
  params_ = wap::GetAssociatedSink::Params::Create(*args_);
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  EXTENSION_FUNCTION_VALIDATE(params_.get());

  AudioManager::Get()->GetMessageLoop()->PostTaskAndReply(
      FROM_HERE,
      base::Bind(&WebrtcAudioPrivateGetAssociatedSinkFunction::
                 GetDevicesOnDeviceThread, this),
      base::Bind(
          &WebrtcAudioPrivateGetAssociatedSinkFunction::OnGetDevicesDone,
          this));

  return true;
}

void WebrtcAudioPrivateGetAssociatedSinkFunction::GetDevicesOnDeviceThread() {
  DCHECK(AudioManager::Get()->GetMessageLoop()->BelongsToCurrentThread());
  AudioManager::Get()->GetAudioInputDeviceNames(&source_devices_);
}

void WebrtcAudioPrivateGetAssociatedSinkFunction::OnGetDevicesDone() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  BrowserThread::PostTaskAndReplyWithResult(
      BrowserThread::IO,
      FROM_HERE,
      base::Bind(&WebrtcAudioPrivateGetAssociatedSinkFunction::
                 GetRawSourceIDOnIOThread,
                 this,
                 GetProfile()->GetResourceContext(),
                 GURL(params_->security_origin),
                 params_->source_id_in_origin),
      base::Bind(
          &WebrtcAudioPrivateGetAssociatedSinkFunction::OnGetRawSourceIDDone,
          this));
}

std::string
WebrtcAudioPrivateGetAssociatedSinkFunction::GetRawSourceIDOnIOThread(
    content::ResourceContext* context,
    GURL security_origin,
    const std::string& source_id_in_origin) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  // Find the raw source ID for source_id_in_origin.
  std::string raw_source_id;
  for (AudioDeviceNames::const_iterator it = source_devices_.begin();
       it != source_devices_.end();
       ++it) {
    const std::string& id = it->unique_id;
    if (content::DoesMediaDeviceIDMatchHMAC(
            context->GetMediaDeviceIDSalt(),
            security_origin,
            source_id_in_origin,
            id)) {
      raw_source_id = id;
      DVLOG(2) << "Found raw ID " << raw_source_id
               << " for source ID in origin " << source_id_in_origin;
      break;
    }
  }

  return raw_source_id;
}

void WebrtcAudioPrivateGetAssociatedSinkFunction::OnGetRawSourceIDDone(
    const std::string& raw_source_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  base::PostTaskAndReplyWithResult(
      AudioManager::Get()->GetMessageLoop(),
      FROM_HERE,
      base::Bind(&WebrtcAudioPrivateGetAssociatedSinkFunction::
                 GetAssociatedSinkOnDeviceThread,
                 this,
                 raw_source_id),
      base::Bind(&WebrtcAudioPrivateGetAssociatedSinkFunction::
                 OnGetAssociatedSinkDone,
                 this));
}

std::string
WebrtcAudioPrivateGetAssociatedSinkFunction::GetAssociatedSinkOnDeviceThread(
    const std::string& raw_source_id) {
  DCHECK(AudioManager::Get()->GetMessageLoop()->BelongsToCurrentThread());

  // We return an empty string if there is no associated output device.
  std::string result;
  if (!raw_source_id.empty()) {
    result = AudioManager::Get()->GetAssociatedOutputDeviceID(raw_source_id);
  }

  return result;
}

void WebrtcAudioPrivateGetAssociatedSinkFunction::OnGetAssociatedSinkDone(
    const std::string& associated_sink_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  results_.reset(
      wap::GetAssociatedSink::Results::Create(associated_sink_id).release());
  SendResponse(true);
}

}  // namespace extensions
