/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Places.
 *
 * The Initial Developer of the Original Code is
 * Google Inc.
 * Portions created by the Initial Developer are Copyright (C) 2005
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Brian Ryner <bryner@brianryner.com> (original author)
 *   Joe Hughes <joe@retrovirus.com>
 *   Dietrich Ayala <dietrich@mozilla.com>
 *   Asaf Romano <mano@mozilla.com>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "nsISupports.idl"

interface nsIFile;
interface nsIURI;
interface nsITransaction;
interface nsINavHistoryBatchCallback;

/**
 * Observer for bookmark changes.
 */
[scriptable, uuid(76f892d9-31ea-4061-b38c-6b40fad57e9d)]
interface nsINavBookmarkObserver : nsISupports
{
  /**
   * Notify this observer that a batch transaction has started.
   * Other notifications will be sent during the batch change,
   * but the observer is guaranteed that onEndUpdateBatch() will be called
   * at the completion of changes.
   */
  void onBeginUpdateBatch();

  /**
   * Notify this observer that a batch transaction has ended.
   */
  void onEndUpdateBatch();

  /**
   * Notify this observer that an item was added.  Called after the actual
   * add took place. The items following the index will be shifted down, but
   * no additional notifications will be sent.
   *
   * @param aItemId
   *        The id of the bookmark that was added.
   * @param aParentId
   *        The id of the folder to which the item was added.
   * @param aIndex
   *        The item's index in the folder.
   * @param aItemType
   *        The type of the item that was added (one of the TYPE_* constants
   *        defined above).
   * @param aURI
   *        The URI of the item that was added when aItemType is TYPE_BOOKMARK,
   *        null otherwise.
   */
  void onItemAdded(in long long aItemId, in long long aParentId,
                   in long aIndex, in unsigned short aItemType,
                   in nsIURI aURI);

  /**
   * Notify this observer that an item is about to be removed.  Called before
   * the actual removal will take place.
   *
   * @param aItemId
   *        The id of the bookmark to be removed.
   * @param aItemType
   *        The type of the item to be removed (one of the TYPE_* constants
   *        defined above).
   */
  void onBeforeItemRemoved(in long long aItemId, in unsigned short aItemType);

  /**
   * Notify this observer that an item was removed.  Called after the actual
   * remove took place. The items following the index will be shifted up, but
   * no additional notifications will be sent.
   *
   * @param aItemId
   *        The id of the item that was removed.
   * @param aParentId
   *        The id of the folder from which the item was removed.
   * @param aIndex
   *        The bookmark's index in the folder.
   * @param aItemType
   *        The type of the item that was removed (one of the TYPE_* constants
   *        defined above).
   */
  void onItemRemoved(in long long aItemId, in long long aParentId,
                     in long aIndex, in unsigned short aItemType);

  /**
   * Notify this observer that an item's information has changed.  This
   * will be called whenever any attributes like "title" are changed.
   * 
   * @param aItemId
   *        The id of the item that was changed.
   * @param aProperty
   *        The property which changed.
   * @param aIsAnnotationProperty
   *        Whether or not aProperty the name of an item annotation.
   * @param aProperty
   *        The property which has been changed (see list below).
   * @param aNewValue
   *        For certain properties, this is set to the new value of the
   *        property (see list below).
   * @param aLastModified
   *        If the item's lastModified field has changed, this parameter is
   *        set to the new value, otherwise it's set to 0.
   * @param aItemType
   *        The type of the item that has been changed(one of the TYPE_* constants
   *        defined above).
   *        
   * property = "cleartime": (history was deleted, there is no last visit date):
   *                         value = empty string.
   * property = "title": value = new title.
   * property = "favicon": value = new "moz-anno" URL of favicon image
   * property = "uri": value = new uri spec.
   * property = "tags: (tags set for the bookmarked uri have changed)
   *             value = empty string.
   * property = "dateAdded": value = PRTime when the item was first added
   * property = "lastModified": value = PRTime when the item was last modified
   * aIsAnnotationProperty = true: value = empty string.
   */
  void onItemChanged(in long long aItemId, in ACString aProperty,
                     in boolean aIsAnnotationProperty,
                     in AUTF8String aNewValue, in PRTime aLastModified,
                     in unsigned short aItemType);

  /**
   * Notify that the item was visited. Normally in bookmarks we use the last
   * visit date, and normally the time will be a new visit that will be more
   * recent, but this is not guaranteed. You should check to see if it's
   * actually more recent before using this new time.
   *
   * @param aBookmarkId
   *        The id of the bookmark that was visited.
   * @see onItemChanged property = "cleartime" for when all visit dates are
   * deleted for the URI.
   */
  void onItemVisited(in long long aBookmarkId, in long long aVisitID,
                     in PRTime time);

