// Copyright 2013 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.

#include "chrome/browser/undo/bookmark_undo_service.h"

#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/undo/bookmark_renumber_observer.h"
#include "chrome/browser/undo/bookmark_undo_service_factory.h"
#include "chrome/browser/undo/undo_operation.h"
#include "chrome/grit/generated_resources.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/browser/bookmark_node_data.h"
#include "components/bookmarks/browser/bookmark_utils.h"
#include "components/bookmarks/browser/scoped_group_bookmark_actions.h"

using bookmarks::BookmarkNodeData;

namespace {

// BookmarkUndoOperation ------------------------------------------------------

// Base class for all bookmark related UndoOperations that facilitates access to
// the BookmarkUndoService.
class BookmarkUndoOperation : public UndoOperation,
                              public BookmarkRenumberObserver {
 public:
  explicit BookmarkUndoOperation(Profile* profile);
  ~BookmarkUndoOperation() override {}

  BookmarkModel* GetBookmarkModel() const;
  BookmarkRenumberObserver* GetUndoRenumberObserver() const;

 private:
  Profile* profile_;
};

BookmarkUndoOperation::BookmarkUndoOperation(Profile* profile)
    : profile_(profile) {
}

BookmarkModel* BookmarkUndoOperation::GetBookmarkModel() const {
  return BookmarkModelFactory::GetForProfile(profile_);
}

BookmarkRenumberObserver* BookmarkUndoOperation::GetUndoRenumberObserver()
    const {
  return BookmarkUndoServiceFactory::GetForProfile(profile_);
}

// BookmarkAddOperation -------------------------------------------------------

// Handles the undo of the insertion of a bookmark or folder.
class BookmarkAddOperation : public BookmarkUndoOperation {
 public:
  BookmarkAddOperation(Profile* profile, const BookmarkNode* parent, int index);
  ~BookmarkAddOperation() override {}

  // UndoOperation:
  void Undo() override;
  int GetUndoLabelId() const override;
  int GetRedoLabelId() const override;

  // BookmarkRenumberObserver:
  void OnBookmarkRenumbered(int64 old_id, int64 new_id) override;

 private:
  int64 parent_id_;
  const int index_;

  DISALLOW_COPY_AND_ASSIGN(BookmarkAddOperation);
};

BookmarkAddOperation::BookmarkAddOperation(Profile* profile,
                                           const BookmarkNode* parent,
                                           int index)
  : BookmarkUndoOperation(profile),
    parent_id_(parent->id()),
    index_(index) {
}

void BookmarkAddOperation::Undo() {
  BookmarkModel* model = GetBookmarkModel();
  const BookmarkNode* parent =
      bookmarks::GetBookmarkNodeByID(model, parent_id_);
  DCHECK(parent);

  model->Remove(parent, index_);
}

int BookmarkAddOperation::GetUndoLabelId() const {
  return IDS_BOOKMARK_BAR_UNDO_ADD;
}

int BookmarkAddOperation::GetRedoLabelId() const {
  return IDS_BOOKMARK_BAR_REDO_DELETE;
}

void BookmarkAddOperation::OnBookmarkRenumbered(int64 old_id, int64 new_id) {
  if (parent_id_ == old_id)
    parent_id_ = new_id;
}

// BookmarkRemoveOperation ----------------------------------------------------

// Handles the undo of the deletion of a bookmark node. For a bookmark folder,
// the information for all descendant bookmark nodes is maintained.
//
// The BookmarkModel allows only single bookmark node to be removed.
class BookmarkRemoveOperation : public BookmarkUndoOperation {
 public:
  BookmarkRemoveOperation(Profile* profile,
                          const BookmarkNode* parent,
                          int old_index,
                          const BookmarkNode* node);
  ~BookmarkRemoveOperation() override {}

  // UndoOperation:
  void Undo() override;
  int GetUndoLabelId() const override;
  int GetRedoLabelId() const override;

  // BookmarkRenumberObserver:
  void OnBookmarkRenumbered(int64 old_id, int64 new_id) override;

 private:
  void UpdateBookmarkIds(const BookmarkNodeData::Element& element,
                         const BookmarkNode* parent,
                         int index_added_at) const;

  int64 parent_id_;
  const int old_index_;
  BookmarkNodeData removed_node_;

