// Copyright 2018 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/services/app_service/app_service_impl.h"

#include <utility>

#include "base/bind.h"
#include "base/token.h"
#include "chrome/services/app_service/public/mojom/types.mojom.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"

namespace {

const char kAppServicePreferredApps[] = "app_service.preferred_apps";

void Connect(apps::mojom::Publisher* publisher,
             apps::mojom::Subscriber* subscriber) {
  mojo::PendingRemote<apps::mojom::Subscriber> clone;
  subscriber->Clone(clone.InitWithNewPipeAndPassReceiver());
  // TODO: replace nullptr with a ConnectOptions.
  publisher->Connect(std::move(clone), nullptr);
}

}  // namespace

namespace apps {

AppServiceImpl::AppServiceImpl(PrefService* profile_prefs)
    : pref_service_(profile_prefs) {
  DCHECK(pref_service_);
  InitializePreferredApps();
}

AppServiceImpl::~AppServiceImpl() = default;

// static
void AppServiceImpl::RegisterProfilePrefs(PrefRegistrySimple* registry) {
  registry->RegisterDictionaryPref(kAppServicePreferredApps);
}

void AppServiceImpl::BindReceiver(
    mojo::PendingReceiver<apps::mojom::AppService> receiver) {
  receivers_.Add(this, std::move(receiver));
}

void AppServiceImpl::FlushMojoCallsForTesting() {
  subscribers_.FlushForTesting();
  receivers_.FlushForTesting();
}

void AppServiceImpl::RegisterPublisher(
    mojo::PendingRemote<apps::mojom::Publisher> publisher_remote,
    apps::mojom::AppType app_type) {
  mojo::Remote<apps::mojom::Publisher> publisher(std::move(publisher_remote));
  // Connect the new publisher with every registered subscriber.
  for (auto& subscriber : subscribers_) {
    ::Connect(publisher.get(), subscriber.get());
  }

  // Check that no previous publisher has registered for the same app_type.
  CHECK(publishers_.find(app_type) == publishers_.end());

  // Add the new publisher to the set.
  publisher.set_disconnect_handler(
      base::BindOnce(&AppServiceImpl::OnPublisherDisconnected,
                     base::Unretained(this), app_type));
  auto result = publishers_.emplace(app_type, std::move(publisher));
  CHECK(result.second);
}

void AppServiceImpl::RegisterSubscriber(
    mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote,
    apps::mojom::ConnectOptionsPtr opts) {
  // Connect the new subscriber with every registered publisher.
  mojo::Remote<apps::mojom::Subscriber> subscriber(
      std::move(subscriber_remote));
  for (const auto& iter : publishers_) {
    ::Connect(iter.second.get(), subscriber.get());
  }

  // TODO: store the opts somewhere.

  // Initialise the Preferred Apps in the Subscribers on register.
  if (preferred_apps_.IsInitialized()) {
    subscriber->InitializePreferredApps(preferred_apps_.GetValue());
  }

  // Add the new subscriber to the set.
  subscribers_.Add(std::move(subscriber));
}

void AppServiceImpl::LoadIcon(apps::mojom::AppType app_type,
                              const std::string& app_id,
                              apps::mojom::IconKeyPtr icon_key,
                              apps::mojom::IconCompression icon_compression,
                              int32_t size_hint_in_dip,
                              bool allow_placeholder_icon,
                              LoadIconCallback callback) {
  auto iter = publishers_.find(app_type);
  if (iter == publishers_.end()) {
    std::move(callback).Run(apps::mojom::IconValue::New());
    return;
  }
  iter->second->LoadIcon(app_id, std::move(icon_key), icon_compression,
                         size_hint_in_dip, allow_placeholder_icon,
                         std::move(callback));
}

void AppServiceImpl::Launch(apps::mojom::AppType app_type,
                            const std::string& app_id,
                            int32_t event_flags,
                            apps::mojom::LaunchSource launch_source,
                            int64_t display_id) {
  auto iter = publishers_.find(app_type);
  if (iter == publishers_.end()) {
    return;
  }
  iter->second->Launch(app_id, event_flags, launch_source, display_id);
}

void AppServiceImpl::LaunchAppWithIntent(
    apps::mojom::AppType app_type,
    const std::string& app_id,
    apps::mojom::IntentPtr intent,
    apps::mojom::LaunchSource launch_source,
    int64_t display_id) {
  auto iter = publishers_.find(app_type);
  if (iter == publishers_.end()) {
    return;
  }
  iter->second->LaunchAppWithIntent(app_id, std::move(intent), launch_source,
                                    display_id);
}

void AppServiceImpl::SetPermission(apps::mojom::AppType app_type,
                                   const std::string& app_id,
                                   apps::mojom::PermissionPtr permission) {
  auto iter = publishers_.find(app_type);
  if (iter == publishers_.end()) {
    return;
  }
  iter->second->SetPermission(app_id, std::move(permission));
}

void AppServiceImpl::Uninstall(apps::mojom::AppType app_type,
                               const std::string& app_id,
                               bool clear_site_data,
                               bool report_abuse) {
  auto iter = publishers_.find(app_type);
  if (iter == publishers_.end()) {
    return;
  }
  iter->second->Uninstall(app_id, clear_site_data, report_abuse);
}

void AppServiceImpl::PauseApp(apps::mojom::AppType app_type,
                              const std::string& app_id) {
  auto iter = publishers_.find(app_type);
  if (iter == publishers_.end()) {
    return;
  }
  iter->second->PauseApp(app_id);
}

void AppServiceImpl::UnpauseApps(apps::mojom::AppType app_type,
                                 const std::string& app_id) {
  auto iter = publishers_.find(app_type);
  if (iter == publishers_.end()) {
    return;
  }
  iter->second->UnpauseApps(app_id);
}

void AppServiceImpl::GetMenuModel(apps::mojom::AppType app_type,
                                  const std::string& app_id,
                                  apps::mojom::MenuType menu_type,
                                  int64_t display_id,
                                  GetMenuModelCallback callback) {
  auto iter = publishers_.find(app_type);
  if (iter == publishers_.end()) {
    std::move(callback).Run(apps::mojom::MenuItems::New());
    return;
  }

  iter->second->GetMenuModel(app_id, menu_type, display_id,
                             std::move(callback));
}

void AppServiceImpl::OpenNativeSettings(apps::mojom::AppType app_type,
                                        const std::string& app_id) {
  auto iter = publishers_.find(app_type);
  if (iter == publishers_.end()) {
    return;
  }
  iter->second->OpenNativeSettings(app_id);
}

void AppServiceImpl::AddPreferredApp(apps::mojom::AppType app_type,
                                     const std::string& app_id,
                                     apps::mojom::IntentFilterPtr intent_filter,
                                     apps::mojom::IntentPtr intent,
                                     bool from_publisher) {
  DCHECK(preferred_apps_.IsInitialized());

  preferred_apps_.AddPreferredApp(app_id, intent_filter);

  DictionaryPrefUpdate update(pref_service_, kAppServicePreferredApps);
  DCHECK(PreferredApps::VerifyPreferredApps(update.Get()));
  apps::mojom::ReplacedAppPreferencesPtr replaced_app_preferences =
      PreferredApps::AddPreferredApp(app_id, intent_filter, update.Get());

  for (auto& subscriber : subscribers_) {
    subscriber->OnPreferredAppSet(app_id, intent_filter->Clone());
  }

  if (from_publisher || !intent) {
    return;
  }

  // Sync the change to publishers. Because |replaced_app_preference| can
  // be any app type, we should run this for all publishers. Currently
  // only implemented in ARC publisher.
  // TODO(crbug.com/853604): The |replaced_app_preference| can be really big,
  // update this logic to only call the relevant publisher for each app after
  // updating the storage structure.
  for (const auto& iter : publishers_) {
    iter.second->OnPreferredAppSet(app_id, std::move(intent_filter),
                                   std::move(intent),
                                   replaced_app_preferences->Clone());
  }
}

void AppServiceImpl::RemovePreferredApp(apps::mojom::AppType app_type,
                                        const std::string& app_id) {
  DCHECK(preferred_apps_.IsInitialized());

  preferred_apps_.DeleteAppId(app_id);

  DictionaryPrefUpdate update(pref_service_, kAppServicePreferredApps);
  DCHECK(PreferredApps::VerifyPreferredApps(update.Get()));
  PreferredApps::DeleteAppId(app_id, update.Get());
}

void AppServiceImpl::RemovePreferredAppForFilter(
    apps::mojom::AppType app_type,
    const std::string& app_id,
    apps::mojom::IntentFilterPtr intent_filter) {
  DCHECK(preferred_apps_.IsInitialized());

  preferred_apps_.DeletePreferredApp(app_id, intent_filter);

  DictionaryPrefUpdate update(pref_service_, kAppServicePreferredApps);
  DCHECK(PreferredApps::VerifyPreferredApps(update.Get()));
  PreferredApps::DeletePreferredApp(app_id, intent_filter, update.Get());

  for (auto& subscriber : subscribers_) {
    subscriber->OnPreferredAppRemoved(app_id, intent_filter->Clone());
  }
}

PreferredApps& AppServiceImpl::GetPreferredAppsForTesting() {
  return preferred_apps_;
}

void AppServiceImpl::OnPublisherDisconnected(apps::mojom::AppType app_type) {
  publishers_.erase(app_type);
}

void AppServiceImpl::InitializePreferredApps() {
  DCHECK(pref_service_);
  preferred_apps_.Init(
      pref_service_->GetDictionary(kAppServicePreferredApps)->CreateDeepCopy());
  for (auto& subscriber : subscribers_) {
    subscriber->InitializePreferredApps(preferred_apps_.GetValue());
  }
}

}  // namespace apps
