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

#import "ios/chrome/browser/find_in_page/model/find_tab_helper.h"

#import "base/check.h"
#import "ios/chrome/browser/find_in_page/model/find_in_page_controller.h"
#import "ios/chrome/browser/find_in_page/model/find_in_page_model.h"
#import "ios/chrome/browser/fullscreen/public/scoped_force_fullscreen.h"
#import "ios/chrome/browser/fullscreen/ui_bundled/fullscreen_controller.h"
#import "ios/chrome/browser/shared/public/commands/fullscreen_commands.h"
#import "ios/chrome/browser/shared/public/features/features.h"
#import "ios/web/public/navigation/navigation_context.h"

FindTabHelper::FindTabHelper(web::WebState* web_state) {
  DCHECK(web_state);
  CHECK(web_state->IsRealized());
  observation_.Observe(web_state);
  controller_ = [[FindInPageController alloc] initWithWebState:web_state];
}

FindTabHelper::~FindTabHelper() {
  CHECK(!controller_);
}

void FindTabHelper::DismissFindNavigator() {
  // Same as `StopFinding()` except the UI is not marked as inactive so it can
  // be set back up if needed later.
  if (IsFullscreenRefactoringEnabled()) {
    scoped_force_fullscreen_.reset();
  }
  [controller_ disableFindInPage];
}

void FindTabHelper::SetFullscreenController(
    FullscreenController* fullscreen_controller) {
  if (!fullscreen_controller) {
    // If the tab helper is being disconnected from the browser then stop the
    // find session.
    StopFinding();
  }
  DCHECK(controller_);
  controller_.fullscreenController = fullscreen_controller;
}

void FindTabHelper::SetFullscreenHandler(
    id<FullscreenCommands> fullscreen_handler) {
  if (!fullscreen_handler) {
    // If the tab helper is being disconnected from the browser then stop the
    // find session.
    StopFinding();
  }
  fullscreen_handler_ = fullscreen_handler;
}

void FindTabHelper::SetResponseDelegate(
    id<FindInPageResponseDelegate> response_delegate) {
  if (!controller_) {
    response_delegate_ = response_delegate;
  } else {
    controller_.responseDelegate = response_delegate;
  }
}

void FindTabHelper::StartFinding(NSString* search_string) {
  [controller_ findStringInPage:search_string];
}

void FindTabHelper::ContinueFinding(FindDirection direction) {
  if (direction == FORWARD) {
    [controller_ findNextStringInPage];

  } else if (direction == REVERSE) {
    [controller_ findPreviousStringInPage];

  } else {
    NOTREACHED();
  }
}

void FindTabHelper::StopFinding() {
  if (!IsFindUIActive()) {
    return;
  }
  SetFindUIActive(false);
  [controller_ disableFindInPage];
}

FindInPageModel* FindTabHelper::GetFindResult() const {
  return controller_.findInPageModel;
}

bool FindTabHelper::CurrentPageSupportsFindInPage() const {
  return [controller_ canFindInPage];
}

bool FindTabHelper::IsFindUIActive() const {
  return controller_.findInPageModel.enabled;
}

void FindTabHelper::SetFindUIActive(bool active) {
  controller_.findInPageModel.enabled = active;
  if (IsFullscreenRefactoringEnabled()) {
    if (active) {
      scoped_force_fullscreen_ = std::make_unique<ScopedForceFullscreen>(
          fullscreen_handler_, ForceFullscreenFeature::kFindInPage);
    } else {
      scoped_force_fullscreen_.reset();
    }
  }
}

void FindTabHelper::PersistSearchTerm() {
  [controller_ saveSearchTerm];
}

void FindTabHelper::RestoreSearchTerm() {
  [controller_ restoreSearchTerm];
}

void FindTabHelper::WebStateDestroyed(web::WebState* web_state) {
  observation_.Reset();
  scoped_force_fullscreen_.reset();
  fullscreen_handler_ = nil;

  [controller_ detachFromWebState];
  controller_ = nil;
}

void FindTabHelper::DidFinishNavigation(
    web::WebState* web_state,
    web::NavigationContext* navigation_context) {
  if (navigation_context->IsSameDocument()) {
    return;
  }

  StopFinding();
}