  DISALLOW_COPY_AND_ASSIGN(BookmarkRemoveOperation);
};

BookmarkRemoveOperation::BookmarkRemoveOperation(Profile* profile,
                                                 const BookmarkNode* parent,
                                                 int old_index,
                                                 const BookmarkNode* node)
  : BookmarkUndoOperation(profile),
    parent_id_(parent->id()),
    old_index_(old_index),
    removed_node_(node) {
}

void BookmarkRemoveOperation::Undo() {
  DCHECK(removed_node_.is_valid());
  BookmarkModel* model = GetBookmarkModel();
  const BookmarkNode* parent =
      bookmarks::GetBookmarkNodeByID(model, parent_id_);
  DCHECK(parent);

  bookmarks::CloneBookmarkNode(
      model, removed_node_.elements, parent, old_index_, false);
  UpdateBookmarkIds(removed_node_.elements[0], parent, old_index_);
}

int BookmarkRemoveOperation::GetUndoLabelId() const {
  return IDS_BOOKMARK_BAR_UNDO_DELETE;
}

int BookmarkRemoveOperation::GetRedoLabelId() const {
  return IDS_BOOKMARK_BAR_REDO_ADD;
}

void BookmarkRemoveOperation::UpdateBookmarkIds(
    const BookmarkNodeData::Element& element,
    const BookmarkNode* parent,
    int index_added_at) const {
  const BookmarkNode* node = parent->GetChild(index_added_at);
  if (element.id() != node->id())
    GetUndoRenumberObserver()->OnBookmarkRenumbered(element.id(), node->id());
  if (!element.is_url) {
    for (int i = 0; i < static_cast<int>(element.children.size()); ++i)
      UpdateBookmarkIds(element.children[i], node, 0);
  }
}

void BookmarkRemoveOperation::OnBookmarkRenumbered(int64 old_id, int64 new_id) {
  if (parent_id_ == old_id)
    parent_id_ = new_id;
}

// BookmarkEditOperation ------------------------------------------------------

// Handles the undo of the modification of a bookmark node.
class BookmarkEditOperation : public BookmarkUndoOperation {
 public:
  BookmarkEditOperation(Profile* profile,
                        const BookmarkNode* node);
  ~BookmarkEditOperation() override {}

  // UndoOperation:
  void Undo() override;
  int GetUndoLabelId() const override;
  int GetRedoLabelId() const override;

  // BookmarkRenumberObserver:
  void OnBookmarkRenumbered(int64 old_id, int64 new_id) override;

 private:
  int64 node_id_;
  BookmarkNodeData original_bookmark_;

  DISALLOW_COPY_AND_ASSIGN(BookmarkEditOperation);
};

BookmarkEditOperation::BookmarkEditOperation(Profile* profile,
                                             const BookmarkNode* node)
    : BookmarkUndoOperation(profile),
      node_id_(node->id()),
      original_bookmark_(node) {
}

void BookmarkEditOperation::Undo() {
  DCHECK(original_bookmark_.is_valid());
  BookmarkModel* model = GetBookmarkModel();
  const BookmarkNode* node = bookmarks::GetBookmarkNodeByID(model, node_id_);
  DCHECK(node);

  model->SetTitle(node, original_bookmark_.elements[0].title);
  if (original_bookmark_.elements[0].is_url)
    model->SetURL(node, original_bookmark_.elements[0].url);
}

int BookmarkEditOperation::GetUndoLabelId() const {
  return IDS_BOOKMARK_BAR_UNDO_EDIT;
}

int BookmarkEditOperation::GetRedoLabelId() const {
  return IDS_BOOKMARK_BAR_REDO_EDIT;
}

void BookmarkEditOperation::OnBookmarkRenumbered(int64 old_id, int64 new_id) {
  if (node_id_ == old_id)
    node_id_ = new_id;
}

// BookmarkMoveOperation ------------------------------------------------------

// Handles the undo of a bookmark being moved to a new location.
class BookmarkMoveOperation : public BookmarkUndoOperation {
 public:
  BookmarkMoveOperation(Profile* profile,
                        const BookmarkNode* old_parent,
                        int old_index,
                        const BookmarkNode* new_parent,
                        int new_index);
  ~BookmarkMoveOperation() override {}
  int GetUndoLabelId() const override;
  int GetRedoLabelId() const override;

  // UndoOperation:
  void Undo() override;

