// 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/chrome/browser/web_state_list/web_state_list.h"

#include <algorithm>
#include <utility>

#include "base/auto_reset.h"
#include "base/logging.h"
#import "ios/chrome/browser/web_state_list/web_state_list_delegate.h"
#import "ios/chrome/browser/web_state_list/web_state_list_observer.h"
#import "ios/chrome/browser/web_state_list/web_state_list_order_controller.h"
#import "ios/chrome/browser/web_state_list/web_state_opener.h"
#import "ios/web/public/navigation_manager.h"
#import "ios/web/public/web_state/web_state.h"

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

namespace {

// Returns whether the given flag is set in a flagset.
bool IsInsertionFlagSet(int flagset, WebStateList::InsertionFlags flag) {
  return (flagset & flag) == flag;
}

// Returns whether the given flag is set in a flagset.
bool IsClosingFlagSet(int flagset, WebStateList::ClosingFlags flag) {
  return (flagset & flag) == flag;
}

}  // namespace

// Wrapper around a WebState stored in a WebStateList.
class WebStateList::WebStateWrapper {
 public:
  explicit WebStateWrapper(std::unique_ptr<web::WebState> web_state);
  ~WebStateWrapper();

  web::WebState* web_state() const { return web_state_.get(); }

  // Replaces the wrapped WebState (and clear associated state) and returns the
  // old WebState after forfeiting ownership.
  std::unique_ptr<web::WebState> ReplaceWebState(
      std::unique_ptr<web::WebState> web_state);

  // Gets and sets information about this WebState opener. The navigation index
  // is used to detect navigation changes during the same session.
  WebStateOpener opener() const { return opener_; }
  void set_opener(WebStateOpener opener) { opener_ = opener; }

  // Returns whether |opener| spawned the wrapped WebState. If |use_group| is
  // true, also use the opener navigation index to detect navigation changes
  // during the same session.
  bool WasOpenedBy(const web::WebState* opener,
                   int opener_navigation_index,
                   bool use_group) const;

 private:
  std::unique_ptr<web::WebState> web_state_;
  WebStateOpener opener_;

  DISALLOW_COPY_AND_ASSIGN(WebStateWrapper);
};

WebStateList::WebStateWrapper::WebStateWrapper(
    std::unique_ptr<web::WebState> web_state)
    : web_state_(std::move(web_state)), opener_(nullptr) {
  DCHECK(web_state_);
}

WebStateList::WebStateWrapper::~WebStateWrapper() = default;

std::unique_ptr<web::WebState> WebStateList::WebStateWrapper::ReplaceWebState(
    std::unique_ptr<web::WebState> web_state) {
  DCHECK_NE(web_state.get(), web_state_.get());
  std::swap(web_state, web_state_);
  opener_ = WebStateOpener();
  return web_state;
}

bool WebStateList::WebStateWrapper::WasOpenedBy(const web::WebState* opener,
                                                int opener_navigation_index,
                                                bool use_group) const {
  DCHECK(opener);
  if (opener_.opener != opener)
    return false;

  if (!use_group)
    return true;

  return opener_.navigation_index == opener_navigation_index;
}

WebStateList::WebStateList(WebStateListDelegate* delegate)
    : delegate_(delegate),
      order_controller_(std::make_unique<WebStateListOrderController>(this)) {
  DCHECK(delegate_);
}

WebStateList::~WebStateList() {
  CHECK(!locked_);
  CloseAllWebStates(CLOSE_NO_FLAGS);
}

bool WebStateList::ContainsIndex(int index) const {
  return 0 <= index && index < count();
}

web::WebState* WebStateList::GetActiveWebState() const {
  if (active_index_ != kInvalidIndex)
    return GetWebStateAt(active_index_);
  return nullptr;
}

web::WebState* WebStateList::GetWebStateAt(int index) const {
  DCHECK(ContainsIndex(index));
  return web_state_wrappers_[index]->web_state();
}

int WebStateList::GetIndexOfWebState(const web::WebState* web_state) const {
  for (int index = 0; index < count(); ++index) {
    if (web_state_wrappers_[index]->web_state() == web_state)
      return index;
  }
  return kInvalidIndex;
}

int WebStateList::GetIndexOfWebStateWithURL(const GURL& url) const {
  for (int index = 0; index < count(); ++index) {
    if (web_state_wrappers_[index]->web_state()->GetVisibleURL() == url)
      return index;
  }
  return kInvalidIndex;
}

