// Copyright 2019 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_URL_LOADING_MODEL_SCENE_URL_LOADING_SERVICE_H_
#define IOS_CHROME_BROWSER_URL_LOADING_MODEL_SCENE_URL_LOADING_SERVICE_H_

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

#import <memory>
#import <string>
#import <unordered_map>

#import "base/ios/block_types.h"
#import "ios/chrome/app/application_delegate/tab_opening.h"
#import "ios/chrome/app/application_mode.h"
#import "ios/chrome/browser/url_loading/model/url_interceptor.h"
#import "ui/base/page_transition_types.h"
#import "url/gurl.h"

class Browser;
struct UrlLoadParams;
class UrlLoadingBrowserAgent;

// Objective-C delegate for SceneUrlLoadingService.
@protocol SceneURLLoadingServiceDelegate

// Sets the current interface to `ApplicationMode::INCOGNITO` or
// `ApplicationMode::NORMAL`.
- (void)setCurrentInterfaceForMode:(ApplicationMode)mode;

// Opens a tab in the target BVC, and switches to it in a way that's appropriate
// to the current UI.
// If the current tab in `targetMode` is a NTP, it can be reused to open URL.
// `completion` is executed after the tab is opened. After Tab is open the
// virtual URL is set to the pending navigation item.
- (void)openSelectedTabInMode:(ApplicationModeForTabOpening)targetMode
            withUrlLoadParams:(const UrlLoadParams&)urlLoadParams
                   completion:(ProceduralBlock)completion;

// Open the list of URLs contained in `URLs` in Incognito mode if
// `inIncognitoMode` is YES. `completion` is executed after all the tabs are
// opened.
- (void)openMultipleTabsWithURLs:(const std::vector<GURL>&)URLs
                 inIncognitoMode:(BOOL)incognitoMode
                      completion:(ProceduralBlock)completion;

// Opens a new tab as if originating from `originPoint` and `focusOmnibox`.
- (void)openNewTabFromOriginPoint:(CGPoint)originPoint
                     focusOmnibox:(BOOL)focusOmnibox
                    inheritOpener:(BOOL)inheritOpener;

// Returns the URL Loading browser agent to load a tab in `incognito` or not.
- (UrlLoadingBrowserAgent*)browserAgentForIncognito:(BOOL)incognito;

// TODO(crbug.com/41427539): refactor to remove this and most methods above.
@property(nonatomic, readonly) Browser* currentBrowserForURLLoading;

@end

// Service used to manage url loading at scene level.
class SceneUrlLoadingService {
 public:
  SceneUrlLoadingService();
  virtual ~SceneUrlLoadingService();

  void SetDelegate(id<SceneURLLoadingServiceDelegate> delegate);

  // Opens a url based on `params` in a new tab.
  virtual void LoadUrlInNewTab(const UrlLoadParams& params);

  // Returns the current active browser in the scene owning this object.
  virtual Browser* GetCurrentBrowser();

  // Returns the URL Loading browser agent to load a tab in `incognito` or not.
  virtual UrlLoadingBrowserAgent* GetBrowserAgent(bool incognito);

  // Adds an interceptor for the given URL.
  // Returns false if an interceptor overlapping with `url` is already
  // registered.
  [[nodiscard]] bool AddInterceptor(
      const GURL& url,
      std::unique_ptr<URLInterceptor> interceptor);

  // Removes the interceptor for the given URL.
  void RemoveInterceptor(const GURL& url);

  // Checks if any interceptor matches the URL in `params`. Returns true if
  // interception happened and normal flow should be prevented.
  bool OnIntercept(const UrlLoadParams& params);

 private:
  __weak id<SceneURLLoadingServiceDelegate> delegate_;

  std::unordered_map<std::string, std::unique_ptr<URLInterceptor>>
      interceptors_;
};

#endif  // IOS_CHROME_BROWSER_URL_LOADING_MODEL_SCENE_URL_LOADING_SERVICE_H_
