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

// This file can be empty. Its purpose is to contain the relatively short lived
// definitions required for experimental flags.

#import "ios/chrome/browser/shared/public/features/system_flags.h"

#import <Foundation/Foundation.h>

#import "base/command_line.h"
#import "base/feature_list.h"
#import "base/metrics/field_trial.h"
#import "base/strings/sys_string_conversions.h"
#import "build/branding_buildflags.h"
#import "components/autofill/core/common/autofill_switches.h"
#import "components/password_manager/core/common/password_manager_features.h"
#import "components/segmentation_platform/public/constants.h"
#import "components/variations/variations_associated_data.h"
#import "ios/chrome/browser/flags/chrome_switches.h"
#import "ios/chrome/browser/memory/model/features.h"
#import "ios/chrome/browser/safety_check/model/ios_chrome_safety_check_manager_constants.h"
#import "ios/chrome/browser/shared/public/features/features.h"

namespace {

NSString* const kAlternateDiscoverFeedServerURL =
    @"AlternateDiscoverFeedServerURL";
NSString* const kEnableStartupCrash = @"EnableStartupCrash";
NSString* const kFirstRunForceEnabled = @"FirstRunForceEnabled";
NSString* const kFirstRunForceDisabled = @"FirstRunForceDisabled";
NSString* const kOriginServerHost = @"AlternateOriginServerHost";
NSString* const kWhatsNewPromoStatus = @"WhatsNewPromoStatus";
NSString* const kClearApplicationGroup = @"ClearApplicationGroup";
NSString* const kNextPromoForDisplayOverride = @"NextPromoForDisplayOverride";
NSString* const kHomeSurfaceDuration = @"HomeSurfaceDuration";
NSString* const kFirstRunRecency = @"FirstRunRecency";
NSString* const kIgnoreDeviceLocaleConditions = @"IgnoreDeviceLocaleConditions";
NSString* const kForceExperienceForDeviceSwitcherExperimentalSettings =
    @"ForceExperienceForDeviceSwitcher";
NSString* const kForceExperienceForShopperExperimentalSettings =
    @"ForceExperienceForShopper";
NSString* const kSafetyCheckUpdateChromeStateOverride =
    @"SafetyCheckUpdateChromeStateOverride";
NSString* const kSafetyCheckPasswordStateOverride =
    @"SafetyCheckPasswordStateOverride";
NSString* const kSafetyCheckSafeBrowsingStateOverride =
    @"SafetyCheckSafeBrowsingStateOverride";
NSString* const kSafetyCheckWeakPasswordsCountOverride =
    @"SafetyCheckWeakPasswordsCountOverride";
NSString* const kSafetyCheckReusedPasswordsCountOverride =
    @"SafetyCheckReusedPasswordsCountOverride";
NSString* const kSafetyCheckCompromisedPasswordsCountOverride =
    @"SafetyCheckCompromisedPasswordsCountOverride";
NSString* const kSimulatePostDeviceRestore = @"SimulatePostDeviceRestore";
NSString* const kShouldIgnoreHistorySyncDeclineLimits =
    @"ShouldIgnoreHistorySyncDeclineLimits";
NSString* const kSafetyCheckNotificationsInactivityThreshold =
    @"SafetyCheckNotificationsInactivityThreshold";
BASE_FEATURE(kEnableThirdPartyKeyboardWorkaround,
             base::FEATURE_ENABLED_BY_DEFAULT);
NSString* const kTipsMagicStackLensShopWithImage =
    @"TipsMagicStackLensShopWithImage";
NSString* const kTipsMagicStackStateOverride = @"TipsMagicStackStateOverride";
NSString* const kInactiveTabsDemoMode = @"InactiveTabsDemoMode";
NSString* const kInactiveTabsTestMode = @"InactiveTabsTestMode";
NSString* const kAsyncStartupOverrideResponse = @"AsyncStartupOverrideResponse";
NSString* const kLensResultPanelGwsURL = @"LensResultPanelGwsURL";
NSString* const kCobrowseGwsURL = @"CobrowseGwsURL";
NSString* const kForceDisableAIMEligibility = @"ForceDisableAIMEligibility";
NSString* const kForceDisableCreateImagesEligibility =
    @"ForceDisableCreateImagesEligibility";
NSString* const kForceDisableCanvasEligibility =
    @"ForceDisableCanvasEligibility";
NSString* const kForceDisableDeepSearchEligibility =
    @"ForceDisableDeepSearchEligibility";
NSString* const kForceDisablePdfUploadEligibility =
    @"ForceDisablePdfUploadEligibility";
NSString* const kShowCatalogItems = @"ShowCatalogItems";
NSString* const kForceMultiProfileForcedMigrationDone =
    @"ForceMultiProfileForcedMigrationDone";
NSString* const kShowBackendPromoDebugTools = @"ShowBackendPromoDebugTools";
NSString* const kForcedPushNotificationType = @"ForcedPushNotificationType";
NSString* const kForcedPushNotificationDelay = @"ForcedPushNotificationDelay";
}  // namespace

