// Copyright 2014 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/omnibox/browser/omnibox_field_trial.h"

#include <algorithm>
#include <cmath>
#include <functional>
#include <string>

#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/no_destructor.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/system/sys_info.h"
#include "base/time/time.h"
#include "base/trace_event/memory_usage_estimator.h"
#include "build/build_config.h"
#include "components/history/core/browser/url_database.h"
#include "components/omnibox/browser/aim_eligibility_service.h"
#include "components/omnibox/browser/autocomplete_provider.h"
#include "components/omnibox/browser/autocomplete_provider_client.h"
#include "components/omnibox/browser/page_classification_functions.h"
#include "components/omnibox/browser/url_index_private_data.h"
#include "components/omnibox/common/omnibox_feature_configs.h"
#include "components/omnibox/common/omnibox_features.h"
#include "components/optimization_guide/machine_learning_tflite_buildflags.h"
#include "components/search/search.h"
#include "components/variations/active_field_trials.h"
#include "components/variations/hashing.h"
#include "components/variations/variations_associated_data.h"
#include "third_party/metrics_proto/omnibox_event.pb.h"
#include "ui/base/device_form_factor.h"
#include "ui/base/ui_base_features.h"

using metrics::OmniboxEventProto;

namespace {

typedef std::map<std::string, std::string> VariationParams;
typedef HUPScoringParams::ScoreBuckets ScoreBuckets;

void InitializeBucketsFromString(const std::string& bucket_string,
                                 ScoreBuckets* score_buckets) {
  // Clear the buckets.
  score_buckets->buckets().clear();
  base::StringPairs kv_pairs;
  if (base::SplitStringIntoKeyValuePairs(bucket_string, ':', ',', &kv_pairs)) {
    for (base::StringPairs::const_iterator it = kv_pairs.begin();
         it != kv_pairs.end(); ++it) {
      ScoreBuckets::CountMaxRelevance bucket;
      base::StringToDouble(it->first, &bucket.first);
      base::StringToInt(it->second, &bucket.second);
      score_buckets->buckets().push_back(bucket);
    }
    std::sort(score_buckets->buckets().begin(), score_buckets->buckets().end(),
              std::greater<ScoreBuckets::CountMaxRelevance>());
  }
}

void InitializeScoreBuckets(const VariationParams& params,
                            const char* relevance_cap_param,
                            const char* half_life_param,
                            const char* score_buckets_param,
                            const char* use_decay_factor_param,
                            ScoreBuckets* score_buckets) {
  auto it = params.find(relevance_cap_param);
  if (it != params.end()) {
    int relevance_cap;
    if (base::StringToInt(it->second, &relevance_cap)) {
      score_buckets->set_relevance_cap(relevance_cap);
    }
  }

  it = params.find(use_decay_factor_param);
  if (it != params.end()) {
    int use_decay_factor;
    if (base::StringToInt(it->second, &use_decay_factor)) {
      score_buckets->set_use_decay_factor(use_decay_factor != 0);
    }
  }

  it = params.find(half_life_param);
  if (it != params.end()) {
    int half_life_days;
    if (base::StringToInt(it->second, &half_life_days)) {
      score_buckets->set_half_life_days(half_life_days);
    }
  }

  it = params.find(score_buckets_param);
  if (it != params.end()) {
    // The value of the score bucket is a comma-separated list of
    // {DecayedCount/DecayedFactor + ":" + MaxRelevance}.
    InitializeBucketsFromString(it->second, score_buckets);
  }
}

OmniboxFieldTrial::MLConfig& GetMLConfigInternal() {
  static base::NoDestructor<OmniboxFieldTrial::MLConfig> s_config;
  return *s_config;
}

bool IsKoreanLocale(const std::string& locale) {
  return locale == "ko" || locale == "ko-KR";
}

#if !BUILDFLAG(IS_IOS)
bool IsEnglishLocale(const std::string& locale) {
  return base::StartsWith(locale, "en", base::CompareCase::SENSITIVE);
}
#endif  // !BUILDFLAG(IS_IOS)

}  // namespace

HUPScoringParams::ScoreBuckets::ScoreBuckets()
    : relevance_cap_(-1), half_life_days_(-1), use_decay_factor_(false) {}

HUPScoringParams::ScoreBuckets::ScoreBuckets(const ScoreBuckets& other) =
    default;

HUPScoringParams::ScoreBuckets::~ScoreBuckets() = default;

size_t HUPScoringParams::ScoreBuckets::EstimateMemoryUsage() const {
  return base::trace_event::EstimateMemoryUsage(buckets_);
}

double HUPScoringParams::ScoreBuckets::HalfLifeTimeDecay(
    const base::TimeDelta& elapsed_time) const {
  double time_ms;
  if ((half_life_days_ <= 0) ||
      ((time_ms = elapsed_time.InMillisecondsF()) <= 0)) {
    return 1.0;
  }

  const double half_life_intervals =
      time_ms / base::Days(half_life_days_).InMillisecondsF();
  return pow(2.0, -half_life_intervals);
}

size_t HUPScoringParams::EstimateMemoryUsage() const {
  size_t res = 0;

  res += base::trace_event::EstimateMemoryUsage(typed_count_buckets);
  res += base::trace_event::EstimateMemoryUsage(visited_count_buckets);

  return res;
}

