// Copyright (c) 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 "extensions/browser/api/audio/audio_api.h"

#include <utility>

#include "base/lazy_instance.h"
#include "base/memory/ptr_util.h"
#include "base/values.h"
#include "components/prefs/pref_registry_simple.h"
#include "extensions/browser/api/audio/audio_device_id_calculator.h"
#include "extensions/browser/api/audio/pref_names.h"
#include "extensions/browser/event_router.h"
#include "extensions/common/api/audio.h"
#include "extensions/common/extension.h"
#include "extensions/common/features/behavior_feature.h"
#include "extensions/common/features/feature_provider.h"

namespace extensions {

namespace audio = api::audio;

namespace {

std::unique_ptr<AudioDeviceIdCalculator> CreateIdCalculator(
    content::BrowserContext* context) {
  return std::make_unique<AudioDeviceIdCalculator>(context);
}

// Checks if an extension is whitelisted to use deprecated version of audio API.
// TODO(tbarzic): Retire this whitelist and remove the deprecated API methods,
//     properties and events. This is currently targeted for M-60
//     (http://crbug.com/697279).
bool CanUseDeprecatedAudioApi(const Extension* extension) {
  if (!extension)
    return false;

  const Feature* allow_deprecated_audio_api_feature =
      FeatureProvider::GetBehaviorFeatures()->GetFeature(
          behavior_feature::kAllowDeprecatedAudioApi);
  if (!allow_deprecated_audio_api_feature)
    return false;

  return allow_deprecated_audio_api_feature->IsAvailableToExtension(extension)
      .is_available();
}

bool CanReceiveDeprecatedAudioEvent(content::BrowserContext* context,
                                    const Extension* extension,
                                    Event* event,
                                    const base::DictionaryValue* filter) {
  return CanUseDeprecatedAudioApi(extension);
}

}  // namespace

static base::LazyInstance<
    BrowserContextKeyedAPIFactory<AudioAPI>>::DestructorAtExit g_factory =
    LAZY_INSTANCE_INITIALIZER;

void AudioAPI::RegisterUserPrefs(PrefRegistrySimple* registry) {
  registry->RegisterListPref(kAudioApiStableDeviceIds);
}

// static
BrowserContextKeyedAPIFactory<AudioAPI>* AudioAPI::GetFactoryInstance() {
  return g_factory.Pointer();
}

AudioAPI::AudioAPI(content::BrowserContext* context)
    : browser_context_(context),
      stable_id_calculator_(CreateIdCalculator(context)),
      service_(AudioService::CreateInstance(stable_id_calculator_.get())),
      audio_service_observer_(this) {
  audio_service_observer_.Add(service_.get());
}

AudioAPI::~AudioAPI() {}

AudioService* AudioAPI::GetService() const {
  return service_.get();
}

void AudioAPI::OnDeviceChanged() {
  EventRouter* event_router = EventRouter::Get(browser_context_);
  if (!event_router)
    return;

  std::unique_ptr<Event> event(new Event(
      events::AUDIO_ON_DEVICE_CHANGED, audio::OnDeviceChanged::kEventName,
      std::unique_ptr<base::ListValue>(new base::ListValue())));
  event->will_dispatch_callback = base::Bind(&CanReceiveDeprecatedAudioEvent);
  event_router->BroadcastEvent(std::move(event));
}

void AudioAPI::OnLevelChanged(const std::string& id, int level) {
  EventRouter* event_router = EventRouter::Get(browser_context_);
  if (!event_router)
    return;

  audio::LevelChangedEvent raw_event;
  raw_event.device_id = id;
  raw_event.level = level;

  std::unique_ptr<base::ListValue> event_args =
      audio::OnLevelChanged::Create(raw_event);
  std::unique_ptr<Event> event(new Event(events::AUDIO_ON_LEVEL_CHANGED,
                                         audio::OnLevelChanged::kEventName,
                                         std::move(event_args)));
  event_router->BroadcastEvent(std::move(event));
}

void AudioAPI::OnMuteChanged(bool is_input, bool is_muted) {
  EventRouter* event_router = EventRouter::Get(browser_context_);
  if (!event_router)
    return;

  // Dispatch onMuteChanged event.
  audio::MuteChangedEvent raw_event;
  raw_event.stream_type =
      is_input ? audio::STREAM_TYPE_INPUT : audio::STREAM_TYPE_OUTPUT;
  raw_event.is_muted = is_muted;
  std::unique_ptr<base::ListValue> event_args =
      audio::OnMuteChanged::Create(raw_event);
  std::unique_ptr<Event> event(new Event(events::AUDIO_ON_MUTE_CHANGED,
                                         audio::OnMuteChanged::kEventName,
                                         std::move(event_args)));
  event_router->BroadcastEvent(std::move(event));
}

void AudioAPI::OnDevicesChanged(const DeviceInfoList& devices) {
  EventRouter* event_router = EventRouter::Get(browser_context_);
  if (!event_router)
    return;

  std::unique_ptr<base::ListValue> args =
      audio::OnDeviceListChanged::Create(devices);
  std::unique_ptr<Event> event(new Event(events::AUDIO_ON_DEVICES_CHANGED,
                                         audio::OnDeviceListChanged::kEventName,
                                         std::move(args)));
  event_router->BroadcastEvent(std::move(event));
}

///////////////////////////////////////////////////////////////////////////////

ExtensionFunction::ResponseAction AudioGetInfoFunction::Run() {
  if (!CanUseDeprecatedAudioApi(extension())) {
    return RespondNow(
        Error("audio.getInfo is deprecated, use audio.getDevices instead."));
  }

  AudioService* service =
      AudioAPI::GetFactoryInstance()->Get(browser_context())->GetService();
  DCHECK(service);
  OutputInfo output_info;
  InputInfo input_info;
  if (!service->GetInfo(&output_info, &input_info)) {
    return RespondNow(
        Error("Error occurred when querying audio device information."));
  }

  return RespondNow(
      ArgumentList(audio::GetInfo::Results::Create(output_info, input_info)));
}

///////////////////////////////////////////////////////////////////////////////

ExtensionFunction::ResponseAction AudioGetDevicesFunction::Run() {
  std::unique_ptr<audio::GetDevices::Params> params(
      audio::GetDevices::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  AudioService* service =
      AudioAPI::GetFactoryInstance()->Get(browser_context())->GetService();
  DCHECK(service);

  std::vector<api::audio::AudioDeviceInfo> devices;
  if (!service->GetDevices(params->filter.get(), &devices)) {
    return RespondNow(
        Error("Error occurred when querying audio device information."));
  }

  return RespondNow(ArgumentList(audio::GetDevices::Results::Create(devices)));
}

///////////////////////////////////////////////////////////////////////////////

ExtensionFunction::ResponseAction AudioSetActiveDevicesFunction::Run() {
  std::unique_ptr<audio::SetActiveDevices::Params> params(
      audio::SetActiveDevices::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  AudioService* service =
      AudioAPI::GetFactoryInstance()->Get(browser_context())->GetService();
  DCHECK(service);

  if (params->ids.as_device_id_lists) {
    if (!service->SetActiveDeviceLists(
            params->ids.as_device_id_lists->input,
            params->ids.as_device_id_lists->output)) {
      return RespondNow(Error("Failed to set active devices."));
    }
  } else if (params->ids.as_strings) {
    if (!CanUseDeprecatedAudioApi(extension())) {
      return RespondNow(
          Error("String list |ids| is deprecated, use DeviceIdLists type."));
    }
    service->SetActiveDevices(*params->ids.as_strings);
  }
  return RespondNow(NoArguments());
}

///////////////////////////////////////////////////////////////////////////////

ExtensionFunction::ResponseAction AudioSetPropertiesFunction::Run() {
  std::unique_ptr<audio::SetProperties::Params> params(
      audio::SetProperties::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  AudioService* service =
      AudioAPI::GetFactoryInstance()->Get(browser_context())->GetService();
  DCHECK(service);

  if (!CanUseDeprecatedAudioApi(extension())) {
    if (params->properties.volume)
      return RespondNow(Error("|volume| property is deprecated, use |level|."));

    if (params->properties.gain)
      return RespondNow(Error("|gain| property is deprecated, use |level|."));

    if (params->properties.is_muted) {
      return RespondNow(
          Error("|isMuted| property is deprecated, use |audio.setMute|."));
    }
  }

  bool level_set = !!params->properties.level;
  int level_value = level_set ? *params->properties.level : -1;

  int volume_value = params->properties.volume.get() ?
      *params->properties.volume : -1;

  int gain_value = params->properties.gain.get() ?
      *params->properties.gain : -1;

  // |volume_value| and |gain_value| are deprecated in favor of |level_value|;
  // they are kept around only to ensure backward-compatibility and should be
  // ignored if |level_value| is set.
  if (!service->SetDeviceSoundLevel(params->id,
                                    level_set ? level_value : volume_value,
                                    level_set ? level_value : gain_value))
    return RespondNow(Error("Could not set volume/gain properties"));

  if (params->properties.is_muted.get() &&
      !service->SetMuteForDevice(params->id, *params->properties.is_muted)) {
    return RespondNow(Error("Could not set mute property."));
  }

  return RespondNow(NoArguments());
}

///////////////////////////////////////////////////////////////////////////////

ExtensionFunction::ResponseAction AudioSetMuteFunction::Run() {
  std::unique_ptr<audio::SetMute::Params> params(
      audio::SetMute::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  AudioService* service =
      AudioAPI::GetFactoryInstance()->Get(browser_context())->GetService();
  DCHECK(service);

  if (!service->SetMute(params->stream_type == audio::STREAM_TYPE_INPUT,
                        params->is_muted)) {
    return RespondNow(Error("Could not set mute state."));
  }
  return RespondNow(NoArguments());
}

///////////////////////////////////////////////////////////////////////////////

ExtensionFunction::ResponseAction AudioGetMuteFunction::Run() {
  std::unique_ptr<audio::GetMute::Params> params(
      audio::GetMute::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  AudioService* service =
      AudioAPI::GetFactoryInstance()->Get(browser_context())->GetService();
  DCHECK(service);

  bool value = false;
  if (!service->GetMute(params->stream_type == audio::STREAM_TYPE_INPUT,
                        &value)) {
    return RespondNow(Error("Could not get mute state."));
  }
  return RespondNow(ArgumentList(audio::GetMute::Results::Create(value)));
}

}  // namespace extensions