  // BookmarkRenumberObserver:
  void OnBookmarkRenumbered(int64 old_id, int64 new_id) override;

 private:
  int64 old_parent_id_;
  int64 new_parent_id_;
  int old_index_;
  int new_index_;

  DISALLOW_COPY_AND_ASSIGN(BookmarkMoveOperation);
};

BookmarkMoveOperation::BookmarkMoveOperation(Profile* profile,
                                             const BookmarkNode* old_parent,
                                             int old_index,
                                             const BookmarkNode* new_parent,
                                             int new_index)
    : BookmarkUndoOperation(profile),
      old_parent_id_(old_parent->id()),
      new_parent_id_(new_parent->id()),
      old_index_(old_index),
      new_index_(new_index) {
}

void BookmarkMoveOperation::Undo() {
  BookmarkModel* model = GetBookmarkModel();
  const BookmarkNode* old_parent =
      bookmarks::GetBookmarkNodeByID(model, old_parent_id_);
  const BookmarkNode* new_parent =
      bookmarks::GetBookmarkNodeByID(model, new_parent_id_);
  DCHECK(old_parent);
  DCHECK(new_parent);

  const BookmarkNode* node = new_parent->GetChild(new_index_);
  int destination_index = old_index_;

  // If the bookmark was moved up within the same parent then the destination
  // index needs to be incremented since the old index did not account for the
  // moved bookmark.
  if (old_parent == new_parent && new_index_ < old_index_)
    ++destination_index;

  model->Move(node, old_parent, destination_index);
}

int BookmarkMoveOperation::GetUndoLabelId() const {
  return IDS_BOOKMARK_BAR_UNDO_MOVE;
}

int BookmarkMoveOperation::GetRedoLabelId() const {
  return IDS_BOOKMARK_BAR_REDO_MOVE;
}

void BookmarkMoveOperation::OnBookmarkRenumbered(int64 old_id, int64 new_id) {
  if (old_parent_id_ == old_id)
    old_parent_id_ = new_id;
  if (new_parent_id_ == old_id)
    new_parent_id_ = new_id;
}

// BookmarkReorderOperation ---------------------------------------------------

// Handle the undo of reordering of bookmarks that can happen as a result of
// sorting a bookmark folder by name or the undo of that operation.  The change
// of order is not recursive so only the order of the immediate children of the
// folder need to be restored.
class BookmarkReorderOperation : public BookmarkUndoOperation {
 public:
  BookmarkReorderOperation(Profile* profile,
                           const BookmarkNode* parent);
  ~BookmarkReorderOperation() override;

  // UndoOperation:
  void Undo() override;
  int GetUndoLabelId() const override;
  int GetRedoLabelId() const override;

  // BookmarkRenumberObserver:
  void OnBookmarkRenumbered(int64 old_id, int64 new_id) override;

 private:
  int64 parent_id_;
  std::vector<int64> ordered_bookmarks_;

  DISALLOW_COPY_AND_ASSIGN(BookmarkReorderOperation);
};

BookmarkReorderOperation::BookmarkReorderOperation(Profile* profile,
                                                   const BookmarkNode* parent)
    : BookmarkUndoOperation(profile),
      parent_id_(parent->id()) {
  ordered_bookmarks_.resize(parent->child_count());
  for (int i = 0; i < parent->child_count(); ++i)
    ordered_bookmarks_[i] = parent->GetChild(i)->id();
}

BookmarkReorderOperation::~BookmarkReorderOperation() {
}

void BookmarkReorderOperation::Undo() {
  BookmarkModel* model = GetBookmarkModel();
  const BookmarkNode* parent =
      bookmarks::GetBookmarkNodeByID(model, parent_id_);
  DCHECK(parent);

  std::vector<const BookmarkNode*> ordered_nodes;
  for (size_t i = 0; i < ordered_bookmarks_.size(); ++i) {
    ordered_nodes.push_back(
        bookmarks::GetBookmarkNodeByID(model, ordered_bookmarks_[i]));
  }

  model->ReorderChildren(parent, ordered_nodes);
}

int BookmarkReorderOperation::GetUndoLabelId() const {
  return IDS_BOOKMARK_BAR_UNDO_REORDER;
}

int BookmarkReorderOperation::GetRedoLabelId() const {
  return IDS_BOOKMARK_BAR_REDO_REORDER;
}

void BookmarkReorderOperation::OnBookmarkRenumbered(int64 old_id,
                                                    int64 new_id) {
  if (parent_id_ == old_id)
    parent_id_ = new_id;
  for (size_t i = 0; i < ordered_bookmarks_.size(); ++i) {
    if (ordered_bookmarks_[i] == old_id)
      ordered_bookmarks_[i] = new_id;
  }
}

}  // namespace