int OmniboxFieldTrial::GetDisabledProviderTypes() {
  const std::string& types_string = base::GetFieldTrialParamValue(
      kBundledExperimentFieldTrialName, kDisableProvidersRule);
  int types = 0;
  if (types_string.empty() || !base::StringToInt(types_string, &types)) {
    return 0;
  }
  return types;
}

void OmniboxFieldTrial::GetActiveSuggestFieldTrialHashes(
    std::vector<uint32_t>* field_trial_hashes) {
  field_trial_hashes->clear();
  if (base::FieldTrialList::TrialExists(kBundledExperimentFieldTrialName)) {
    field_trial_hashes->push_back(
        variations::HashName(kBundledExperimentFieldTrialName));
  }
}

size_t OmniboxFieldTrial::GetProviderMaxMatches(
    AutocompleteProvider::Type provider) {
  size_t default_max_matches_per_provider = 3;

  std::string param_value;
  if (OmniboxFieldTrial::IsMlUrlScoringEnabled()) {
    param_value =
        OmniboxFieldTrial::GetMLConfig().ml_url_scoring_max_matches_by_provider;
  } else {
    param_value = base::GetFieldTrialParamValueByFeature(
        omnibox::kUIExperimentMaxAutocompleteMatches,
        OmniboxFieldTrial::kUIMaxAutocompleteMatchesByProviderParam);
  }

  // If the experiment param specifies a max results for |provider|, return the
  // specified limit.
  // E.g., if param_value = '3:2' and provider = 3, return 2.
  // Otherwise, if the experiment param specifies a default value for
  // unspecified providers, return the default value.
  // E.g., if param_value = '3:3,*:4' and provider = 1, return 4,
  // Otherwise, return |default_max_matches_per_provider|.
  base::StringPairs kv_pairs;
  if (base::SplitStringIntoKeyValuePairs(param_value, ':', ',', &kv_pairs)) {
    for (const auto& kv_pair : kv_pairs) {
      int k;
      base::StringToInt(kv_pair.first, &k);
      size_t v;
      base::StringToSizeT(kv_pair.second, &v);

      if (kv_pair.first == "*") {
        default_max_matches_per_provider = v;
      } else if (k == provider) {
        return v;
      }
    }
  }

  return default_max_matches_per_provider;
}



void OmniboxFieldTrial::GetDefaultHUPScoringParams(
    HUPScoringParams* scoring_params) {
  ScoreBuckets* type_score_buckets = &scoring_params->typed_count_buckets;
  type_score_buckets->set_half_life_days(30);
  type_score_buckets->set_use_decay_factor(false);
  // Default typed count buckets based on decayed typed count. The
  // values here are based on the results of field trials to determine what
  // maximized overall result quality.
  const std::string& typed_count_score_buckets_str =
      "1.0:1413,0.97:1390,0.93:1360,0.85:1340,0.72:1320,0.50:1250,0.0:1203";
  InitializeBucketsFromString(typed_count_score_buckets_str,
                              type_score_buckets);

  ScoreBuckets* visit_score_buckets = &scoring_params->visited_count_buckets;
  visit_score_buckets->set_half_life_days(30);
  visit_score_buckets->set_use_decay_factor(false);
  // Buckets based on visit count.  Like the typed count buckets above, the
  // values here were chosen based on field trials.  Note that when a URL hasn't
  // been visited in the last 30 days, we clamp its score to 100, which
  // basically demotes it below any other results in the dropdown.
  const std::string& visit_count_score_buckets_str = "4.0:790,0.5:590,0.0:100";
  InitializeBucketsFromString(visit_count_score_buckets_str,
                              visit_score_buckets);
}

void OmniboxFieldTrial::GetExperimentalHUPScoringParams(
    HUPScoringParams* scoring_params) {
  VariationParams params;
  if (!base::GetFieldTrialParams(kBundledExperimentFieldTrialName, &params)) {
    return;
  }

  InitializeScoreBuckets(params, kHUPNewScoringTypedCountRelevanceCapParam,
                         kHUPNewScoringTypedCountHalfLifeTimeParam,
                         kHUPNewScoringTypedCountScoreBucketsParam,
                         kHUPNewScoringTypedCountUseDecayFactorParam,
                         &scoring_params->typed_count_buckets);
  InitializeScoreBuckets(params, kHUPNewScoringVisitedCountRelevanceCapParam,
                         kHUPNewScoringVisitedCountHalfLifeTimeParam,
                         kHUPNewScoringVisitedCountScoreBucketsParam,
                         kHUPNewScoringVisitedCountUseDecayFactorParam,
                         &scoring_params->visited_count_buckets);
}

float OmniboxFieldTrial::HQPBookmarkValue() {
  std::string bookmark_value_str = base::GetFieldTrialParamValue(
      kBundledExperimentFieldTrialName, kHQPBookmarkValueRule);
  if (bookmark_value_str.empty()) {
    return 10;
  }
  // This is a best-effort conversion; we trust the hand-crafted parameters
  // downloaded from the server to be perfect.  There's no need for handle
  // errors smartly.
  double bookmark_value;
  base::StringToDouble(bookmark_value_str, &bookmark_value);
  return bookmark_value;
}