int WebStateList::GetIndexOfInactiveWebStateWithURL(const GURL& url) const {
  for (int index = 0; index < count(); ++index) {
    if (index == active_index_)
      continue;
    if (web_state_wrappers_[index]->web_state()->GetVisibleURL() == url)
      return index;
  }
  return kInvalidIndex;
}

WebStateOpener WebStateList::GetOpenerOfWebStateAt(int index) const {
  DCHECK(ContainsIndex(index));
  return web_state_wrappers_[index]->opener();
}

void WebStateList::SetOpenerOfWebStateAt(int index, WebStateOpener opener) {
  DCHECK(ContainsIndex(index));
  DCHECK(ContainsIndex(GetIndexOfWebState(opener.opener)));
  web_state_wrappers_[index]->set_opener(opener);
}

int WebStateList::GetIndexOfNextWebStateOpenedBy(const web::WebState* opener,
                                                 int start_index,
                                                 bool use_group) const {
  return GetIndexOfNthWebStateOpenedBy(opener, start_index, use_group, 1);
}

int WebStateList::GetIndexOfLastWebStateOpenedBy(const web::WebState* opener,
                                                 int start_index,
                                                 bool use_group) const {
  return GetIndexOfNthWebStateOpenedBy(opener, start_index, use_group, INT_MAX);
}

int WebStateList::InsertWebState(int index,
                                 std::unique_ptr<web::WebState> web_state,
                                 int insertion_flags,
                                 WebStateOpener opener) {
  const bool activating = IsInsertionFlagSet(insertion_flags, INSERT_ACTIVATE);

  {
    // Inner block for the mutation lock, because ActivateWebState might need to
    // be called (if |activating| is true), and that method has its own mutation
    // lock.
    CHECK(!locked_);
    base::AutoReset<bool> scoped_lock(&locked_, /* locked */ true);
    if (IsInsertionFlagSet(insertion_flags, INSERT_INHERIT_OPENER))
      opener = WebStateOpener(GetActiveWebState());

    if (!IsInsertionFlagSet(insertion_flags, INSERT_FORCE_INDEX)) {
      index = order_controller_->DetermineInsertionIndex(opener.opener);
      if (index < 0 || count() < index)
        index = count();
    }

    DCHECK(ContainsIndex(index) || index == count());
    delegate_->WillAddWebState(web_state.get());

    web::WebState* web_state_ptr = web_state.get();
    web_state_wrappers_.insert(
        web_state_wrappers_.begin() + index,
        std::make_unique<WebStateWrapper>(std::move(web_state)));

    if (active_index_ >= index)
      ++active_index_;

    for (auto& observer : observers_)
      observer.WebStateInsertedAt(this, web_state_ptr, index, activating);

    if (opener.opener)
      SetOpenerOfWebStateAt(index, opener);
  }

  if (activating)
    ActivateWebStateAt(index);

  return index;
}

void WebStateList::MoveWebStateAt(int from_index, int to_index) {
  CHECK(!locked_);
  base::AutoReset<bool> scoped_lock(&locked_, /* locked */ true);
  DCHECK(ContainsIndex(from_index));
  DCHECK(ContainsIndex(to_index));
  if (from_index == to_index)
    return;

  std::unique_ptr<WebStateWrapper> web_state_wrapper =
      std::move(web_state_wrappers_[from_index]);
  web::WebState* web_state = web_state_wrapper->web_state();
  web_state_wrappers_.erase(web_state_wrappers_.begin() + from_index);
  web_state_wrappers_.insert(web_state_wrappers_.begin() + to_index,
                             std::move(web_state_wrapper));

  if (active_index_ == from_index) {
    active_index_ = to_index;
  } else {
    int min = std::min(from_index, to_index);
    int max = std::max(from_index, to_index);
    int delta = from_index < to_index ? -1 : +1;
    if (min <= active_index_ && active_index_ <= max)
      active_index_ += delta;
  }

  for (auto& observer : observers_)
    observer.WebStateMoved(this, web_state, from_index, to_index);
}

std::unique_ptr<web::WebState> WebStateList::ReplaceWebStateAt(
    int index,
    std::unique_ptr<web::WebState> web_state) {
  DCHECK(ContainsIndex(index));
  delegate_->WillAddWebState(web_state.get());

  ClearOpenersReferencing(index);

  web::WebState* web_state_ptr = web_state.get();
  std::unique_ptr<web::WebState> old_web_state =
      web_state_wrappers_[index]->ReplaceWebState(std::move(web_state));

  for (auto& observer : observers_) {
    observer.WebStateReplacedAt(this, old_web_state.get(), web_state_ptr,
                                index);
  }

  // When the active WebState is replaced, notify the observers as nearly
  // all of them needs to treat a replacement as the selection changed.
  NotifyIfActiveWebStateChanged(old_web_state.get(),
                                WebStateListObserver::CHANGE_REASON_REPLACED);

  delegate_->WebStateDetached(old_web_state.get());
  return old_web_state;
}

