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

#ifndef IOS_CHROME_BROWSER_SETTINGS_UI_BUNDLED_SETTINGS_NAVIGATION_CONTROLLER_H_
#define IOS_CHROME_BROWSER_SETTINGS_UI_BUNDLED_SETTINGS_NAVIGATION_CONTROLLER_H_

#import <UIKit/UIKit.h>

#import "ios/chrome/browser/keyboard/ui_bundled/key_command_actions.h"
#import "ios/chrome/browser/settings/ui_bundled/settings_controller_protocol.h"
#import "ios/chrome/browser/shared/public/commands/scene_commands.h"
#import "ios/chrome/browser/shared/public/commands/settings_commands.h"

class Browser;
@protocol BrowserCommands;
enum class DefaultBrowserSettingsPageSource;
@protocol SettingsRootViewControlling;
@protocol SnackbarCommands;
@class UserFeedbackData;

namespace password_manager {
struct CredentialUIEntry;
enum class PasswordCheckReferrer;
}  // namespace password_manager

namespace autofill {
class CreditCard;
}  // namespace autofill

namespace autofill::autofill_metrics {
enum class AutofillSettingsReferrer;
}  // namespace autofill::autofill_metrics

// The accessibility identifier for the settings' "Done" button.
extern NSString* const kSettingsDoneButtonId;

@protocol SettingsNavigationControllerDelegate <NSObject>

// Informs the delegate that the settings navigation controller should be
// closed.
- (void)closeSettings;

// Informs the delegate that settings navigation controller has been dismissed
// (e.g. it was swiped down). This means that closeSettings wasn't called and we
// need to perform some clean up tasks.
- (void)settingsWasDismissed;

@end

// TODO(crbug.com/516717892): Refactor to remove all delegate arguments from
// creation methods.
// Controller to modify user settings.
@interface SettingsNavigationController
    : UINavigationController <KeyCommandActions, SettingsCommands>

// Creates a new SettingsTableViewController and the chrome around it.
// `browser` is the browser where settings are being displayed and should not be
// nil nor Off-the-Record. `delegate` may be nil.
+ (instancetype)
    mainSettingsControllerForBrowser:(Browser*)browser
                            delegate:(id<SettingsNavigationControllerDelegate>)
                                         delegate
            hasDefaultBrowserBlueDot:(BOOL)hasDefaultBrowserBlueDot;

+ (instancetype)
    mainSettingsControllerForBrowser:(Browser*)browser
                            delegate:(id<SettingsNavigationControllerDelegate>)
                                         delegate
            hasDefaultBrowserBlueDot:(BOOL)hasDefaultBrowserBlueDot
     shouldShowLevelUpWalkthroughIPH:(BOOL)shouldShowLevelUpWalkthroughIPH;

// Creates a new ManageAccountsTableViewController and the chrome around it.
// `browser` is the browser where settings are being displayed and should not be
// nil.
//`showSignoutButton` whether the view should contains a "signout" button.
//`showDoneButton` whether the navigation controller top trailing corner should
// have a "Done" button.
// `signoutDismissalByParentCoordinator` if `YES` the view should not dismiss
// itself when the user is signed-out, the owning coordinator will do it.
+ (instancetype)
           accountsControllerForBrowser:(Browser*)browser
                     baseViewController:(UIViewController*)baseViewController
                               delegate:
                                   (id<SettingsNavigationControllerDelegate>)
                                       delegate
              closeSettingsOnAddAccount:(BOOL)closeSettingsOnAddAccount
                      showSignoutButton:(BOOL)showSignoutButton
                         showDoneButton:(BOOL)showDoneButton
    signoutDismissalByParentCoordinator:
        (BOOL)signoutDismissalByParentCoordinator;

// Creates a new SettingsNavigationController and the chrome around it.
// `browser` is the browser where settings are being displayed and should not be
// nil. `delegate` may be nil.
+ (instancetype)
    BWGControllerForBrowser:(Browser*)browser
                   delegate:(id<SettingsNavigationControllerDelegate>)delegate;