bool OmniboxFieldTrial::HQPAllowMatchInTLDValue() {
  return base::GetFieldTrialParamValue(kBundledExperimentFieldTrialName,
                                       kHQPAllowMatchInTLDRule) == "true";
}

bool OmniboxFieldTrial::HQPAllowMatchInSchemeValue() {
  return base::GetFieldTrialParamValue(kBundledExperimentFieldTrialName,
                                       kHQPAllowMatchInSchemeRule) == "true";
}

void OmniboxFieldTrial::GetSuggestPollingStrategy(bool* from_last_keystroke,
                                                  int* polling_delay_ms) {
  *from_last_keystroke =
      base::GetFieldTrialParamValue(
          kBundledExperimentFieldTrialName,
          kMeasureSuggestPollingDelayFromLastKeystrokeRule) == "true";

  const std::string& polling_delay_string = base::GetFieldTrialParamValue(
      kBundledExperimentFieldTrialName, kSuggestPollingDelayMsRule);
  if (polling_delay_string.empty() ||
      !base::StringToInt(polling_delay_string, polling_delay_ms) ||
      (*polling_delay_ms <= 0)) {
    *polling_delay_ms = kDefaultMinimumTimeBetweenSuggestQueriesMs;
  }
}

std::string OmniboxFieldTrial::HQPExperimentalScoringBuckets() {
  return base::GetFieldTrialParamValue(kBundledExperimentFieldTrialName,
                                       kHQPExperimentalScoringBucketsParam);
}

float OmniboxFieldTrial::HQPExperimentalTopicalityThreshold() {
  std::string topicality_threshold_str = base::GetFieldTrialParamValue(
      kBundledExperimentFieldTrialName,
      kHQPExperimentalScoringTopicalityThresholdParam);

  double topicality_threshold;
  if (topicality_threshold_str.empty() ||
      !base::StringToDouble(topicality_threshold_str, &topicality_threshold)) {
    return 0.5f;
  }

  return static_cast<float>(topicality_threshold);
}

int OmniboxFieldTrial::MaxNumHQPUrlsIndexedAtStartup() {
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
  // Limits on Android and iOS are chosen based on experiment results. See
  // crbug.com/715852#c18 and crbug.com/1141539#c31.
  constexpr int kDefaultOnLowEndDevices = 100;
  constexpr int kDefaultOnNonLowEndDevices = 400;
#else
  // Use 20,000 entries as a safety cap for users with spammed history,
  // such as users who were stuck in a redirect loop with autogenerated URLs.
  // This limit will only affect 0.01% of Windows users. crbug.com/750845.
  constexpr int kDefaultOnLowEndDevices = 20000;
  constexpr int kDefaultOnNonLowEndDevices = 20000;
#endif

  if (base::SysInfo::IsLowEndDeviceOrPartialLowEndModeEnabled()) {
    return kDefaultOnLowEndDevices;
  } else {
    return kDefaultOnNonLowEndDevices;
  }
}

size_t OmniboxFieldTrial::HQPMaxVisitsToScore() {
  std::string max_visits_str = base::GetFieldTrialParamValue(
      kBundledExperimentFieldTrialName, kHQPMaxVisitsToScoreRule);
  constexpr size_t kDefaultMaxVisitsToScore = 10;
  static_assert(
      URLIndexPrivateData::kMaxVisitsToStoreInCache >= kDefaultMaxVisitsToScore,
      "HQP should store at least as many visits as it expects to score");
  if (max_visits_str.empty()) {
    return kDefaultMaxVisitsToScore;
  }
  // This is a best-effort conversion; we trust the hand-crafted parameters
  // downloaded from the server to be perfect.  There's no need for handle
  // errors smartly.
  size_t max_visits_value;
  base::StringToSizeT(max_visits_str, &max_visits_value);
  return max_visits_value;
}

float OmniboxFieldTrial::HQPTypedValue() {
  std::string typed_value_str = base::GetFieldTrialParamValue(
      kBundledExperimentFieldTrialName, kHQPTypedValueRule);
  if (typed_value_str.empty()) {
    return 1.5;
  }
  // This is a best-effort conversion; we trust the hand-crafted parameters
  // downloaded from the server to be perfect.  There's no need for handle
  // errors smartly.
  double typed_value;
  base::StringToDouble(typed_value_str, &typed_value);
  return typed_value;
}

OmniboxFieldTrial::NumMatchesScores OmniboxFieldTrial::HQPNumMatchesScores() {
  std::string str = base::GetFieldTrialParamValue(
      kBundledExperimentFieldTrialName, kHQPNumMatchesScoresRule);
  static constexpr char kDefaultNumMatchesScores[] = "1:3,2:2.5,3:2,4:1.5";
  if (str.empty()) {
    str = kDefaultNumMatchesScores;
  }
  // The parameter is a comma-separated list of (number, value) pairs such as
  // listed above.
  // This is a best-effort conversion; we trust the hand-crafted parameters
  // downloaded from the server to be perfect.  There's no need to handle
  // errors smartly.
  base::StringPairs kv_pairs;
  if (!base::SplitStringIntoKeyValuePairs(str, ':', ',', &kv_pairs)) {
    return NumMatchesScores{};
  }
  NumMatchesScores num_matches_scores(kv_pairs.size());
  for (size_t i = 0; i < kv_pairs.size(); ++i) {
    base::StringToSizeT(kv_pairs[i].first, &num_matches_scores[i].first);
    // The input must be sorted by number of matches.
    DCHECK((i == 0) ||
           (num_matches_scores[i].first > num_matches_scores[i - 1].first));
    base::StringToDouble(kv_pairs[i].second, &num_matches_scores[i].second);
  }
  return num_matches_scores;
}

