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

#import "ios/web/navigation/legacy_navigation_manager_impl.h"

#include <stddef.h>

#include <utility>

#include "base/logging.h"
#import "ios/web/navigation/crw_session_controller+private_constructors.h"
#import "ios/web/navigation/crw_session_controller.h"
#import "ios/web/navigation/navigation_item_impl.h"
#import "ios/web/navigation/navigation_item_impl_list.h"
#import "ios/web/navigation/navigation_manager_delegate.h"
#include "ios/web/public/load_committed_details.h"
#import "ios/web/public/navigation_item.h"
#include "ios/web/public/reload_type.h"
#import "ios/web/public/web_client.h"
#import "ios/web/public/web_state/web_state.h"
#include "ui/base/page_transition_types.h"

#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif

namespace web {

LegacyNavigationManagerImpl::LegacyNavigationManagerImpl() = default;

LegacyNavigationManagerImpl::~LegacyNavigationManagerImpl() {
  [session_controller_ setNavigationManager:nullptr];
}

void LegacyNavigationManagerImpl::SetBrowserState(BrowserState* browser_state) {
  NavigationManagerImpl::SetBrowserState(browser_state);
  [session_controller_ setBrowserState:browser_state];
}

void LegacyNavigationManagerImpl::SetSessionController(
    CRWSessionController* session_controller) {
  session_controller_ = session_controller;
  [session_controller_ setNavigationManager:this];
}

void LegacyNavigationManagerImpl::InitializeSession() {
  SetSessionController(
      [[CRWSessionController alloc] initWithBrowserState:browser_state_]);
}

void LegacyNavigationManagerImpl::OnNavigationItemsPruned(
    size_t pruned_item_count) {
  delegate_->OnNavigationItemsPruned(pruned_item_count);
}

void LegacyNavigationManagerImpl::OnNavigationItemChanged() {
  delegate_->OnNavigationItemChanged();
}

void LegacyNavigationManagerImpl::OnNavigationItemCommitted() {
  LoadCommittedDetails details;
  details.item = GetLastCommittedItem();
  DCHECK(details.item);
  details.previous_item_index = [session_controller_ previousItemIndex];
  if (details.previous_item_index >= 0) {
    DCHECK([session_controller_ previousItem]);
    details.is_in_page = IsFragmentChangeNavigationBetweenUrls(
        [session_controller_ previousItem]->GetURL(), details.item->GetURL());
  } else {
    details.is_in_page = NO;
  }

  delegate_->OnNavigationItemCommitted(details);
}

CRWSessionController* LegacyNavigationManagerImpl::GetSessionController()
    const {
  return session_controller_;
}

void LegacyNavigationManagerImpl::AddTransientItem(const GURL& url) {
  [session_controller_ addTransientItemWithURL:url];

  // TODO(crbug.com/676129): Transient item is only supposed to be added for
  // pending non-app-specific loads, but pending item can be null because of the
  // bug. The workaround should be removed once the bug is fixed.
  NavigationItem* item = GetPendingItem();
  if (!item)
    item = GetLastCommittedNonAppSpecificItem();
  // |item| may still be nullptr if NTP is the only entry in the session.
  // See https://crbug.com/822908 for details.
  if (item) {
    DCHECK(item->GetUserAgentType() != UserAgentType::NONE);
    GetTransientItem()->SetUserAgentType(item->GetUserAgentType());
  }
}

void LegacyNavigationManagerImpl::AddPendingItem(
    const GURL& url,
    const web::Referrer& referrer,
    ui::PageTransition navigation_type,
    NavigationInitiationType initiation_type,
    UserAgentOverrideOption user_agent_override_option) {
  [session_controller_ addPendingItem:url
                             referrer:referrer
                           transition:navigation_type
                       initiationType:initiation_type
              userAgentOverrideOption:user_agent_override_option];

  if (!GetPendingItem()) {
    return;
  }

  UpdatePendingItemUserAgentType(user_agent_override_option,
                                 GetLastCommittedNonAppSpecificItem(),
                                 GetPendingItem());
}

void LegacyNavigationManagerImpl::CommitPendingItem() {
  [session_controller_ commitPendingItem];
}

BrowserState* LegacyNavigationManagerImpl::GetBrowserState() const {
  return browser_state_;
}

WebState* LegacyNavigationManagerImpl::GetWebState() const {
  return delegate_->GetWebState();
}

NavigationItem* LegacyNavigationManagerImpl::GetVisibleItem() const {
  return [session_controller_ visibleItem];
}

void LegacyNavigationManagerImpl::DiscardNonCommittedItems() {
  [session_controller_ discardNonCommittedItems];
}

int LegacyNavigationManagerImpl::GetItemCount() const {
  return session_controller_ ? [session_controller_ items].size() : 0;
}

NavigationItem* LegacyNavigationManagerImpl::GetItemAtIndex(
    size_t index) const {
  return GetNavigationItemImplAtIndex(index);
}

NavigationItemImpl* LegacyNavigationManagerImpl::GetNavigationItemImplAtIndex(
    size_t index) const {
  return [session_controller_ itemAtIndex:index];
}

int LegacyNavigationManagerImpl::GetIndexOfItem(
    const web::NavigationItem* item) const {
  return [session_controller_ indexOfItem:item];
}

int LegacyNavigationManagerImpl::GetPendingItemIndex() const {
  if (GetPendingItem()) {
    if ([session_controller_ pendingItemIndex] != -1) {
      return [session_controller_ pendingItemIndex];
    }
    // TODO(crbug.com/665189): understand why last committed item index is
    // returned here.
    return GetLastCommittedItemIndex();
  }
  return -1;
}

int LegacyNavigationManagerImpl::GetLastCommittedItemIndex() const {
  if (GetItemCount() == 0)
    return -1;
  return [session_controller_ lastCommittedItemIndex];
}

bool LegacyNavigationManagerImpl::RemoveItemAtIndex(int index) {
  if (index == GetLastCommittedItemIndex() || index == GetPendingItemIndex())
    return false;

  if (index < 0 || index >= GetItemCount())
    return false;

  [session_controller_ removeItemAtIndex:index];
  return true;
}

bool LegacyNavigationManagerImpl::CanGoBack() const {
  return CanGoToOffset(-1);
}

bool LegacyNavigationManagerImpl::CanGoForward() const {
  return CanGoToOffset(1);
}

bool LegacyNavigationManagerImpl::CanGoToOffset(int offset) const {
  int index = GetIndexForOffset(offset);
  return 0 <= index && index < GetItemCount();
}

void LegacyNavigationManagerImpl::GoBack() {
  GoToIndex(GetIndexForOffset(-1));
}

void LegacyNavigationManagerImpl::GoForward() {
  GoToIndex(GetIndexForOffset(1));
}

NavigationItemList LegacyNavigationManagerImpl::GetBackwardItems() const {
  return [session_controller_ backwardItems];
}

NavigationItemList LegacyNavigationManagerImpl::GetForwardItems() const {
  return [session_controller_ forwardItems];
}

void LegacyNavigationManagerImpl::Restore(
    int last_committed_item_index,
    std::vector<std::unique_ptr<NavigationItem>> items) {
  WillRestore(items.size());

  DCHECK(GetItemCount() == 0 && !GetPendingItem());
  DCHECK_LT(last_committed_item_index, static_cast<int>(items.size()));
  DCHECK(items.empty() || last_committed_item_index >= 0);
  SetSessionController([[CRWSessionController alloc]
        initWithBrowserState:browser_state_
             navigationItems:std::move(items)
      lastCommittedItemIndex:last_committed_item_index]);
}

void LegacyNavigationManagerImpl::CopyStateFromAndPrune(
    const NavigationManager* manager) {
  DCHECK(manager);
  CRWSessionController* other_session =
      static_cast<const NavigationManagerImpl*>(manager)
          ->GetSessionController();
  [session_controller_ copyStateFromSessionControllerAndPrune:other_session];
}

bool LegacyNavigationManagerImpl::CanPruneAllButLastCommittedItem() const {
  return [session_controller_ canPruneAllButLastCommittedItem];
}

int LegacyNavigationManagerImpl::GetIndexForOffset(int offset) const {
  int result = [session_controller_ pendingItemIndex] == -1
                   ? GetLastCommittedItemIndex()
                   : static_cast<int>([session_controller_ pendingItemIndex]);

  if (offset < 0) {
    if (GetTransientItem() && [session_controller_ pendingItemIndex] == -1) {
      // Going back from transient item that added to the end navigation stack
      // is a matter of discarding it as there is no need to move navigation
      // index back.
      offset++;
    }

    while (offset < 0 && result > 0) {
      // To stop the user getting 'stuck' on redirecting pages they weren't
      // even aware existed, it is necessary to pass over pages that would
      // immediately result in a redirect (the item *before* the redirected
      // page).
      while (result > 0) {
        const NavigationItem* item = GetItemAtIndex(result);
        if (!ui::PageTransitionIsRedirect(item->GetTransitionType()))
          break;
        --result;
      }
      --result;
      ++offset;
    }
    // Result may be out of bounds, so stop trying to skip redirect items and
    // simply add the remainder.
    result += offset;
    if (result > GetItemCount() /* overflow */)
      result = INT_MIN;
  } else if (offset > 0) {
    while (offset > 0 && result < GetItemCount()) {
      ++result;
      --offset;
      // As with going back, skip over redirects.
      while (result + 1 < GetItemCount()) {
        const NavigationItem* item = GetItemAtIndex(result + 1);
        if (!ui::PageTransitionIsRedirect(item->GetTransitionType()))
          break;
        ++result;
      }
    }
    // Result may be out of bounds, so stop trying to skip redirect items and
    // simply add the remainder.
    result += offset;
    if (result < 0 /* overflow */)
      result = INT_MAX;
  }

  return result;
}

NavigationItemImpl* LegacyNavigationManagerImpl::GetLastCommittedItemImpl()
    const {
  return [session_controller_ lastCommittedItem];
}

NavigationItemImpl* LegacyNavigationManagerImpl::GetPendingItemImpl() const {
  return [session_controller_ pendingItem];
}

NavigationItemImpl* LegacyNavigationManagerImpl::GetTransientItemImpl() const {
  return [session_controller_ transientItem];
}

void LegacyNavigationManagerImpl::FinishGoToIndex(int index,
                                                  NavigationInitiationType type,
                                                  bool has_user_gesture) {
  const ScopedNavigationItemImplList& items = [session_controller_ items];
  NavigationItem* to_item = items[index].get();
  NavigationItem* previous_item = GetLastCommittedItem();

  to_item->SetTransitionType(ui::PageTransitionFromInt(
      to_item->GetTransitionType() | ui::PAGE_TRANSITION_FORWARD_BACK));

  bool same_document_navigation =
      [session_controller_ isSameDocumentNavigationBetweenItem:previous_item
                                                       andItem:to_item];
  if (same_document_navigation) {
    [session_controller_ goToItemAtIndex:index discardNonCommittedItems:YES];
    delegate_->OnGoToIndexSameDocumentNavigation(type, has_user_gesture);
  } else {
    [session_controller_ discardNonCommittedItems];
    [session_controller_ setPendingItemIndex:index];
    delegate_->LoadCurrentItem();
  }
}

int LegacyNavigationManagerImpl::GetPreviousItemIndex() const {
  return base::checked_cast<int>([session_controller_ previousItemIndex]);
}

void LegacyNavigationManagerImpl::SetPreviousItemIndex(
    int previous_item_index) {
  [session_controller_ setPreviousItemIndex:previous_item_index];
}

void LegacyNavigationManagerImpl::AddPushStateItemIfNecessary(
    const GURL& url,
    NSString* state_object,
    ui::PageTransition transition) {
  [session_controller_ pushNewItemWithURL:url
                              stateObject:state_object
                               transition:transition];
}

}  // namespace web