// Creates a new SettingsNavigationController that displays the Suggestions from
// Gemini Help Improve settings.
+ (instancetype)
    geminiHelpImproveControllerForBrowser:(Browser*)browser
                                 delegate:
                                     (id<SettingsNavigationControllerDelegate>)
                                         delegate;

// Creates a new GoogleServicesSettingsCollectionViewController and the chrome
// around it. `browser` is the browser where settings are being displayed and
// should not be nil. `delegate` may be nil.
+ (instancetype)
    googleServicesControllerForBrowser:(Browser*)browser
                              delegate:
                                  (id<SettingsNavigationControllerDelegate>)
                                      delegate;

// Creates a new SettingsNavigationController that contains only the sync
// management UI. `browser` is the browser where settings are being displayed
// and should not be nil. `delegate` may be nil. The user must be signed-in and
// sign-in must be enabled.
+ (instancetype)
    syncSettingsControllerForBrowser:(Browser*)browser
                            delegate:(id<SettingsNavigationControllerDelegate>)
                                         delegate;

// Creates a new SettingsNavigationController that displays the price tracking
// notifications UI. `browser` is the browser where settings are being displayed
// and should not be nil.
+ (instancetype)
    priceNotificationsControllerForBrowser:(Browser*)browser
                                  delegate:
                                      (id<SettingsNavigationControllerDelegate>)
                                          delegate;

// Creates a new SyncEncryptionPassphraseCollectionViewController and the chrome
// around it. `browser` is the browser where settings are being displayed and
// should not be nil. `delegate` may be nil.
// When called, the current scene must not be blocked.
+ (instancetype)
    syncPassphraseControllerForBrowser:(Browser*)browser
                              delegate:
                                  (id<SettingsNavigationControllerDelegate>)
                                      delegate;

// Creates a new view controller presenting the saved passwords list and the
// chrome around it. `browser` is the browser where settings are being displayed
// and should not be nil. `delegate` may be nil.
+ (instancetype)
    savePasswordsControllerForBrowser:(Browser*)browser
      shouldShowLevelUpWalkthroughIPH:(BOOL)shouldShowLevelUpWalkthroughIPH
                             delegate:(id<SettingsNavigationControllerDelegate>)
                                          delegate;

// Creates a new view controller presenting the Autofill and Passwords settings
// and the chrome around it. `browser` is the browser where settings are being
// displayed and should not be nil. `delegate` may be nil.
+ (instancetype)
    autofillAndPasswordsControllerForBrowser:(Browser*)browser
                                    referrer:
                                        (autofill::autofill_metrics::
                                             AutofillSettingsReferrer)referrer
                                    delegate:
                                        (id<SettingsNavigationControllerDelegate>)
                                            delegate;

// Creates a new view controller presenting the Identity Docs settings.
// `browser` is the browser where settings are being displayed and should not be
// nil. `delegate` may be nil.
+ (instancetype)
    identityDocsControllerForBrowser:(Browser*)browser
                            referrer:(autofill::autofill_metrics::
                                          AutofillSettingsReferrer)referrer
                            delegate:(id<SettingsNavigationControllerDelegate>)
                                         delegate;

// Creates a new view controller presenting the Travel settings. `browser`
// is the browser where settings are being displayed and should not be nil.
// `delegate` may be nil.
+ (instancetype)
    travelControllerForBrowser:(Browser*)browser
                      referrer:
                          (autofill::autofill_metrics::AutofillSettingsReferrer)
                              referrer
                      delegate:
                          (id<SettingsNavigationControllerDelegate>)delegate;

// Creates a new view controller presenting the Shopping settings. `browser` is
// the browser where settings are being displayed and should not be nil.
// `delegate` may be nil.
+ (instancetype)
    shoppingControllerForBrowser:(Browser*)browser
                        referrer:(autofill::autofill_metrics::
                                      AutofillSettingsReferrer)referrer
                        delegate:
                            (id<SettingsNavigationControllerDelegate>)delegate;

