// Copyright (c) 2012 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/extensions/api/bookmarks/bookmark_api_helpers.h"

#include <math.h>  // For floor()
#include <vector>

#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/extensions/api/bookmarks/bookmark_api_constants.h"
#include "chrome/common/extensions/api/bookmarks.h"

namespace extensions {

namespace keys = bookmark_api_constants;
using api::bookmarks::BookmarkTreeNode;

namespace bookmark_api_helpers {

namespace {

void AddNodeHelper(const BookmarkNode* node,
                   std::vector<linked_ptr<BookmarkTreeNode> >* nodes,
                   bool recurse,
                   bool only_folders) {
  if (node->IsVisible()) {
    linked_ptr<BookmarkTreeNode> new_node(GetBookmarkTreeNode(node,
                                                              recurse,
                                                              only_folders));
    nodes->push_back(new_node);
  }
}

// TODO(mwrosen): Remove this function once chrome.bookmarkManagerPrivate is
// refactored to use the JSON schema compiler.
void AddNodeHelper(const BookmarkNode* node,
                   base::ListValue* list,
                   bool recurse,
                   bool only_folders) {
  if (node->IsVisible()) {
    base::DictionaryValue* dict =
        GetNodeDictionary(node, recurse, only_folders);
    list->Append(dict);
  }
}

}  // namespace

BookmarkTreeNode* GetBookmarkTreeNode(const BookmarkNode* node,
                                      bool recurse,
                                      bool only_folders) {
  BookmarkTreeNode* bookmark_tree_node = new BookmarkTreeNode;

  bookmark_tree_node->id = base::Int64ToString(node->id());

  const BookmarkNode* parent = node->parent();
  if (parent) {
    bookmark_tree_node->parent_id.reset(new std::string(
        base::Int64ToString(parent->id())));
    bookmark_tree_node->index.reset(new int(parent->GetIndexOf(node)));
  }

  if (!node->is_folder()) {
    bookmark_tree_node->url.reset(new std::string(node->url().spec()));
  } else {
    // Javascript Date wants milliseconds since the epoch, ToDoubleT is seconds.
    base::Time t = node->date_folder_modified();
    if (!t.is_null()) {
      bookmark_tree_node->date_group_modified.reset(
          new double(floor(t.ToDoubleT() * 1000)));
    }
  }

  bookmark_tree_node->title = UTF16ToUTF8(node->GetTitle());
  if (!node->date_added().is_null()) {
    // Javascript Date wants milliseconds since the epoch, ToDoubleT is seconds.
    bookmark_tree_node->date_added.reset(
        new double(floor(node->date_added().ToDoubleT() * 1000)));
  }

  if (recurse && node->is_folder()) {
    std::vector<linked_ptr<BookmarkTreeNode> > children;
    for (int i = 0; i < node->child_count(); ++i) {
      const BookmarkNode* child = node->GetChild(i);
      if (child->IsVisible() && (!only_folders || child->is_folder())) {
        linked_ptr<BookmarkTreeNode> child_node(
            GetBookmarkTreeNode(child, true, only_folders));
        children.push_back(child_node);
      }
    }
    bookmark_tree_node->children.reset(
        new std::vector<linked_ptr<BookmarkTreeNode> >(children));
  }
  return bookmark_tree_node;
}

base::DictionaryValue* GetNodeDictionary(const BookmarkNode* node,
                                         bool recurse,
                                         bool only_folders) {
  base::DictionaryValue* dict = new base::DictionaryValue;
  dict->SetString(keys::kIdKey, base::Int64ToString(node->id()));

  const BookmarkNode* parent = node->parent();
  if (parent) {
    dict->SetString(keys::kParentIdKey, base::Int64ToString(parent->id()));
    dict->SetInteger(keys::kIndexKey, parent->GetIndexOf(node));
  }

  if (!node->is_folder()) {
    dict->SetString(keys::kUrlKey, node->url().spec());
  } else {
    // Javascript Date wants milliseconds since the epoch, ToDoubleT is seconds.
    base::Time t = node->date_folder_modified();
    if (!t.is_null())
      dict->SetDouble(keys::kDateFolderModifiedKey,
                      floor(t.ToDoubleT() * 1000));
  }

  dict->SetString(keys::kTitleKey, node->GetTitle());
  if (!node->date_added().is_null()) {
    // Javascript Date wants milliseconds since the epoch, ToDoubleT is seconds.
    dict->SetDouble(keys::kDateAddedKey,
                    floor(node->date_added().ToDoubleT() * 1000));
  }

  if (recurse && node->is_folder()) {
    base::ListValue* children = new base::ListValue;
    for (int i = 0; i < node->child_count(); ++i) {
      const BookmarkNode* child = node->GetChild(i);
      if (child->IsVisible() && (!only_folders || child->is_folder())) {
        base::DictionaryValue* dict =
            GetNodeDictionary(child, true, only_folders);
        children->Append(dict);
      }
    }
    dict->Set(keys::kChildrenKey, children);
  }
  return dict;
}

void AddNode(const BookmarkNode* node,
             std::vector<linked_ptr<BookmarkTreeNode> >* nodes,
             bool recurse) {
  return AddNodeHelper(node, nodes, recurse, false);
}

void AddNodeFoldersOnly(const BookmarkNode* node,
                        std::vector<linked_ptr<BookmarkTreeNode> >* nodes,
                        bool recurse) {
  return AddNodeHelper(node, nodes, recurse, true);
}

void AddNode(const BookmarkNode* node, base::ListValue* list, bool recurse) {
  return AddNodeHelper(node, list, recurse, false);
}

void AddNodeFoldersOnly(const BookmarkNode* node,
                        base::ListValue* list,
                        bool recurse) {
  return AddNodeHelper(node, list, recurse, true);
}

bool RemoveNode(BookmarkModel* model,
                int64 id,
                bool recursive,
                std::string* error) {
  const BookmarkNode* node = model->GetNodeByID(id);
  if (!node) {
    *error = keys::kNoNodeError;
    return false;
  }
  if (model->is_permanent_node(node)) {
    *error = keys::kModifySpecialError;
    return false;
  }
  if (node->is_folder() && !node->empty() && !recursive) {
    *error = keys::kFolderNotEmptyError;
    return false;
  }

  const BookmarkNode* parent = node->parent();
  model->Remove(parent, parent->GetIndexOf(node));
  return true;
}

}  // namespace bookmark_api_helpers
}  // namespace extensions
