// 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 "components/live_caption/caption_util.h"

#include <stddef.h>

#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/metrics/histogram_functions.h"
#include "base/notreached.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "components/live_caption/pref_names.h"
#include "components/prefs/pref_service.h"
#include "media/base/media_switches.h"
#include "ui/base/ui_base_switches.h"
#include "ui/native_theme/caption_style.h"

#if BUILDFLAG(IS_WIN)
#include "base/win/windows_version.h"
#endif

#if !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_ANDROID)
#include "components/soda/soda_util.h"
#endif

namespace {

// Returns whether the style is default or not. If the user has changed any of
// the captions settings from the default value, that is an interesting metric
// to observe.
bool IsDefaultStyle(std::optional<ui::CaptionStyle> style) {
  return (style.has_value() && style->text_size.empty() &&
          style->font_family.empty() && style->text_color.empty() &&
          style->background_color.empty() && style->text_shadow.empty());
}

// Adds !important to all captions styles. They should always override any
// styles added by the video author or by a user stylesheet. This is because in
// Chrome, there is an option to turn off captions styles, so any time the
// captions are on, the styles should take priority.
std::string AddCSSImportant(std::string css_string) {
  return css_string.empty() ? "" : css_string + " !important";
}

// Constructs the CaptionStyle struct from the caption-related preferences.
std::optional<ui::CaptionStyle> GetCaptionStyleFromPrefs(PrefService* prefs) {
  if (!prefs) {
    return std::nullopt;
  }

  ui::CaptionStyle style;

  style.text_size =
      AddCSSImportant(prefs->GetString(prefs::kAccessibilityCaptionsTextSize));
  style.font_family =
      AddCSSImportant(prefs->GetString(prefs::kAccessibilityCaptionsTextFont));
  if (!prefs->GetString(prefs::kAccessibilityCaptionsTextColor).empty()) {
    std::string text_color = base::StringPrintf(
        "rgba(%s,%s)",
        prefs->GetString(prefs::kAccessibilityCaptionsTextColor).c_str(),
        base::NumberToString(
            prefs->GetInteger(prefs::kAccessibilityCaptionsTextOpacity) / 100.0)
            .c_str());
    style.text_color = AddCSSImportant(text_color);
  }

  if (!prefs->GetString(prefs::kAccessibilityCaptionsBackgroundColor).empty()) {
    std::string background_color = base::StringPrintf(
        "rgba(%s,%s)",
        prefs->GetString(prefs::kAccessibilityCaptionsBackgroundColor).c_str(),
        base::NumberToString(
            prefs->GetInteger(prefs::kAccessibilityCaptionsBackgroundOpacity) /
            100.0)
            .c_str());
    style.background_color = AddCSSImportant(background_color);
  }

  style.text_shadow = AddCSSImportant(
      prefs->GetString(prefs::kAccessibilityCaptionsTextShadow));

  return style;
}

}  // namespace

namespace captions {

std::optional<ui::CaptionStyle> GetCaptionStyleFromUserSettings(
    PrefService* prefs,
    bool record_metrics) {
  std::optional<ui::CaptionStyle> style;

  // Apply command-line CaptionStyle parameters.
  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          ::switches::kForceCaptionStyle)) {
    style = ui::CaptionStyle::FromSpec(
        base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
            switches::kForceCaptionStyle));
  }

  // Apply system caption style.
  if (!style) {
    style = ui::CaptionStyle::FromSystemSettings();
    if (record_metrics && style.has_value()) {
      base::UmaHistogramBoolean(
          "Accessibility.CaptionSettingsLoadedFromSystemSettings",
          !IsDefaultStyle(style));
    }
  }

  // Apply caption style from preferences if system caption style is undefined.
  if (!style) {
    style = GetCaptionStyleFromPrefs(prefs);
    if (record_metrics && style.has_value()) {
      base::UmaHistogramBoolean("Accessibility.CaptionSettingsLoadedFromPrefs",
                                !IsDefaultStyle(style));
    }
  }

  return style;
}

bool IsLiveCaptionFeatureSupported() {
#if !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_ANDROID)
  return speech::IsOnDeviceSpeechRecognitionSupported();
#else
  return false;
#endif  // !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_ANDROID)
}

bool IsHeadlessCaptionFeatureSupported() {
  return base::FeatureList::IsEnabled(media::kHeadlessLiveCaption);
}

std::string GetCaptionSettingsUrl() {
#if BUILDFLAG(IS_CHROMEOS)
  return "chrome://os-settings/audioAndCaptions";
#elif BUILDFLAG(IS_LINUX)
  return "chrome://settings/captions";
#elif BUILDFLAG(IS_WIN)
  return base::win::GetVersion() >= base::win::Version::WIN10
             ? "chrome://settings/accessibility"
             : "chrome://settings/captions";
#elif BUILDFLAG(IS_MAC)
  return "chrome://settings/accessibility";
#else
  NOTREACHED();
#endif
}

}  // namespace captions