size_t OmniboxFieldTrial::HQPNumTitleWordsToAllow() {
  // The value of the rule is a string that encodes an integer (actually
  // size_t) containing the number of words.
  size_t num_title_words;
  if (!base::StringToSizeT(
          base::GetFieldTrialParamValue(kBundledExperimentFieldTrialName,
                                        kHQPNumTitleWordsRule),
          &num_title_words)) {
    return 20;
  }
  return num_title_words;
}

bool OmniboxFieldTrial::HQPAlsoDoHUPLikeScoring() {
  return base::GetFieldTrialParamValue(kBundledExperimentFieldTrialName,
                                       kHQPAlsoDoHUPLikeScoringRule) == "true";
}

bool OmniboxFieldTrial::HUPSearchDatabase() {
  const std::string& value = base::GetFieldTrialParamValue(
      kBundledExperimentFieldTrialName, kHUPSearchDatabaseRule);
  return value.empty() || (value == "true");
}

bool OmniboxFieldTrial::IsOnDeviceHeadSuggestEnabledForIncognito() {
  return base::FeatureList::IsEnabled(omnibox::kOnDeviceHeadProviderIncognito);
}

bool OmniboxFieldTrial::IsOnDeviceHeadSuggestEnabledForNonIncognito() {
  return base::FeatureList::IsEnabled(
      omnibox::kOnDeviceHeadProviderNonIncognito);
}

bool OmniboxFieldTrial::IsOnDeviceHeadSuggestEnabledForAnyMode() {
  return IsOnDeviceHeadSuggestEnabledForIncognito() ||
         IsOnDeviceHeadSuggestEnabledForNonIncognito();
}

bool OmniboxFieldTrial::IsOnDeviceTailSuggestEnabled(
    const std::string& locale) {
  // Tail model will only be enabled when head provider is also enabled.
  if (!IsOnDeviceHeadSuggestEnabledForAnyMode()) {
    return false;
  }

  // Currently only launch for English locales. Remove this flag once i18n is
  // also launched.
  // Do not launch for iOS since the feature is not supported in iOS yet.
#if !BUILDFLAG(IS_IOS)
  if (IsEnglishLocale(locale)) {
    return base::FeatureList::IsEnabled(
        omnibox::kOnDeviceTailEnableEnglishModel);
  }
#endif  // !BUILDFLAG(IS_IOS)

  return base::FeatureList::IsEnabled(omnibox::kOnDeviceTailModel);
}

bool OmniboxFieldTrial::ShouldEncodeLeadingSpaceForOnDeviceTailSuggest() {
  return base::GetFieldTrialParamByFeatureAsBool(omnibox::kOnDeviceTailModel,
                                                 "ShouldEncodeLeadingSpace",
                                                 /*default_value=*/false);
}

bool OmniboxFieldTrial::ShouldApplyOnDeviceHeadModelSelectionFix() {
  return base::GetFieldTrialParamByFeatureAsBool(
             omnibox::kOnDeviceHeadProviderNonIncognito,
             OmniboxFieldTrial::kOnDeviceHeadModelSelectionFix,
             /*default_value=*/true) ||
         base::GetFieldTrialParamByFeatureAsBool(
             omnibox::kOnDeviceHeadProviderIncognito,
             OmniboxFieldTrial::kOnDeviceHeadModelSelectionFix,
             /*default_value=*/true);
}

bool OmniboxFieldTrial::IsOnDeviceHeadSuggestEnabledForLocale(
    const std::string& locale) {
  if (IsKoreanLocale(locale)) {
    return false;
  }
  return IsOnDeviceHeadSuggestEnabledForAnyMode();
}

std::string OmniboxFieldTrial::OnDeviceHeadModelLocaleConstraint(
    bool is_incognito) {
  const base::Feature* feature =
      is_incognito ? &omnibox::kOnDeviceHeadProviderIncognito
                   : &omnibox::kOnDeviceHeadProviderNonIncognito;
  std::string constraint = base::GetFieldTrialParamValueByFeature(
      *feature, kOnDeviceHeadModelLocaleConstraint);
  if (constraint.empty()) {
    constraint = "500000";
  }
  return constraint;
}

const char OmniboxFieldTrial::kBundledExperimentFieldTrialName[] =
    "OmniboxBundledExperimentV1";
const char OmniboxFieldTrial::kDisableProvidersRule[] = "DisableProviders";
const char OmniboxFieldTrial::kHQPBookmarkValueRule[] = "HQPBookmarkValue";
const char OmniboxFieldTrial::kHQPTypedValueRule[] = "HQPTypedValue";
const char OmniboxFieldTrial::kHQPAllowMatchInTLDRule[] = "HQPAllowMatchInTLD";
const char OmniboxFieldTrial::kHQPAllowMatchInSchemeRule[] =
    "HQPAllowMatchInScheme";