  /**
   * Notify this observer that an item has been moved.
   *  @param aItemId
   *         The id of the item that was moved.
   *  @param aOldParentId
   *         The id of the old parent.
   *  @param aOldIndex
   *         The old index inside the old parent.
   *  @param aNewParentId
   *         The id of the new parent.
   *  @param aNewIndex
   *         The index inside the new parent.
   * @param  aItemType
   *         The type of the item that was moved (one of the TYPE_* constants
   *         defined above).
   */
  void onItemMoved(in long long aItemId,
                   in long long aOldParentId, in long aOldIndex,
                   in long long aNewParentId, in long aNewIndex,
                   in unsigned short aItemType);
};

/**
 * The BookmarksService interface provides methods for managing bookmarked
 * history items.  Bookmarks consist of a set of user-customizable
 * folders.  A URI in history can be contained in one or more such folders.
 */

[scriptable, uuid(573f99bd-988c-4253-836f-4ce009d33ac6)]
interface nsINavBookmarksService : nsISupports
{
  /**
   * The item ID of the Places root.
   */
  readonly attribute long long placesRoot;

  /**
   * The item ID of the bookmarks menu folder.
   */
  readonly attribute long long bookmarksMenuFolder;

  /**
   * The item ID of the top-level folder that contain the tag "folders".
   */
  readonly attribute long long tagsFolder;

 /**
  * The item ID of the unfiled-bookmarks folder.
  */
  readonly attribute long long unfiledBookmarksFolder;

  /**
   * The item ID of the personal toolbar folder.
   */
  readonly attribute long long toolbarFolder;

  /**
   * This value should be used for APIs that allow passing in an index
   * where an index is not known, or not required to be specified.
   * e.g.: When appending an item to a folder.
   */
  const short DEFAULT_INDEX = -1;

  const unsigned short TYPE_BOOKMARK = 1;
  const unsigned short TYPE_FOLDER = 2;
  const unsigned short TYPE_SEPARATOR = 3;
  const unsigned short TYPE_DYNAMIC_CONTAINER = 4;

  /**
   * Inserts a child bookmark into the given folder.
   *
   *  @param aParentId
   *         The id of the parent folder
   *  @param aURI
   *         The URI to insert
   *  @param aIndex
   *         The index to insert at, or DEFAULT_INDEX to append
   *  @param aTitle
   *         The title for the new bookmark
   *  @return The ID of the newly-created bookmark.
   */
  long long insertBookmark(in long long aParentId, in nsIURI aURI,
                           in long aIndex, in AUTF8String aTitle);

  /**
   * Removes a child item. Used to delete a bookmark or separator.
   *  @param aItemId
   *         The child item to remove
   */
  void removeItem(in long long aItemId);

  /**
   * Creates a new child folder and inserts it under the given parent.
   *  @param aParentFolder
   *         The id of the parent folder
   *  @param aName
   *         The name of the new folder
   *  @param aIndex
   *         The index to insert at, or DEFAULT_INDEX to append
   *  @return The ID of the newly-inserted folder.
   */
  long long createFolder(in long long aParentFolder, in AUTF8String name,
                         in long index);

  /**
   * Creates a dynamic container under the given parent folder.
   *
   *  @param aParentFolder
   *         The id of the parent folder
   *  @param aName
   *         The name of the new folder
   *  @param aContractId
   *         The contract id of the service which is to manipulate this
   *         container.
   *  @param aIndex
   *         The index to insert at, or DEFAULT_INDEX to append
   *         
   *  @return The ID of the newly-inserted folder.
   */
  long long createDynamicContainer(in long long aParentFolder, in AUTF8String aName,
                                   in AString aContractId, in long aIndex);

  /**
   * Gets an undo-able transaction for removing a folder from the bookmarks
   * tree. 
   *  @param aItemId
   *         The id of the folder to remove.
   *  @return An object implementing nsITransaction that can be used to undo 
   *          or redo the action. 
   *
   * This method exists because complex delete->undo operations rely on 
   * recreated folders to have the same ID they had before they were deleted, 
   * so that any other items deleted in different transactions can be 
   * re-inserted correctly. This provides a safe encapsulation of this 
   * functionality without exposing the ability to recreate folders with 
   * specific IDs (potentially dangerous if abused by other code!) in the
   * public API.
   */
  nsITransaction getRemoveFolderTransaction(in long long aItemId);