// Creates a new PasswordManagerViewController in search mode and the chrome
// around it. `browser` is the browser where settings are being displayed and
// should not be nil. `delegate` may be nil.
+ (instancetype)
    passwordManagerSearchControllerForBrowser:(Browser*)browser
                                     delegate:
                                         (id<SettingsNavigationControllerDelegate>)
                                             delegate;

// Creates a new PasswordDetailsViewController and the chrome around it.
// `browser` is the browser where the view is being displayed and should not be
// nil. `delegate` button should be shown in the upper left corner if the
// navigation stack is empty.
+ (instancetype)
    passwordDetailsControllerForBrowser:(Browser*)browser
                               delegate:
                                   (id<SettingsNavigationControllerDelegate>)
                                       delegate
                             credential:
                                 (password_manager::CredentialUIEntry)credential
                             inEditMode:(BOOL)editMode;

// Creates a new CredentialImportViewController displayed from a
// PasswordManagerViewController and the chrome around it. `browser` is the
// browser where settings are being displayed and should not be nil. `delegate`
// may be nil. `UUID` is a token received from the OS during app launch needed
// to receive credentials from an OS library.
+ (instancetype)
    credentialImportControllerForBrowser:(Browser*)browser
                                delegate:
                                    (id<SettingsNavigationControllerDelegate>)
                                        delegate
                                    UUID:(NSUUID*)UUID API_AVAILABLE(ios(26.0));

// Creates a new AutofillProfileEditTableViewHelper and the
// chrome around it. `browser` is the browser where settings are being displayed
// and should not be nil. `delegate` may be nil. `address` is the address for
// which the details should be opened.
+ (instancetype)
    addressDetailsControllerForBrowser:(Browser*)browser
                              delegate:
                                  (id<SettingsNavigationControllerDelegate>)
                                      delegate
                               address:(autofill::AutofillProfile)address
                            inEditMode:(BOOL)editMode
                 offerMigrateToAccount:(BOOL)offerMigrateToAccount;

// Creates a new AutofillProfileTableViewController and the chrome around
// it. `browser` is the browser where settings are being displayed and should
// not be nil. `delegate` may be nil.
+ (instancetype)
    autofillProfileControllerForBrowser:(Browser*)browser
                               delegate:
                                   (id<SettingsNavigationControllerDelegate>)
                                       delegate;

// Creates a new PrivacyController `browser` is the browser where settings are
// being displayed and should not be nil. `delegate` may be nil.
+ (instancetype)
    privacyControllerForBrowser:(Browser*)browser
                       delegate:
                           (id<SettingsNavigationControllerDelegate>)delegate;

// Creates a new AutofillCreditCardCollectionViewController and the chrome
// around it. `browser` is the browser where settings are being displayed and
// should not be nil. `delegate` may be nil.
+ (instancetype)
    autofillCreditCardControllerForBrowser:(Browser*)browser
                                  delegate:
                                      (id<SettingsNavigationControllerDelegate>)
                                          delegate;

// Creates a new AutofillCreditCardEditTableViewController and the chrome around
// it. `browser` is the browser where settings are being displayed and should
// not be nil. `delegate` may be nil.
+ (instancetype)
    autofillCreditCardEditControllerForBrowser:(Browser*)browser
                                      delegate:
                                          (id<SettingsNavigationControllerDelegate>)
                                              delegate
                                    creditCard:(autofill::CreditCard)creditCard
                                    inEditMode:(BOOL)editMode;

// Creates a new DefaultBrowserSettingsTableViewController and the chrome
// around it. `browser` is the browser where settings are being displayed and
// should not be nil. `delegate` may be nil.
+ (instancetype)
    defaultBrowserControllerForBrowser:(Browser*)browser
                              delegate:
                                  (id<SettingsNavigationControllerDelegate>)
                                      delegate
                          sourceForUMA:(DefaultBrowserSettingsPageSource)source;