const char
    OmniboxFieldTrial::kMeasureSuggestPollingDelayFromLastKeystrokeRule[] =
        "MeasureSuggestPollingDelayFromLastKeystroke";
const char OmniboxFieldTrial::kSuggestPollingDelayMsRule[] =
    "SuggestPollingDelayMs";
const char OmniboxFieldTrial::kHQPMaxVisitsToScoreRule[] =
    "HQPMaxVisitsToScoreRule";
const char OmniboxFieldTrial::kHQPNumMatchesScoresRule[] =
    "HQPNumMatchesScores";
const char OmniboxFieldTrial::kHQPNumTitleWordsRule[] = "HQPNumTitleWords";
const char OmniboxFieldTrial::kHQPAlsoDoHUPLikeScoringRule[] =
    "HQPAlsoDoHUPLikeScoring";
const char OmniboxFieldTrial::kHUPSearchDatabaseRule[] = "HUPSearchDatabase";
const char OmniboxFieldTrial::kHUPNewScoringTypedCountRelevanceCapParam[] =
    "TypedCountRelevanceCap";
const char OmniboxFieldTrial::kHUPNewScoringTypedCountHalfLifeTimeParam[] =
    "TypedCountHalfLifeTime";
const char OmniboxFieldTrial::kHUPNewScoringTypedCountScoreBucketsParam[] =
    "TypedCountScoreBuckets";
const char OmniboxFieldTrial::kHUPNewScoringTypedCountUseDecayFactorParam[] =
    "TypedCountUseDecayFactor";
const char OmniboxFieldTrial::kHUPNewScoringVisitedCountRelevanceCapParam[] =
    "VisitedCountRelevanceCap";
const char OmniboxFieldTrial::kHUPNewScoringVisitedCountHalfLifeTimeParam[] =
    "VisitedCountHalfLifeTime";
const char OmniboxFieldTrial::kHUPNewScoringVisitedCountScoreBucketsParam[] =
    "VisitedCountScoreBuckets";
const char OmniboxFieldTrial::kHUPNewScoringVisitedCountUseDecayFactorParam[] =
    "VisitedCountUseDecayFactor";

const char OmniboxFieldTrial::kHQPExperimentalScoringBucketsParam[] =
    "HQPExperimentalScoringBuckets";
const char
    OmniboxFieldTrial::kHQPExperimentalScoringTopicalityThresholdParam[] =
        "HQPExperimentalScoringTopicalityThreshold";

const char
    OmniboxFieldTrial::kMaxNumHQPUrlsIndexedAtStartupOnLowEndDevicesParam[] =
        "MaxNumHQPUrlsIndexedAtStartupOnLowEndDevices";
const char
    OmniboxFieldTrial::kMaxNumHQPUrlsIndexedAtStartupOnNonLowEndDevicesParam[] =
        "MaxNumHQPUrlsIndexedAtStartupOnNonLowEndDevices";

const char OmniboxFieldTrial::kMaxZeroSuggestMatchesParam[] =
    "MaxZeroSuggestMatches";
const char OmniboxFieldTrial::kUIMaxAutocompleteMatchesByProviderParam[] =
    "UIMaxAutocompleteMatchesByProvider";
const char OmniboxFieldTrial::kUIMaxAutocompleteMatchesParam[] =
    "UIMaxAutocompleteMatches";
const char OmniboxFieldTrial::kDynamicMaxAutocompleteUrlCutoffParam[] =
    "OmniboxDynamicMaxAutocompleteUrlCutoff";
const char OmniboxFieldTrial::kDynamicMaxAutocompleteIncreasedLimitParam[] =
    "OmniboxDynamicMaxAutocompleteIncreasedLimit";
const char OmniboxFieldTrial::kSuppressPsuggestBackfillWithMIAParam[] =
    "SuppressPsuggestBackfillWithMIA";

const char OmniboxFieldTrial::kOnDeviceHeadModelLocaleConstraint[] =
    "ForceModelLocaleConstraint";
const char OmniboxFieldTrial::kOnDeviceHeadModelSelectionFix[] = "SelectionFix";

int OmniboxFieldTrial::kDefaultMinimumTimeBetweenSuggestQueriesMs = 100;