  /**
   * Convenience function for container services.  Removes
   * all children of the given folder.
   *  @param aItemId
   *         The id of the folder to remove children from.
   */
  void removeFolderChildren(in long long aItemId);

  /**
   * Moves an item to a different container, preserving its contents.
   *  @param aItemId
   *         The id of the item to move
   *  @param aNewParentId
   *         The id of the new parent
   *  @param aIndex
   *         The index under aNewParent, or DEFAULT_INDEX to append
   *
   * NOTE: When moving down in the same container we take into account the
   * removal of the original item. If you want to move from index X to
   * index Y > X you must use moveItem(id, folder, Y + 1)
   */
  void moveItem(in long long aItemId, in long long aNewParentId, in long aIndex);

  /**
   * Inserts a bookmark separator into the given folder at the given index.
   * The separator can be removed using removeChildAt().
   *  @param aParentId
   *         The id of the parent folder
   *  @param aIndex
   *         The separator's index under folder, or DEFAULT_INDEX to append
   *  @return The ID of the new separator.
   */
  long long insertSeparator(in long long aParentId, in long aIndex);

  /**
   * Get the itemId given the containing folder and the index.
   *  @param aParentId
   *         The id of the diret parent folder of the item
   *  @param aIndex
   *         The index of the item within the parent folder.
   *         Pass DEFAULT_INDEX for the last item.
   *  @return The ID of the found item, -1 if the item does not exists.
   */
  long long getIdForItemAt(in long long aParentId, in long aIndex);

  /**
   * Get a globally unique identifier for an item, meant to be used in
   * sync scenarios.  Even if their contents are exactly the same
   * (including an item in a different profile with the same ItemId),
   * the GUID would be different.
   *  @param   aItemId
   *           The ID of the item to get the GUID for
   *  @return The GUID string.
   */
  AString getItemGUID(in long long aItemId);

  /**
   * Set a globally unique identifier.  This can be useful when a sync
   * algorithm deems two independently created items (on different
   * profiles) to be the same item.
   *  @param   aItemId
   *           The id of the item to set the GUID of
   *  @param   aGUID
   *           The GUID string
   */
  void setItemGUID(in long long aItemId, in AString aGUID);

  /**
   * Get the ID of the item with the given GUID.
   * @param   aGUID
   *          The GUID string of the item to search for
   * @return The item ID, or -1 if not found.
   */
  long long getItemIdForGUID(in AString aGUID);

  /**
   * Set the title for an item.
   *  @param aItemId
   *         The id of the item whose title should be updated 
   *  @param aTitle
   *         The new title for the bookmark.
   */
  void setItemTitle(in long long aItemId, in AUTF8String aTitle);

  /**
   * Get the title for an item.
   *
   * If no item title is available it will return a void string (null in JS).
   *
   *  @param aItemId
   *         The id of the item whose title should be retrieved
   *  @return The title of the item.
   */
  AUTF8String getItemTitle(in long long aItemId);

  /**
   * Set the date added time for an item.
   */
  void setItemDateAdded(in long long aItemId, in PRTime aDateAdded);
  /**
   * Get the date added time for an item.
   */
  PRTime getItemDateAdded(in long long aItemId);

  /**
   * Set the last modified time for an item.
   *
   *  @note This is the only method that will send an itemChanged notification
   *        for the property.  lastModified will still be updated in
   *        any other method that changes an item property, but we will send
   *        the corresponding itemChanged notification instead.
   */
  void setItemLastModified(in long long aItemId, in PRTime aLastModified);
  /**
   * Get the last modified time for an item.
   *
   *  @note When an item is added lastModified is set to the same value as
   *        dateAdded.
   */
  PRTime getItemLastModified(in long long aItemId);

  /**
   * Get the URI for a bookmark item.
   */
  nsIURI getBookmarkURI(in long long aItemId);

  /**
   * Get the index for an item.
   */
  long getItemIndex(in long long aItemId);

  /**
   * Changes the index for a item. This method does not change the indices of
   * any other items in the same folder, so ensure that the new index does not
   * already exist, or change the index of other items accordingly, otherwise
   * the indices will become corrupted.
   *
   * WARNING: This is API is intended for scenarios such as folder sorting,
   *          where the caller manages the indices of *all* items in the folder.
   *          You must always ensure each index is unique after a reordering.
   *
   *  @param aItemId    The id of the item to modify
   *  @param aNewIndex  The new index
   * 
   *  @throws If aNewIndex is out of bounds.
   */
  void setItemIndex(in long long aItemId, in long aNewIndex);