namespace experimental_flags {

bool AlwaysDisplayFirstRun() {
  return
      [[NSUserDefaults standardUserDefaults] boolForKey:kFirstRunForceEnabled];
}

bool NeverDisplayFirstRun() {
  return
      [[NSUserDefaults standardUserDefaults] boolForKey:kFirstRunForceDisabled];
}

NSString* GetOriginServerHost() {
  return [[NSUserDefaults standardUserDefaults] stringForKey:kOriginServerHost];
}

NSString* GetAlternateDiscoverFeedServerURL() {
  return [[NSUserDefaults standardUserDefaults]
      stringForKey:kAlternateDiscoverFeedServerURL];
}

bool ShouldResetNoticeCardOnFeedStart() {
  return [[NSUserDefaults standardUserDefaults] boolForKey:@"ResetNoticeCard"];
}

bool ShouldForceContentNotificationsPromo() {
  return [[NSUserDefaults standardUserDefaults]
      boolForKey:@"ForceContentNotificationsPromo"];
}

bool ShouldForceFeedSigninPromo() {
  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
  return [[NSUserDefaults standardUserDefaults]
             boolForKey:@"ForceFeedSigninPromo"] ||
         command_line->HasSwitch(switches::kForceFeedSigninPromo);
}

bool ShouldIgnoreDeviceLocaleConditions() {
  return [[NSUserDefaults standardUserDefaults]
      boolForKey:kIgnoreDeviceLocaleConditions];
}

bool ShouldIgnoreTileAblationConditions() {
  return [[NSUserDefaults standardUserDefaults]
      boolForKey:@"IgnoreTileAblationConditions"];
}

bool IsMemoryDebuggingEnabled() {
#if BUILDFLAG(IOS_ENABLE_MEMORY_DEBUGGING)
  return true;
#else
  return [[NSUserDefaults standardUserDefaults]
      boolForKey:@"EnableMemoryDebugging"];
#endif
}

bool IsOmniboxDebuggingEnabled() {
  return [[NSUserDefaults standardUserDefaults]
      boolForKey:@"EnableOmniboxDebugging"];
}

bool IsSpotlightDebuggingEnabled() {
  return [[NSUserDefaults standardUserDefaults]
      boolForKey:@"EnableSpotlightDebugging"];
}

bool IsStartupCrashEnabled() {
  return [[NSUserDefaults standardUserDefaults] boolForKey:kEnableStartupCrash];
}

bool MustClearApplicationGroupSandbox() {
  bool value =
      [[NSUserDefaults standardUserDefaults] boolForKey:kClearApplicationGroup];
  [[NSUserDefaults standardUserDefaults] setBool:NO
                                          forKey:kClearApplicationGroup];
  return value;
}

bool IsThirdPartyKeyboardWorkaroundEnabled() {
  // Check if the experimental flag is forced on or off.
  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
  if (command_line->HasSwitch(switches::kEnableThirdPartyKeyboardWorkaround)) {
    return true;
  } else if (command_line->HasSwitch(
                 switches::kDisableThirdPartyKeyboardWorkaround)) {
    return false;
  }

  // Check if the Finch experiment is turned on.
  return base::FeatureList::IsEnabled(kEnableThirdPartyKeyboardWorkaround);
}

NSString* GetForcedPromoToDisplay() {
  return [[NSUserDefaults standardUserDefaults]
      stringForKey:kNextPromoForDisplayOverride];
}

std::optional<UpdateChromeSafetyCheckState> GetUpdateChromeSafetyCheckState() {
  std::string state =
      base::SysNSStringToUTF8([[NSUserDefaults standardUserDefaults]
          stringForKey:kSafetyCheckUpdateChromeStateOverride]);

  return UpdateChromeSafetyCheckStateForName(state);
}

std::optional<PasswordSafetyCheckState> GetPasswordSafetyCheckState() {
  std::string state =
      base::SysNSStringToUTF8([[NSUserDefaults standardUserDefaults]
          stringForKey:kSafetyCheckPasswordStateOverride]);

  return PasswordSafetyCheckStateForName(state);
}

std::optional<SafeBrowsingSafetyCheckState> GetSafeBrowsingSafetyCheckState() {
  std::string state =
      base::SysNSStringToUTF8([[NSUserDefaults standardUserDefaults]
          stringForKey:kSafetyCheckSafeBrowsingStateOverride]);

  return SafeBrowsingSafetyCheckStateForName(state);
}

std::optional<int> GetSafetyCheckWeakPasswordsCount() {
  int weakPasswordsCount = [[NSUserDefaults standardUserDefaults]
      integerForKey:kSafetyCheckWeakPasswordsCountOverride];

  if (weakPasswordsCount == 0) {
    return std::nullopt;
  }

  return weakPasswordsCount;
}

base::TimeDelta GetReturnToHomeSurfaceDuration() {
  int duration = [[NSUserDefaults standardUserDefaults]
      integerForKey:kHomeSurfaceDuration];
  if (duration == 0) {
    return base::Hours(4);
  }
  if (duration == -1) {
    // if set to -1 the duration will be instant.
    return base::Seconds(0);
  }
  return base::Seconds(duration);
}

std::optional<int> GetFirstRunRecency() {
  int first_run_recency =
      [[NSUserDefaults standardUserDefaults] integerForKey:kFirstRunRecency];
  if (first_run_recency == 0) {
    return std::nullopt;
  }
  return first_run_recency;
}

std::optional<int> GetSafetyCheckReusedPasswordsCount() {
  int reusedPasswordsCount = [[NSUserDefaults standardUserDefaults]
      integerForKey:kSafetyCheckReusedPasswordsCountOverride];

  if (reusedPasswordsCount == 0) {
    return std::nullopt;
  }

  return reusedPasswordsCount;
}

std::optional<int> GetSafetyCheckCompromisedPasswordsCount() {
  int compromisedPasswordsCount = [[NSUserDefaults standardUserDefaults]
      integerForKey:kSafetyCheckCompromisedPasswordsCountOverride];

  if (compromisedPasswordsCount == 0) {
    return std::nullopt;
  }

  return compromisedPasswordsCount;
}

std::string GetSegmentForForcedDeviceSwitcherExperience() {
  // Checks iOS Experimental Settings.
  std::string segment =
      base::SysNSStringToUTF8([[NSUserDefaults standardUserDefaults]
          stringForKey:kForceExperienceForDeviceSwitcherExperimentalSettings]);
  if (segment.empty()) {
    // Checks command line flag.
    base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
    if (command_line->HasSwitch(
            switches::kForceDeviceSwitcherExperienceCommandLineFlag)) {
      segment = command_line->GetSwitchValueNative(
          switches::kForceDeviceSwitcherExperienceCommandLineFlag);
    }
  }
  return segment;
}

std::string GetSegmentForForcedShopperExperience() {
  // Checks iOS Experimental Settings.
  std::string segment =
      [[NSUserDefaults standardUserDefaults]
          boolForKey:kForceExperienceForShopperExperimentalSettings]
          ? segmentation_platform::kShoppingUserUmaName
          : segmentation_platform::kLegacyNegativeLabel;
  if (segment.empty()) {
    // Checks command line flag.
    base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
    if (command_line->HasSwitch(switches::kForceShopperExperience)) {
      segment =
          command_line->GetSwitchValueNative(switches::kForceShopperExperience);
    }
  }
  return segment;
}

bool SimulatePostDeviceRestore() {
  return [[NSUserDefaults standardUserDefaults]
      boolForKey:kSimulatePostDeviceRestore];
}

bool ShouldIgnoreHistorySyncDeclineLimits() {
  return [[NSUserDefaults standardUserDefaults]
      boolForKey:kShouldIgnoreHistorySyncDeclineLimits];
}

std::optional<int> GetForcedInactivityThresholdForSafetyCheckNotifications() {
  int threshold = [[NSUserDefaults standardUserDefaults]
      integerForKey:kSafetyCheckNotificationsInactivityThreshold];

  if (threshold == 0) {
    return std::nullopt;
  }

  return threshold;
}

std::optional<int> GetForcedTipsMagicStackState() {
  int tipsIdentifier = [[NSUserDefaults standardUserDefaults]
      integerForKey:kTipsMagicStackStateOverride];

  if (tipsIdentifier == 0) {
    return std::nullopt;
  }

  return tipsIdentifier;
}

bool ShouldDisplayLensShopTipWithImage() {
  return [[NSUserDefaults standardUserDefaults]
      boolForKey:kTipsMagicStackLensShopWithImage];
}

bool ShouldUseInactiveTabsDemoThreshold() {
  return
      [[NSUserDefaults standardUserDefaults] boolForKey:kInactiveTabsDemoMode];
}

bool ShouldUseInactiveTabsTestThreshold() {
  return
      [[NSUserDefaults standardUserDefaults] boolForKey:kInactiveTabsTestMode];
}

bool ShouldOpenInIncognitoOverride() {
  NSString* value = [[NSUserDefaults standardUserDefaults]
      stringForKey:kAsyncStartupOverrideResponse];
  return ([value isEqualToString:@"FirstPartyIncognitoNoDelay"] ||
          [value isEqualToString:@"FirstPartyIncognito500Delay"] ||
          [value isEqualToString:@"AlwaysShowTheUI"]);
}

bool ShouldDelayAsyncStartup() {
  NSString* value = [[NSUserDefaults standardUserDefaults]
      stringForKey:kAsyncStartupOverrideResponse];
  return ([value isEqualToString:@"FirstPartyIncognito500Delay"] ||
          [value isEqualToString:@"500ms"]);
}

bool AlwaysShowTheFirstPartyIncognitoUI() {
  NSString* value = [[NSUserDefaults standardUserDefaults]
      stringForKey:kAsyncStartupOverrideResponse];
  return [value isEqualToString:@"AlwaysShowTheUI"];
}

bool EnableAIPrototypingMenu() {
  return [[NSUserDefaults standardUserDefaults]
      boolForKey:@"EnableAIPrototypingMenu"];
}

NSString* GetLensResultPanelGwsURL() {
  return [[NSUserDefaults standardUserDefaults]
      stringForKey:kLensResultPanelGwsURL];
}

NSString* GetCobrowseGwsURL() {
  return [[NSUserDefaults standardUserDefaults] stringForKey:kCobrowseGwsURL];
}

bool ShouldForceDisableComposeboxAIM() {
  return [[NSUserDefaults standardUserDefaults]
      boolForKey:kForceDisableAIMEligibility];
}

bool ShouldForceDisableComposeboxCreateImages() {
  return [[NSUserDefaults standardUserDefaults]
      boolForKey:kForceDisableCreateImagesEligibility];
}

bool ShouldForceDisableComposeboxCanvas() {
  return [[NSUserDefaults standardUserDefaults]
      boolForKey:kForceDisableCanvasEligibility];
}

bool ShouldForceDisableComposeboxDeepSearch() {
  return [[NSUserDefaults standardUserDefaults]
      boolForKey:kForceDisableDeepSearchEligibility];
}

bool ShouldForceDisableComposeboxPdfUpload() {
  return [[NSUserDefaults standardUserDefaults]
      boolForKey:kForceDisablePdfUploadEligibility];
}

bool ShouldShowCatalogItems() {
#if BUILDFLAG(CHROMIUM_BRANDING) && !defined(NDEBUG)
  // Always show catalog items in debug builds.
  return true;
#else
  return [[NSUserDefaults standardUserDefaults] boolForKey:kShowCatalogItems];
#endif
}

bool ShouldForceMultiProfileForcedMigrationDone() {
  return [[NSUserDefaults standardUserDefaults]
      boolForKey:kForceMultiProfileForcedMigrationDone];
}

bool ShouldShowBackendPromoDebugTools() {
  return [[NSUserDefaults standardUserDefaults]
      boolForKey:kShowBackendPromoDebugTools];
}
int GetForcedPushNotificationType() {
  return [[NSUserDefaults standardUserDefaults]
      integerForKey:kForcedPushNotificationType];
}

int GetForcedPushNotificationDelay() {
  return [[NSUserDefaults standardUserDefaults]
      integerForKey:kForcedPushNotificationDelay];
}

}  // namespace experimental_flags