namespace OmniboxFieldTrial {

// Local history zero-prefix (aka zero-suggest) and prefix suggestions:

// Whether to ignore all ZPS prefetch responses received from the Suggest
// service when the user is on a Google SRP. This can be used, for example,
// during experimentation to measure the performance impact of only the
// request/response portion of ZPS prefetching (i.e. without updating the
// user-visible list of suggestions in the Omnibox).
const base::FeatureParam<bool> kZeroSuggestPrefetchingOnSRPCounterfactual(
    &omnibox::kZeroSuggestPrefetchingOnSRP,
    "ZeroSuggestPrefetchingOnSRPCounterfactual",
    false);

// The debouncing delay (in milliseconds) to use when throttling ZPS prefetch
// requests.
const base::FeatureParam<int> kZeroSuggestPrefetchDebounceDelay(
    &omnibox::kZeroSuggestPrefetchDebouncing,
    "ZeroSuggestPrefetchDebounceDelay",
    300);

// Whether to calculate debouncing delay relative to the latest successful run
// (instead of the latest run request).
const base::FeatureParam<bool> kZeroSuggestPrefetchDebounceFromLastRun(
    &omnibox::kZeroSuggestPrefetchDebouncing,
    "ZeroSuggestPrefetchDebounceFromLastRun",
    true);

// The maximum number of entries stored by the in-memory zero-suggest cache at
// at any given time (LRU eviction policy is used to enforce this limit).
const base::FeatureParam<int> kZeroSuggestCacheMaxSize(
    &omnibox::kZeroSuggestInMemoryCaching,
    "ZeroSuggestCacheMaxSize",
    5);

bool IsZeroSuggestPrefetchingEnabled() {
  return base::FeatureList::IsEnabled(omnibox::kZeroSuggestPrefetching) ||
         base::FeatureList::IsEnabled(omnibox::kZeroSuggestPrefetchingOnSRP) ||
         base::FeatureList::IsEnabled(omnibox::kZeroSuggestPrefetchingOnWeb);
}

bool IsZeroSuggestPrefetchingEnabledInContext(
    metrics::OmniboxEventProto::PageClassification page_classification) {
  switch (page_classification) {
    case metrics::OmniboxEventProto::NTP_ZPS_PREFETCH:
      return base::FeatureList::IsEnabled(omnibox::kZeroSuggestPrefetching);
    case metrics::OmniboxEventProto::SRP_ZPS_PREFETCH:
      return base::FeatureList::IsEnabled(
          omnibox::kZeroSuggestPrefetchingOnSRP);
    case metrics::OmniboxEventProto::OTHER_ZPS_PREFETCH:
      return base::FeatureList::IsEnabled(
          omnibox::kZeroSuggestPrefetchingOnWeb);
    default:
      return false;
  }
}

bool IsOnFocusZeroSuggestEnabledInContext(
    metrics::OmniboxEventProto::PageClassification page_classification) {
  static bool enabled =
      base::FeatureList::IsEnabled(omnibox::kFocusTriggersWebAndSRPZeroSuggest);

  switch (page_classification) {
    case metrics::OmniboxEventProto::
        SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT:
    case metrics::OmniboxEventProto::OTHER:
      return enabled;
    default:
      return false;
  }
}

bool IsHideSuggestionGroupHeadersEnabledInContext(
    metrics::OmniboxEventProto::PageClassification page_classification) {
  static bool enabled =
      base::FeatureList::IsEnabled(omnibox::kHideSuggestionGroupHeaders);

  switch (page_classification) {
    case metrics::OmniboxEventProto::
        SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT:
    case metrics::OmniboxEventProto::OTHER:
      return enabled;
    default:
      return false;
  }
}

bool IsDeterministicAimActionInTypedStateEnabled(
    AutocompleteProviderClient* client) {
  ui::DeviceFormFactor factor = ui::GetDeviceFormFactor();
  if (!(factor == ui::DEVICE_FORM_FACTOR_PHONE ||
        factor == ui::DEVICE_FORM_FACTOR_FOLDABLE)) {
    return false;
  }

  return AimEligibilityService::GenericKillSwitchFeatureCheck(
      client->GetAimEligibilityService(),
      omnibox::kOmniboxAimShortcutTypedState);
}

bool IsAimOmniboxEntrypointEnabled(
    const AimEligibilityService* aim_eligibility_service) {
  return AimEligibilityService::GenericKillSwitchFeatureCheck(
      aim_eligibility_service, omnibox::kAiModeOmniboxEntryPoint,
      omnibox::kAiModeOmniboxEntryPointEnUs);
}

bool IsAimStarterPackEnabled(
    const AimEligibilityService* aim_eligibility_service) {
  // AI starter pack should be available if any AI omnibox feature is available.
  return AimEligibilityService::GenericKillSwitchFeatureCheck(
             aim_eligibility_service,
             omnibox_feature_configs::Toolbelt::kOmniboxToolbelt) ||
         AimEligibilityService::GenericKillSwitchFeatureCheck(
             aim_eligibility_service, omnibox::kAiModeStartPack);
}

// Rich autocompletion.

bool IsRichAutocompletionEnabled() {
  return base::FeatureList::IsEnabled(omnibox::kRichAutocompletion);
}

const base::FeatureParam<size_t> kRichAutocompletionAutocompleteTitlesMinChar(
    &omnibox::kRichAutocompletion,
    "RichAutocompletionAutocompleteTitlesMinChar",
    3);

const base::FeatureParam<size_t>
    kRichAutocompletionAutocompleteShortcutTextMinChar(
        &omnibox::kRichAutocompletion,
        "RichAutocompletionAutocompleteShortcutTextMinChar",
        3);

// ---------------------------------------------------------
// ML Relevance Scoring ->

// If true, enables scoring signal annotators for logging Omnibox scoring
// signals to OmniboxEventProto.
const base::FeatureParam<bool> kEnableScoringSignalsAnnotatorsForLogging(
    &omnibox::kLogUrlScoringSignals,
    "enable_scoring_signals_annotators",
    false);

// If true, enables scoring signal annotators for ML scoring.
const base::FeatureParam<bool> kEnableScoringSignalsAnnotatorsForMlScoring(
    &omnibox::kMlUrlScoring,
    "enable_scoring_signals_annotators_for_ml_scoring",
    true);

// If true, runs the ML scoring model but does not assign new relevance scores
// to the URL suggestions and does not rerank them.
const base::FeatureParam<bool> kMlUrlScoringCounterfactual(
    &omnibox::kMlUrlScoring,
    "MlUrlScoringCounterfactual",
    false);

// If true, increases the number of candidates the URL autocomplete providers
// pass to the controller beyond `provider_max_matches`.
const base::FeatureParam<bool> kMlUrlScoringUnlimitedNumCandidates(
    &omnibox::kMlUrlScoring,
    "MlUrlScoringUnlimitedNumCandidates",
    false);

const base::FeatureParam<std::string> kMlUrlScoringMaxMatchesByProvider(
    &omnibox::kMlUrlScoring,
    "MlUrlScoringMaxMatchesByProvider",
    "");

MLConfig::MLConfig() {
  log_url_scoring_signals =
      base::FeatureList::IsEnabled(omnibox::kLogUrlScoringSignals);
  enable_history_scoring_signals_annotator_for_searches =
      base::FeatureList::IsEnabled(
          omnibox::kEnableHistoryScoringSignalsAnnotatorForSearches);
  enable_scoring_signals_annotators =
      kEnableScoringSignalsAnnotatorsForLogging.Get() ||
      kEnableScoringSignalsAnnotatorsForMlScoring.Get();
  shortcut_document_signals =
      base::FeatureParam<bool>(&omnibox::kLogUrlScoringSignals,
                               "MlUrlScoringShortcutDocumentSignals", false)
          .Get() ||
      base::FeatureParam<bool>(&omnibox::kMlUrlScoring,
                               "MlUrlScoringShortcutDocumentSignals", true)
          .Get();

  ml_url_scoring = base::FeatureList::IsEnabled(omnibox::kMlUrlScoring);
  ml_url_scoring_counterfactual = kMlUrlScoringCounterfactual.Get();
  ml_url_scoring_unlimited_num_candidates =
      kMlUrlScoringUnlimitedNumCandidates.Get();
  ml_url_scoring_max_matches_by_provider =
      kMlUrlScoringMaxMatchesByProvider.Get();

  // `kMlUrlSearchBlending` parameters.
  mapped_search_blending =
      base::FeatureParam<bool>(&omnibox::kMlUrlSearchBlending,
                               "MlUrlSearchBlending_MappedSearchBlending",
                               mapped_search_blending)
          .Get();
  mapped_search_blending_min =
      base::FeatureParam<int>(&omnibox::kMlUrlSearchBlending,
                              "MlUrlSearchBlending_MappedSearchBlendingMin",
                              mapped_search_blending_min)
          .Get();
  mapped_search_blending_max =
      base::FeatureParam<int>(&omnibox::kMlUrlSearchBlending,
                              "MlUrlSearchBlending_MappedSearchBlendingMax",
                              mapped_search_blending_max)
          .Get();
  mapped_search_blending_grouping_threshold =
      base::FeatureParam<int>(
          &omnibox::kMlUrlSearchBlending,
          "MlUrlSearchBlending_MappedSearchBlendingGroupingThreshold",
          mapped_search_blending_grouping_threshold)
          .Get();

  // `kMlUrlPiecewiseMappedSearchBlending` parameters.
  piecewise_mapped_search_blending =
      base::FeatureParam<bool>(&omnibox::kMlUrlPiecewiseMappedSearchBlending,
                               "MlUrlPiecewiseMappedSearchBlending",
                               piecewise_mapped_search_blending)
          .Get();
  piecewise_mapped_search_blending_grouping_threshold =
      base::FeatureParam<int>(
          &omnibox::kMlUrlPiecewiseMappedSearchBlending,
          "MlUrlPiecewiseMappedSearchBlending_GroupingThreshold",
          piecewise_mapped_search_blending_grouping_threshold)
          .Get();
  piecewise_mapped_search_blending_break_points =
      base::FeatureParam<std::string>(
          &omnibox::kMlUrlPiecewiseMappedSearchBlending,
          "MlUrlPiecewiseMappedSearchBlending_BreakPoints", "")
          .Get();
  piecewise_mapped_search_blending_break_points_verbatim_url =
      base::FeatureParam<std::string>(
          &omnibox::kMlUrlPiecewiseMappedSearchBlending,
          "MlUrlPiecewiseMappedSearchBlending_BreakPoints_VerbatimUrl",
          piecewise_mapped_search_blending_break_points.c_str())
          .Get();
  piecewise_mapped_search_blending_break_points_search =
      base::FeatureParam<std::string>(
          &omnibox::kMlUrlPiecewiseMappedSearchBlending,
          "MlUrlPiecewiseMappedSearchBlending_BreakPoints_Search", "0,0;1,1400")
          .Get();
  piecewise_mapped_search_blending_relevance_bias =
      base::FeatureParam<int>(
          &omnibox::kMlUrlPiecewiseMappedSearchBlending,
          "MlUrlPiecewiseMappedSearchBlending_RelevanceBias",
          piecewise_mapped_search_blending_relevance_bias)
          .Get();

  url_scoring_model = base::FeatureList::IsEnabled(omnibox::kUrlScoringModel);

  ml_url_score_caching =
      base::FeatureList::IsEnabled(omnibox::kMlUrlScoreCaching);
  max_ml_score_cache_size =
      base::FeatureParam<int>(&omnibox::kMlUrlScoreCaching,
                              "MlUrlScoreCaching_MaxMlScoreCacheSize",
                              max_ml_score_cache_size)
          .Get();

  enable_ml_scoring_for_searches =
      base::FeatureParam<bool>(&omnibox::kMlUrlScoring,
                               "MlUrlScoring_EnableMlScoringForSearches", false)
          .Get();
  enable_ml_scoring_for_verbatim_urls =
      base::FeatureParam<bool>(&omnibox::kMlUrlScoring,
                               "MlUrlScoring_EnableMlScoringForVerbatimUrls",
                               false)
          .Get();
}

MLConfig::~MLConfig() = default;

MLConfig::MLConfig(const MLConfig&) = default;

MLConfig& MLConfig::operator=(const MLConfig& other) = default;

ScopedMLConfigForTesting::ScopedMLConfigForTesting()
    : original_config_(std::make_unique<MLConfig>(GetMLConfig())) {
  GetMLConfigInternal() = {};
}

ScopedMLConfigForTesting::~ScopedMLConfigForTesting() {
  GetMLConfigInternal() = *original_config_;
}

MLConfig& ScopedMLConfigForTesting::GetMLConfig() {
  return GetMLConfigInternal();
}

const MLConfig& GetMLConfig() {
  return GetMLConfigInternal();
}

bool IsReportingUrlScoringSignalsEnabled() {
  return GetMLConfig().log_url_scoring_signals;
}

bool IsPopulatingUrlScoringSignalsEnabled() {
  return IsReportingUrlScoringSignalsEnabled() || IsMlUrlScoringEnabled();
}

bool AreScoringSignalsAnnotatorsEnabled() {
  return GetMLConfig().enable_scoring_signals_annotators;
}
bool IsMlUrlScoringEnabled() {
#if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
  return IsUrlScoringModelEnabled() && GetMLConfig().ml_url_scoring;
#else
  return false;
#endif  // BUILDFLAG(BUILD_WITH_TFLITE_LIB)
}
bool IsMlUrlScoringCounterfactual() {
  return IsMlUrlScoringEnabled() && GetMLConfig().ml_url_scoring_counterfactual;
}
bool IsMlUrlScoringUnlimitedNumCandidatesEnabled() {
  return IsMlUrlScoringEnabled() &&
         GetMLConfig().ml_url_scoring_unlimited_num_candidates;
}
bool IsUrlScoringModelEnabled() {
  return GetMLConfig().url_scoring_model;
}
bool IsMlUrlScoreCachingEnabled() {
  return GetMLConfig().ml_url_score_caching;
}

std::vector<std::pair<double, int>> GetPiecewiseMappingBreakPoints(
    PiecewiseMappingVariant mapping_variant) {
  std::vector<std::pair<double, int>> break_points;

  std::string param_value;
  switch (mapping_variant) {
    case PiecewiseMappingVariant::kRegular:
      param_value = OmniboxFieldTrial::GetMLConfig()
                        .piecewise_mapped_search_blending_break_points;
      break;
    case PiecewiseMappingVariant::kVerbatimUrl:
      param_value =
          OmniboxFieldTrial::GetMLConfig()
              .piecewise_mapped_search_blending_break_points_verbatim_url;
      break;
    case PiecewiseMappingVariant::kSearch:
      param_value = OmniboxFieldTrial::GetMLConfig()
                        .piecewise_mapped_search_blending_break_points_search;
      break;
    default:
      NOTREACHED();
  }

  base::StringPairs pairs;
  if (base::SplitStringIntoKeyValuePairs(param_value, ',', ';', &pairs)) {
    for (const auto& p : pairs) {
      double ml_score;
      base::StringToDouble(p.first, &ml_score);
      int relevance;
      base::StringToInt(p.second, &relevance);

      break_points.push_back(std::make_pair(ml_score, relevance));
    }
  }

  return break_points;
}

// <- ML Relevance Scoring
// ---------------------------------------------------------
// Touch Down Trigger For Prefetch ->
const base::FeatureParam<int>
    kTouchDownTriggerForPrefetchMaxPrefetchesPerOmniboxSession(
        &omnibox::kOmniboxTouchDownTriggerForPrefetch,
        "max_prefetches_per_omnibox_session",
        5);
// <- Touch Down Trigger For Prefetch
// ---------------------------------------------------------
// Site Search Starter Pack ->
const base::FeatureParam<std::string> kGeminiUrlOverride(
    &omnibox::kStarterPackExpansion,
    "StarterPackGeminiUrlOverride",
    "https://gemini.google.com/prompt?"
    "utm_source=chrome_omnibox&utm_medium=owned&utm_campaign=gemini_shortcut");

bool IsStarterPackExpansionEnabled() {
  return base::FeatureList::IsEnabled(omnibox::kStarterPackExpansion);
}

bool IsStarterPackIPHEnabled() {
  return base::FeatureList::IsEnabled(omnibox::kStarterPackIPH);
}

// <- Site Search Starter Pack
}  // namespace OmniboxFieldTrial