// Creates a new SearchEngineTableViewController to select the default search
// engine used by Chrome. `browser` is the browser where settings are being
// displayed and should not be nil. `delegate` may be nil.
+ (instancetype)
    defaultSearchEngineControllerForBrowser:(Browser*)browser
                                   delegate:
                                       (id<SettingsNavigationControllerDelegate>)
                                           delegate;

// Creates a new SafetyCheckTableViewController and the chrome
// around it. `browser` is the browser where settings are being displayed and
// should not be nil. `delegate` may be nil. `referrer` represents where in the
// app the Safety Check is being requested from.
+ (instancetype)
    safetyCheckControllerForBrowser:(Browser*)browser
                           delegate:(id<SettingsNavigationControllerDelegate>)
                                        delegate
                           referrer:(password_manager::PasswordCheckReferrer)
                                        referrer;

// Creates a new PrivacySafeBrowsingViewController and the chrome
// around it. `browser` is the browser where settings are being displayed and
// should not be nil. `delegate` may be nil.
+ (instancetype)
    safeBrowsingControllerForBrowser:(Browser*)browser
                            delegate:(id<SettingsNavigationControllerDelegate>)
                                         delegate;

// Creates a new InactiveTabsSettingsTableViewController and the chrome around
// it. `browser` is the browser where settings are being displayed and
// should not be nil. `delegate` may be nil.
+ (instancetype)
    inactiveTabsControllerForBrowser:(Browser*)browser
                            delegate:(id<SettingsNavigationControllerDelegate>)
                                         delegate;

// Creates a new ContentSettingTableViewController and the chrome
// around it. `browser` is the browser where settings are being displayed and
// should not be nil. `delegate` may be nil.
+ (instancetype)
    contentSettingsControllerForBrowser:(Browser*)browser
                               delegate:
                                   (id<SettingsNavigationControllerDelegate>)
                                       delegate;

// Creates a new NotificationsViewController and the chrome around it. `browser`
// is the browser where settings are being displayed and should not be nil.
// `delegate` may be nil.
+ (instancetype)
    notificationsSettingsControllerForBrowser:(Browser*)browser
                                       client:(std::optional<
                                                  PushNotificationClientId>)
                                                  clientID
                                     delegate:
                                         (id<SettingsNavigationControllerDelegate>)
                                             delegate;

// Initializes the UINavigationController with `rootViewController`.
- (instancetype)initWithRootViewController:(UIViewController*)rootViewController
                                   browser:(Browser*)browser
                                  delegate:
                                      (id<SettingsNavigationControllerDelegate>)
                                          delegate NS_DESIGNATED_INITIALIZER;

- (instancetype)initWithRootViewController:(UIViewController*)rootViewController
    NS_UNAVAILABLE;
- (instancetype)initWithNavigationBarClass:(Class)navigationBarClass
                              toolbarClass:(Class)toolbarClass NS_UNAVAILABLE;
- (instancetype)initWithNibName:(NSString*)nibNameOrNil
                         bundle:(NSBundle*)nibBundleOrNil NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;

// Returns a new Cancel button for a UINavigationItem which will call
// `closeSettings` when it is pressed. Should only be called by view controllers
// owned by SettingsNavigationController.
- (UIBarButtonItem*)cancelButton;

// Returns a new Done button for a UINavigationItem which will call
// `closeSettings` when it is pressed. Should only be called by view controllers
// owned by SettingsNavigationController.
- (UIBarButtonItem*)doneButton;

// Notifies this `SettingsNavigationController` of a dismissal such
// that it has a possibility to do necessary clean up.
- (void)cleanUpSettings;

// Closes this `SettingsNavigationController` by asking its delegate.
- (void)closeSettings;

// Pops the top view controller if there exists more than one view controller in
// the navigation stack. Closes the settings if the top view controller is the
// only view controller in the navigation stack.
- (void)popViewControllerOrCloseSettingsAnimated:(BOOL)animated;

@end

#endif  // IOS_CHROME_BROWSER_SETTINGS_UI_BUNDLED_SETTINGS_NAVIGATION_CONTROLLER_H_
