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

#include "chrome/browser/ui/ash/capture_mode/search_results_view.h"

#include "ash/capture_mode/capture_mode_controller.h"
#include "ash/capture_mode/capture_mode_session.h"
#include "ash/constants/ash_features.h"
#include "ash/public/cpp/capture_mode/capture_mode_api.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/ash/web_view/ash_web_view_impl.h"
#include "chrome/browser/ui/navigator/browser_navigator.h"
#include "chrome/browser/ui/navigator/browser_navigator_params.h"
#include "content/public/browser/web_contents.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/window_open_disposition.h"

namespace ash {

namespace {

// The rounded corners for the web view.
constexpr gfx::RoundedCornersF kRoundedCorners(16);

AshWebView::InitParams GetInitParams() {
  AshWebView::InitParams params;
  params.suppress_navigation = true;
  params.rounded_corners = kRoundedCorners;
  return params;
}

// Modifies `new_tab_params` to open in a new tab.
void OpenURLFromTabInternal(NavigateParams& new_tab_params) {
  new_tab_params.window_action = NavigateParams::WindowAction::kShowWindow;
  Navigate(&new_tab_params);
}

}  // namespace

SearchResultsView::SearchResultsView() : AshWebViewImpl(GetInitParams()) {
  // We should not use `CanShowSunfishUi` here, as that could change between
  // sending the region and receiving a URL which will then create this view
  // (for example, if the Sunfish policy changes).
  DCHECK(features::IsSunfishFeatureEnabled());
}

SearchResultsView::~SearchResultsView() = default;

content::WebContents* SearchResultsView::OpenURLFromTab(
    content::WebContents* source,
    const content::OpenURLParams& params,
    base::OnceCallback<void(content::NavigationHandle&)>
        navigation_handle_callback) {
  // Open the URL specified by `params` in a new tab.
  NavigateParams new_tab_params(static_cast<BrowserWindowInterface*>(nullptr),
                                params.url, params.transition);
  switch (params.disposition) {
    case WindowOpenDisposition::UNKNOWN:
    case WindowOpenDisposition::NEW_BACKGROUND_TAB:
    case WindowOpenDisposition::CURRENT_TAB:
    case WindowOpenDisposition::SINGLETON_TAB:
      new_tab_params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
      break;
    case WindowOpenDisposition::NEW_FOREGROUND_TAB:
    case WindowOpenDisposition::NEW_POPUP:
    case WindowOpenDisposition::NEW_WINDOW:
    case WindowOpenDisposition::SAVE_TO_DISK:
    case WindowOpenDisposition::OFF_THE_RECORD:
    case WindowOpenDisposition::IGNORE_ACTION:
    case WindowOpenDisposition::SWITCH_TO_TAB:
    case WindowOpenDisposition::NEW_PICTURE_IN_PICTURE:
    case WindowOpenDisposition::NEW_SPLIT_VIEW:
      // These other dispositions will open new windows / tabs, so use these
      // dispositions as-is.
      new_tab_params.disposition = params.disposition;
      break;
  }
  new_tab_params.initiating_profile =
      Profile::FromBrowserContext(source->GetBrowserContext());
  OpenURLFromTabInternal(new_tab_params);

  if (auto* controller = CaptureModeController::Get()) {
    controller->OnSearchResultClicked();
  }
  return new_tab_params.navigated_or_inserted_contents;
}

bool SearchResultsView::IsWebContentsCreationOverridden(
    content::RenderFrameHost* opener,
    content::SiteInstance* source_site_instance,
    content::mojom::WindowContainerType window_container_type,
    const GURL& opener_url,
    const std::string& frame_name,
    const GURL& target_url) {
  // All navigation attempts are suppressed by `suppress_navigation`, which is
  // needed to override opening links in `OpenURLFromTab()`. Ensure new web
  // contents also open in new tabs. See
  // `AshWebViewImpl::NotifyDidSuppressNavigation()`.
  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
      FROM_HERE,
      base::BindOnce(
          [](const base::WeakPtr<SearchResultsView>& self, GURL url) {
            if (self) {
              self->OpenURLFromTab(
                  self->web_contents(),
                  content::OpenURLParams(
                      url, content::Referrer(),
                      WindowOpenDisposition::NEW_FOREGROUND_TAB,
                      ui::PAGE_TRANSITION_LINK,
                      /*is_renderer_initiated=*/false),
                  /*navigation_handle_callback=*/{});
            }
          },
          weak_factory_.GetWeakPtr(), target_url));
  return false;
}

bool SearchResultsView::TakeFocus(content::WebContents* web_contents,
                                  bool reverse) {
  // If we are in a capture session, we need the `CaptureModeSessionFocusCycler`
  // to handle focus traversal differently.
  auto* controller = CaptureModeController::Get();
  if (controller->IsActive()) {
    return controller->capture_mode_session()->TakeFocusForSearchResultsPanel(
        reverse);
  }

  return AshWebViewImpl::TakeFocus(web_contents, reverse);
}

void SearchResultsView::OnWebContentsFocused(
    content::RenderWidgetHost* render_widget_host) {
  // Make sure we aren't pseudo focusing another capture session item when the
  // web contents take focus.
  auto* controller = CaptureModeController::Get();
  if (controller->IsActive()) {
    controller->capture_mode_session()->ClearPseudoFocus();
    // The session focus cycler may have set a different a11y override window
    // when the web contents take focus, so we'll need to set it back to the
    // panel for screenreaders like ChromeVox to work properly.
    controller->capture_mode_session()
        ->SetA11yOverrideWindowToSearchResultsPanel();
  }

  AshWebViewImpl::OnWebContentsFocused(render_widget_host);
}

BEGIN_METADATA(SearchResultsView)
END_METADATA

}  // namespace ash
