// Copyright 2017 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_AUTOFILL_MODEL_AUTOFILL_TAB_HELPER_H_
#define IOS_CHROME_BROWSER_AUTOFILL_MODEL_AUTOFILL_TAB_HELPER_H_

#import <memory>

#import "base/memory/raw_ptr.h"
#import "components/autofill/ios/form_util/child_frame_registrar.h"
#import "ios/web/public/web_state_observer.h"
#import "ios/web/public/web_state_user_data.h"

@class AutofillAgent;
@class AutofillAgentDelegate;
@protocol AutofillCommands;
@protocol AtMemoryCommands;
@protocol FormSuggestionProvider;
@protocol SnackbarCommands;
@class UIViewController;

namespace autofill {
class AutofillClientIOS;
class ChromeAutofillClientIOS;
}

// Class binding an instance of AutofillAgent to a WebState.
class AutofillTabHelper : public web::WebStateObserver,
                          public web::WebStateUserData<AutofillTabHelper>,
                          public autofill::ChildFrameRegistrarObserver {
 public:
  AutofillTabHelper(const AutofillTabHelper&) = delete;
  AutofillTabHelper& operator=(const AutofillTabHelper&) = delete;

  ~AutofillTabHelper() override;

  // Sets a weak reference to the view controller used to present UI.
  void SetBaseViewController(UIViewController* base_view_controller);

  void SetAutofillHandler(id<AutofillCommands> autofill_handler);
  // Sets the handlers for the UI commands. `snackbar_handler` handles snackbar
  // commands and `at_memory_handler` handles AtMemory commands.
  void SetCommandHandlers(id<SnackbarCommands> snackbar_handler,
                          id<AtMemoryCommands> at_memory_handler);

  // Returns an object that can provide Autofill suggestions.
  id<FormSuggestionProvider> GetSuggestionProvider();

  autofill::AutofillClientIOS* autofill_client();

 private:
  friend class web::WebStateUserData<AutofillTabHelper>;

  explicit AutofillTabHelper(web::WebState* web_state);

  // web::WebStateObserver implementation.
  void WebStateDestroyed(web::WebState* web_state) override;

  // autofill::ChildFrameRegistrarObserver implementation.
  void OnDidDoubleRegistration(autofill::LocalFrameToken local) override;

  // Re-creates `autofill_agent_delegate_` with the current command handlers and
  // assigns it to the `autofill_agent_`. If `snackbar_handler_` is nil, both
  // the delegate and its assignment are nilled out.
  void UpdateAutofillAgentDelegate();

  // The handlers.
  __weak id<SnackbarCommands> snackbar_handler_;
  __weak id<AtMemoryCommands> at_memory_handler_;

  // The delegate for the AutofillAgent.
  __strong AutofillAgentDelegate* autofill_agent_delegate_;

  // The Objective-C AutofillAgent instance.
  __strong AutofillAgent* autofill_agent_;

  // The iOS AutofillClient instance.
  std::unique_ptr<autofill::ChromeAutofillClientIOS> autofill_client_;

  // The WebState holding this instance of the helper.
  raw_ptr<web::WebState> web_state_;

  // Scoped WebState observation.
  base::ScopedObservation<web::WebState, web::WebStateObserver>
      web_state_observation_{this};
};

#endif  // IOS_CHROME_BROWSER_AUTOFILL_MODEL_AUTOFILL_TAB_HELPER_H_