std::unique_ptr<web::WebState> WebStateList::DetachWebStateAt(int index) {
  CHECK(!locked_);
  base::AutoReset<bool> scoped_lock(&locked_, /* locked */ true);
  DCHECK(ContainsIndex(index));
  int new_active_index = order_controller_->DetermineNewActiveIndex(index);

  web::WebState* web_state = web_state_wrappers_[index]->web_state();
  for (auto& observer : observers_)
    observer.WillDetachWebStateAt(this, web_state, index);

  ClearOpenersReferencing(index);
  std::unique_ptr<web::WebState> detached_web_state =
      web_state_wrappers_[index]->ReplaceWebState(nullptr);
  web_state_wrappers_.erase(web_state_wrappers_.begin() + index);

  // Update the active index to prevent observer from seeing an invalid WebState
  // as the active one but only send the WebStateActivatedAt notification after
  // the WebStateDetachedAt one.
  bool active_web_state_was_closed = (index == active_index_);
  if (active_index_ > index)
    --active_index_;
  else if (active_index_ == index)
    active_index_ = new_active_index;

  for (auto& observer : observers_)
    observer.WebStateDetachedAt(this, web_state, index);

  if (active_web_state_was_closed) {
    NotifyIfActiveWebStateChanged(web_state,
                                  WebStateListObserver::CHANGE_REASON_NONE);
  }

  delegate_->WebStateDetached(web_state);
  return detached_web_state;
}

void WebStateList::CloseWebStateAt(int index, int close_flags) {
  // Lock after detaching, since that has its own lock.
  auto detached_web_state = DetachWebStateAt(index);

  CHECK(!locked_);
  base::AutoReset<bool> scoped_lock(&locked_, /* locked */ true);
  const bool user_action = IsClosingFlagSet(close_flags, CLOSE_USER_ACTION);
  for (auto& observer : observers_) {
    observer.WillCloseWebStateAt(this, detached_web_state.get(), index,
                                 user_action);
  }

  detached_web_state.reset();
}

void WebStateList::CloseAllWebStates(int close_flags) {
  while (!empty())
    CloseWebStateAt(count() - 1, close_flags);
}

void WebStateList::ActivateWebStateAt(int index) {
  DCHECK(ContainsIndex(index));
  web::WebState* old_web_state = GetActiveWebState();
  active_index_ = index;
  NotifyIfActiveWebStateChanged(
      old_web_state, WebStateListObserver::CHANGE_REASON_USER_ACTION);
}

void WebStateList::AddObserver(WebStateListObserver* observer) {
  observers_.AddObserver(observer);
}

void WebStateList::RemoveObserver(WebStateListObserver* observer) {
  observers_.RemoveObserver(observer);
}

void WebStateList::ClearOpenersReferencing(int index) {
  web::WebState* old_web_state = web_state_wrappers_[index]->web_state();
  for (auto& web_state_wrapper : web_state_wrappers_) {
    if (web_state_wrapper->opener().opener == old_web_state)
      web_state_wrapper->set_opener(WebStateOpener());
  }
}

void WebStateList::NotifyIfActiveWebStateChanged(web::WebState* old_web_state,
                                                 int reason) {
  web::WebState* new_web_state = GetActiveWebState();
  if (old_web_state == new_web_state)
    return;

  for (auto& observer : observers_) {
    observer.WebStateActivatedAt(this, old_web_state, new_web_state,
                                 active_index_, reason);
  }
}

int WebStateList::GetIndexOfNthWebStateOpenedBy(const web::WebState* opener,
                                                int start_index,
                                                bool use_group,
                                                int n) const {
  DCHECK_GT(n, 0);
  if (!opener || !ContainsIndex(start_index) || start_index == INT_MAX)
    return kInvalidIndex;

  const int opener_navigation_index =
      use_group ? opener->GetNavigationManager()->GetLastCommittedItemIndex()
                : -1;

  int found_index = kInvalidIndex;
  for (int index = start_index + 1; index < count() && n; ++index) {
    if (web_state_wrappers_[index]->WasOpenedBy(opener, opener_navigation_index,
                                                use_group)) {
      found_index = index;
      --n;
    } else if (found_index != kInvalidIndex) {
      return found_index;
    }
  }

  return found_index;
}

// static
const int WebStateList::kInvalidIndex;