  /**
   * Get an item's type (bookmark, separator, folder).
   * The type is one of the TYPE_* constants defined above.
   */
  unsigned short getItemType(in long long aItemId);

  /**
   * Checks whether a folder is marked as read-only.
   * If this is set to true, UI will not allow the user to add, remove,
   * or reorder children in this folder. The default for all folders is false.
   * Note: This does not restrict API calls, only UI actions.
   *
   * @param aItemId
   *        the item-id of the folder.
   */
  boolean getFolderReadonly(in long long aItemId);

  /**
   * Sets or unsets the readonly flag from a folder.
   * If this is set to true, UI will not allow the user to add, remove,
   * or reorder children in this folder. The default for all folders is false.
   * Note: This does not restrict API calls, only UI actions.
   *
   * @param aFolder
   *        the item-id of the folder.
   * @param aReadOnly
   *        the read-only state (boolean).
   */
  void setFolderReadonly(in long long aFolder, in boolean aReadOnly);

  /**
   * Returns true if the given URI is in any bookmark folder. If you want the
   * results to be redirect-aware, use getBookmarkedURIFor()
   */
  boolean isBookmarked(in nsIURI aURI);

  /**
   * Used to see if the given URI is bookmarked, or any page that redirected to
   * it is bookmarked. For example, if I bookmark "mozilla.org" by manually
   * typing it in, and follow the bookmark, I will get redirected to
   * "www.mozilla.org". Logically, this new page is also bookmarked. This
   * function, if given "www.mozilla.org", will return the URI of the bookmark,
   * in this case "mozilla.org".
   *
   * If there is no bookmarked page found, it will return NULL.
   *
   * @note The function will only return bookmarks in the first 3 levels of
   *       redirection (1 -> 2 -> 3 -> aURI).
   */
  nsIURI getBookmarkedURIFor(in nsIURI aURI);

  /**
   * Change the bookmarked URI for a bookmark.
   * This changes which "place" the bookmark points at,
   * which means all annotations, etc are carried along.
   */
  void changeBookmarkURI(in long long aItemId, in nsIURI aNewURI);

  /**
   * Get the parent folder's id for an item.
   */
  long long getFolderIdForItem(in long long aItemId);

  /**
   * Returns the list of bookmark ids that contain the given URI.
   */
  void getBookmarkIdsForURI(in nsIURI aURI, [optional] out unsigned long count,
                            [array, retval, size_is(count)] out long long bookmarks);

  /**
   * Associates the given keyword with the given bookmark.
   *
   * Use an empty keyword to clear the keyword associated with the URI.
   * In both of these cases, succeeds but does nothing if the URL/keyword is not found.
   */
  void setKeywordForBookmark(in long long aItemId, in AString aKeyword);

  /**
   * Retrieves the keyword for the given URI. Will be void string
   * (null in JS) if no such keyword is found.
   */
  AString getKeywordForURI(in nsIURI aURI);

  /**
   * Retrieves the keyword for the given bookmark. Will be void string
   * (null in JS) if no such keyword is found.
   */
  AString getKeywordForBookmark(in long long aItemId);

  /**
   * Returns the URI associated with the given keyword. Empty if no such
   * keyword is found.
   */
  nsIURI getURIForKeyword(in AString keyword);

  /**
   * Adds a bookmark observer. If ownsWeak is false, the bookmark service will
   * keep an owning reference to the observer.  If ownsWeak is true, then
   * aObserver must implement nsISupportsWeakReference, and the bookmark
   * service will keep a weak reference to the observer.
   */
  void addObserver(in nsINavBookmarkObserver observer, in boolean ownsWeak);

  /**
   * Removes a bookmark observer.
   */
  void removeObserver(in nsINavBookmarkObserver observer);

  /**
   * Runs the passed callback inside of a database transaction.
   * Use this when a lot of things are about to change, for example
   * adding or deleting a large number of bookmark items. Calls can
   * be nested. Observers are notified when batches begin and end, via 
   * nsINavBookmarkObserver.onBeginUpdateBatch/onEndUpdateBatch.
   *
   * @param aCallback
   *        nsINavHistoryBatchCallback interface to call.
   * @param aUserData
   *        Opaque parameter passed to nsINavBookmarksBatchCallback
   */
  void runInBatchMode(in nsINavHistoryBatchCallback aCallback,
                      in nsISupports aUserData);
};
