// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/extensions/extension_post_install_dialog_model.h"

#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/extensions/commands/command_service.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/sync/extension_sync_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/signin_promo_util.h"
#include "chrome/common/extensions/api/omnibox/omnibox_handler.h"
#include "chrome/grit/generated_resources.h"
#include "components/prefs/pref_service.h"
#include "components/signin/public/base/signin_pref_names.h"
#include "extensions/buildflags/buildflags.h"
#include "extensions/common/api/extension_action/action_info.h"
#include "extensions/common/command.h"
#include "extensions/common/extension.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/image/image_skia_operations.h"

static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE));

namespace {

std::optional<extensions::Command> CommandForExtensionAction(
    const extensions::Extension* extension,
    Profile* profile) {
  const auto* info = extensions::ActionInfo::GetExtensionActionInfo(extension);

  if (!info) {
    return std::nullopt;
  }

  auto* service = extensions::CommandService::Get(profile);
  extensions::Command command;

  if (service->GetExtensionActionCommand(extension->id(), info->type,
                                         extensions::CommandService::ACTIVE,
                                         &command, nullptr)) {
    return command;
  }

  return std::nullopt;
}

std::u16string MakeHowToUseText(const extensions::ActionInfo* action,
                                std::optional<extensions::Command> command,
                                const std::string& keyword) {
  std::u16string extra;
  if (command.has_value()) {
    extra = command->accelerator().GetShortcutText();
  }

  // TODO(crbug.com/405148986): This returns an empty string for MV3 extensions
  // which specify the "action" key in the manifest since
  // ActionInfo::Type::kAction is not handled. Add the appropriate string here.
  int message_id = 0;
  if (action && action->type == extensions::ActionInfo::Type::kBrowser) {
    message_id =
        extra.empty()
            ? IDS_EXTENSION_INSTALLED_BROWSER_ACTION_INFO
            : IDS_EXTENSION_INSTALLED_BROWSER_ACTION_INFO_WITH_SHORTCUT;
  } else if (action && action->type == extensions::ActionInfo::Type::kPage) {
    message_id = extra.empty()
                     ? IDS_EXTENSION_INSTALLED_PAGE_ACTION_INFO
                     : IDS_EXTENSION_INSTALLED_PAGE_ACTION_INFO_WITH_SHORTCUT;
  } else if (!keyword.empty()) {
    extra = base::UTF8ToUTF16(keyword);
    message_id = IDS_EXTENSION_INSTALLED_OMNIBOX_KEYWORD_INFO;
  }

  if (!message_id) {
    return std::u16string();
  }

  return extra.empty() ? l10n_util::GetStringUTF16(message_id)
                       : l10n_util::GetStringFUTF16(message_id, extra);
}

}  // namespace

ExtensionPostInstallDialogModel::ExtensionPostInstallDialogModel(
    Profile* profile,
    const extensions::Extension* extension,
    const SkBitmap& icon)
    : icon_(icon),
      extension_id_(extension->id()),
      extension_name_(extension->name()) {
  const std::string& keyword = extensions::OmniboxInfo::GetKeyword(extension);
  std::optional<extensions::Command> command =
      CommandForExtensionAction(extension, profile);
  const auto* action_info =
      extensions::ActionInfo::GetExtensionActionInfo(extension);

  const bool toolbar_action = !!action_info;

  show_how_to_use_ =
      (toolbar_action && !action_info->synthesized) || !keyword.empty();
  // If there's a shortcut, don't show the how-to-manage text because it
  // clutters the bubble.
  show_how_to_manage_ = !command.has_value();
  show_key_binding_ = command.has_value();

  if (show_how_to_use_) {
    how_to_use_text_ = MakeHowToUseText(action_info, command, keyword);

    // Don't show how to use if the text returned is empty.
    show_how_to_use_ = !how_to_use_text_.empty();
  }
}

ExtensionPostInstallDialogModel::~ExtensionPostInstallDialogModel() = default;

std::u16string ExtensionPostInstallDialogModel::GetHowToUseText() const {
  DCHECK(show_how_to_use_);
  return how_to_use_text_;
}

gfx::ImageSkia ExtensionPostInstallDialogModel::MakeIconOfSize(
    const gfx::Size& wanted) const {
  gfx::Size size(icon_.width(), icon_.height());
  if (size.width() > wanted.width() || size.height() > wanted.height()) {
    size.SetSize(wanted.width(), wanted.height());
  }

  return gfx::ImageSkiaOperations::CreateResizedImage(
      gfx::ImageSkia::CreateFrom1xBitmap(icon_),
      skia::ImageOperations::RESIZE_BEST, size);
}