// BookmarkUndoService --------------------------------------------------------

BookmarkUndoService::BookmarkUndoService(Profile* profile) : profile_(profile) {
}

BookmarkUndoService::~BookmarkUndoService() {
  BookmarkModelFactory::GetForProfile(profile_)->RemoveObserver(this);
}

void BookmarkUndoService::BookmarkModelLoaded(BookmarkModel* model,
                                              bool ids_reassigned) {
  undo_manager_.RemoveAllOperations();
}

void BookmarkUndoService::BookmarkModelBeingDeleted(BookmarkModel* model) {
  undo_manager_.RemoveAllOperations();
}

void BookmarkUndoService::BookmarkNodeMoved(BookmarkModel* model,
                                            const BookmarkNode* old_parent,
                                            int old_index,
                                            const BookmarkNode* new_parent,
                                            int new_index) {
  scoped_ptr<UndoOperation> op(new BookmarkMoveOperation(profile_,
                                                         old_parent,
                                                         old_index,
                                                         new_parent,
                                                         new_index));
  undo_manager()->AddUndoOperation(op.Pass());
}

void BookmarkUndoService::BookmarkNodeAdded(BookmarkModel* model,
                                            const BookmarkNode* parent,
                                            int index) {
  scoped_ptr<UndoOperation> op(new BookmarkAddOperation(profile_,
                                                        parent,
                                                        index));
  undo_manager()->AddUndoOperation(op.Pass());
}

void BookmarkUndoService::OnWillRemoveBookmarks(BookmarkModel* model,
                                                const BookmarkNode* parent,
                                                int old_index,
                                                const BookmarkNode* node) {
  scoped_ptr<UndoOperation> op(new BookmarkRemoveOperation(profile_,
                                                           parent,
                                                           old_index,
                                                           node));
  undo_manager()->AddUndoOperation(op.Pass());
}

void BookmarkUndoService::OnWillRemoveAllUserBookmarks(BookmarkModel* model) {
  bookmarks::ScopedGroupBookmarkActions merge_removes(model);
  for (int i = 0; i < model->root_node()->child_count(); ++i) {
    const BookmarkNode* permanent_node = model->root_node()->GetChild(i);
    for (int j = permanent_node->child_count() - 1; j >= 0; --j) {
      scoped_ptr<UndoOperation> op(new BookmarkRemoveOperation(profile_,
          permanent_node, j, permanent_node->GetChild(j)));
      undo_manager()->AddUndoOperation(op.Pass());
    }
  }
}

void BookmarkUndoService::OnWillChangeBookmarkNode(BookmarkModel* model,
                                                   const BookmarkNode* node) {
  scoped_ptr<UndoOperation> op(new BookmarkEditOperation(profile_, node));
  undo_manager()->AddUndoOperation(op.Pass());
}

void BookmarkUndoService::OnWillReorderBookmarkNode(BookmarkModel* model,
                                                    const BookmarkNode* node) {
  scoped_ptr<UndoOperation> op(new BookmarkReorderOperation(profile_, node));
  undo_manager()->AddUndoOperation(op.Pass());
}

void BookmarkUndoService::GroupedBookmarkChangesBeginning(
    BookmarkModel* model) {
  undo_manager()->StartGroupingActions();
}

void BookmarkUndoService::GroupedBookmarkChangesEnded(BookmarkModel* model) {
  undo_manager()->EndGroupingActions();
}

void BookmarkUndoService::OnBookmarkRenumbered(int64 old_id, int64 new_id) {
  std::vector<UndoOperation*> all_operations =
      undo_manager()->GetAllUndoOperations();
  for (std::vector<UndoOperation*>::iterator it = all_operations.begin();
       it != all_operations.end(); ++it) {
    static_cast<BookmarkUndoOperation*>(*it)->OnBookmarkRenumbered(old_id,
                                                                   new_id);
  }
}
