/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "nsISupports.idl"

// decls for stuff from other files
interface nsIURI;
interface calIItemBase;
interface nsIVariant;

// forward decls for this file
interface calICalendarACLManager;
interface calICalendarACLEntry;
interface calIObserver;
interface calIOperationListener;
interface calIRange;
interface calISchedulingSupport;
interface calIDateTime;
interface calIOperation;
interface calIStatusObserver;
interface nsIDOMChromeWindow;


[scriptable, uuid(b18782c0-6557-4e8e-931d-4bf052f0a31e)]
interface calICalendar : nsISupports
{
  /**
   * Unique ID of this calendar. Only the calendar manager is allowed to set
   * this attribute. For everybody else, it should be considered to be
   * read-only.
   * The id is null for unregistered calendars.
   */
  attribute AUTF8String id;

  /**
   * Name of the calendar
   * Notes: Can only be set after the calendar is registered with the calendar manager.
   */
  attribute AUTF8String name;

  /**
   * Type of the calendar
   *   'memory', 'storage', 'caldav', etc
   */
  readonly attribute AUTF8String type;

  /**
   * If this calendar is provided by an extension, this attribute should return
   * the extension's id, otherwise null.
   */
  readonly attribute AString providerID;

  /**
   * Returns the acl manager for the calendar, based on the "aclManagerClass"
   * property. If this property is not defined, the default manager is used
   */
  readonly attribute calICalendarACLManager aclManager;

  /**
   * Returns the acl entry associated to the calendar.
   */
  readonly attribute calICalendarACLEntry aclEntry;

  /**
   * Multiple calendar instances may be composited, logically acting as a
   * single calendar, e.g. for caching puorposing.
   * This attribute determines the topmost calendar that returned items should
   * belong to. If the current instance is the topmost calendar, then it should
   * be returned directly.
   *
   * @see calIItemBase::calendar
   */
  attribute calICalendar superCalendar;

  /**
   * Setting this URI causes the calendar to be (re)loaded.
   * This is not an unique identifier! It is also not unchangeable. Don't
   * use it to identify a calendar, use the id attribute for that purpose.
   */
  attribute nsIURI uri;

  /**
   * Is this calendar read-only?  Used by the UI to decide whether or not
   * widgetry should allow editing.
   */
  attribute boolean readOnly;

  /**
   * Whether or not it makes sense to call refresh() on this calendar.
   */
  readonly attribute boolean canRefresh;

  /**
   * Setting this attribute to true will prevent the calendar to make calendar properties
   * persistent, which is useful if you would like to set properties on unregistered
   * calendar instances.
   */
  attribute boolean transientProperties;

  /**
   * Gets a calendar property.
   * The call returns null in case the property is not known;
   * callers should use a sensible default in that case.
   *
   * It's up to the provider where to store properties,
   * e.g. on the server or in local prefs.
   *
   * Currently known properties are:
   *   [boolean]  disabled
   *   [boolean]  auto-enabled       If true, the calendar will be enabled on next startup.
   *   [boolean]  force-disabled     If true, the calendar cannot be enabled (transient).
   *   [boolean]  calendar-main-in-composite
   *   [string]   name
   *   [boolean]  readOnly
   *   [boolean]  requiresNetwork    If false, the calendar does not require
   *                                   network access at all. This is mainy used
   *                                   as a UI hint.
   *   [boolean]  suppressAlarms     If true, alarms of this calendar are not minded.
   *   [boolean]  cache.supported    If true, the calendar should to be cached,
   *                                   e.g. this generally applies to network calendars;
   *                                   default is true (if not present).
   *   [boolean]  cache.enabled      If true, the calendar is cached; default is false.
   *   [boolean]  cache.always       If true, the cache will always be enabled
   *                                   and the user cannot turn it off. For
   *                                   backward compatibility, return true for
   *                                   cache.enabled too.
   *
   *   [nsresult] currentStatus      The current error status of the calendar (transient).
   *
   *   [calIItipTransport] itip.transport    If the provider implements a custom calIItipTransport (transient)
   *                                           If null, then Email Scheduling will effectively be
   *                                           disabled. This means for example, the calendar will
   *                                           not show up in the list of calendars to store an
   *                                           invitation in.
   *   [boolean] itip.disableRevisionChecks  If true, the iTIP handling code disables revision checks
   *                                            against SEQUENCE and DTSTAMP, and will never reject an
   *                                            iTIP message as outdated
   *   [nsIMsgIdentity] imip.identity        If provided, this is the email identity used for
   *                                           scheduling purposes
   *   [boolean] imip.identity.disabled      If true, this calendar doesn't support switching imip
   *                                           identities. This for example means that the
   *                                           dropdown of identities will not be shown in the
   *                                           calendar properties dialog. (transient)
   *                                           scheduling purposes
   *   [nsIMsgAccount] imip.account          If provided, this is the email account used for
   *                                           scheduling purposes
   *   [string] imip.identity.key            If provided, this is the email internal identity key used to
   *                                           get the above
   *
   *   [string]   organizerId        If provided, this is the preset organizer id on creating
   *                                   scheduling appointments (transient)
   *   [string]   organizerCN        If provided, this is the preset organizer common name on creating
   *                                   scheduling appointments (transient)
   *
   * The following calendar capabilities can be used to inform the UI or backend
   * that certain features are not supported. If not otherwise mentioned, not
   * specifying these capabilities assumes a default value of true
   *   capabilities.alarms.popup.supported              Supports popup alarms
   *   capabilities.alarms.oninviations.supported       Supports alarms on inviations.
   *   capabilities.alarms.maxCount                     Maximum number of alarms supported per event
   *   capabilities.attachments.supported               Supports attachments
   *   capabilities.categories.maxCount                 Maximum number of supported categories.
   *                                                      -1 means infinite, 0 means disabled.
   *   capabilities.privacy.supported                   Supports a privacy state
   *   capabilities.priority.supported                  Supports the priority field
   *   capabilities.events.supported                    Supports tasks
   *   capabilities.tasks.supported                     Supports events
   *   capabilities.timezones.floating.supported        Supports local time
   *   capabilities.timezones.UTC.supported             Supports UTC/GMT timezone
   *   capabilities.autoschedule.supported              Supports caldav schedule properties in
   *                                                      icalendar (SCHEDULE-AGENT, SCHEDULE-STATUS...)
   *
   * The following capabilities are used to restrict the values for specific
   * fields. An array should be specified with the values, the default
   * values are specified here. Extensions using this need to take care of
   * adding any UI elements needed in an overlay. To make sure the correct
   * elements are shown, those elements should additionally specify an attribute
   * "provider", with the type of the provider.
   *
   *   capabilities.privacy.values = ["PUBLIC", "CONFIDENTIAL", "PRIVATE"];
   *
   * The following special capability disables rewriting the WWW-Authenticate
   * header on HTTP requests to include the calendar name. The default value
   * is false, i.e rewriting is NOT disabled.
   *
   *   capabilities.realmrewrite.disabled = false
   *
   * The following capability describes if the calendar can be permanently
   * deleted, or just unsubscribed. If this property is not specified, then
   * only unsubscribing is allowed. If an empty array is specified, neither
   * deleting nor unsubscribing is presented in the UI.
   *
   *   capabilities.removeModes = ["delete", "unsubscribe"]
   *
   * @param aName property name
   * @return value (string, integer and boolean values are supported),
   *               else null
   */
  nsIVariant getProperty(in AUTF8String aName);

  /**
   * Sets a calendar property.
   * This will (only) cause a notification onPropertyChanged() in case
   * the value has changed.
   *
   * It's up to the provider where to store properties,
   * e.g. on the server or in local prefs.
   *
   * @param aName property name
   * @param aValue value
   *               (string, integer and boolean values are supported)
   */
  void setProperty(in AUTF8String aName, in nsIVariant aValue);

  /**
   * Deletes a calendar property.
   *
   * It's up to the provider where to store properties,
   * e.g. on the server or in local prefs.
   *
   * @param aName property name
   */
  void deleteProperty(in AUTF8String aName);

  /**
   * In combination with the other parameters to getItems(), these
   * constants provide for a very basic filtering mechanisms for use
   * in getting and observing items.  At some point fairly soon, we're
   * going to need to generalize this mechanism significantly (so we
   * can allow boolean logic, categories, etc.).
   *
   * When adding item filters (bits which, when not set to 1, reduce the
   * scope of the results), use bit positions <= 15, so that
   * ITEM_FILTER_ALL_ITEMS remains compatible for components that have the
   * constant compiled in.
   *
   * XXX the naming here is questionable; adding a filter (setting a bit, in
   * this case) usually _reduces_ the set of items that pass the set of
   * filters, rather than adding to it.
   */
  const unsigned long ITEM_FILTER_COMPLETED_YES = 1 << 0;
  const unsigned long ITEM_FILTER_COMPLETED_NO = 1 << 1;
  const unsigned long ITEM_FILTER_COMPLETED_ALL = (ITEM_FILTER_COMPLETED_YES |
                                                   ITEM_FILTER_COMPLETED_NO);

  const unsigned long ITEM_FILTER_TYPE_TODO = 1 << 2;
  const unsigned long ITEM_FILTER_TYPE_EVENT = 1 << 3;
  const unsigned long ITEM_FILTER_TYPE_JOURNAL = 1 << 4;
  const unsigned long ITEM_FILTER_TYPE_ALL = (ITEM_FILTER_TYPE_TODO |
                                              ITEM_FILTER_TYPE_EVENT |
                                              ITEM_FILTER_TYPE_JOURNAL);

  const unsigned long ITEM_FILTER_ALL_ITEMS = 0xFFFF;

  /**
   * If set, return calIItemBase occurrences for all the appropriate instances,
   * as determined by an item's recurrenceInfo.  All of these occurrences will
   * have their parentItem set to the recurrence parent.  If not set, will
   * return only calIItemBase parent items.
   */
  const unsigned long ITEM_FILTER_CLASS_OCCURRENCES = 1 << 16;

  /**
   * Scope: Attendee
   * Filter items that correspond to an invitation from another
   * user and the current user has not replied to it yet.
   */
  const unsigned long ITEM_FILTER_REQUEST_NEEDS_ACTION = 1 << 17;

  /**
   * Flags for items that have been created, modified or deleted while
   * offline.
   * ITEM_FILTER_OFFLINE_DELETED is a particular case in that elements *must*
   * be excluded from searches when not specified in the filter mask.
   */
  const unsigned long ITEM_FILTER_OFFLINE_CREATED = 1 << 29;
  const unsigned long ITEM_FILTER_OFFLINE_MODIFIED = 1 << 30;
  const unsigned long ITEM_FILTER_OFFLINE_DELETED = 1 << 31;

  void addObserver( in calIObserver observer );
  void removeObserver( in calIObserver observer );

  /**
   * supportsScheduling indicates whether the calendar implements the
   * calISchedulingSupport interface.
   */
  readonly attribute boolean supportsScheduling;

  /**
   * getSchedulingSupport provides a calISchedulingSupport implementation for
   * calendars that support it.
   */
  calISchedulingSupport getSchedulingSupport();

  /**
   * addItem adds the given calIItemBase to the calendar.
   *
   * @param aItem       item to add
   * @return            optional operation handle to track the operation
   *
   * - If aItem already has an ID, that ID is used when adding.
   * - If aItem is mutable and has no ID, the calendar is expected
   *   to generate an ID for the item.
   * - If aItem is immutable and has no ID, an error is thrown.
   *
   * The result of the operation is the calIItemBase corresponding to the
   * immutable version of the newly added item.
   *
   * If an item with a given ID already exists in the calendar, the Promise is
   * rejected with a NS_ERROR_XXXXX error.
   *
   * @return {Promise<calIItemBase>}
   */
  Promise addItem(in calIItemBase aItem);

  /**
   * adoptItem adds the given calIItemBase to the calendar, but doesn't
   * clone it. It adopts the item as-is. This is generally for use in
   * performance-critical situations where there is no danger of the caller
   * using the item after making the call.
   *
   * @see addItem
   *
   * @return {Promise<calIItemBase>}
   */
  Promise adoptItem(in calIItemBase aItem);

  /**
   * modifyItem takes a modified item and modifies the
   * calendar's internal version of the item to match. The item is expected to
   * be mutable and have an ID that already exists in the calendar. If it does
   * not, the Promise is rejected with NS_ERROR_XXXXX.
   *
   * If the generation of the given aNewItem does not match the generation
   * of the internal item (indicating that someone else modified the
   * item), the Promise is rejected with NS_ERROR_XXXXX.
   *
   * If you would like to disable revision checks, pass null as aOldItem. This
   * will overwrite the item on the server.
   *
   * @param aNewItem    new version to replace the old one
   * @param aOldItem    caller's view of the item to be changed, as it is now
   * @return {Promise<calIItemBase>} the newly-updated immutable version of
   *                                 the modified item.
   *
   */
  Promise modifyItem(in calIItemBase aNewItem, in calIItemBase aOldItem);

  /**
   * Deletes an item. The item is expected to have an ID that already exists in
   * the calendar.
   *
   * @param aItem            item to delete
   * @return {Promise<void>} optional operation handle to track the operation
   */
  Promise deleteItem(in calIItemBase aItem);

  /**
   * Get a single event.  The event will be typed as one of the subclasses
   * of calIItemBase (whichever concrete type is most appropriate).
   *
   * @param aId                           UID of the event
   * @return {Promise<calIItemBase|null>} A Promise that is resolved with the item if found.
   */
  Promise getItem(in string aId);

  /**
   * XXX As mentioned above, this method isn't suitably general.  It's just
   * placeholder until it gets supplanted by something more SQL or RDF-like.
   *
   *   Ordering: This method is currently guaranteed to return lists ordered
   *   as follows to make for the least amount of pain when
   *   migrating existing frontend code:
   *
   *     The events are sorted based on the order of their next occurrence
   *     if they recur in the future or their last occurrence in the past
   *     otherwise.  Here's a presentation of the sort criteria using the
   *     time axis:
   *
   *     -----(Last occurrence of Event1)---(Last occurrence of Event2)----(Now)----(Next occurrence of Event3)---->
   *
   *     (Note that Event1 and Event2 will not recur in the future.)
   *
   *   We should probably be able get rid of this ordering constraint
   *   at some point in the future.
   *
   * Note that the range is intended to act as a mask on the
   * occurrences, not just the initial recurring items.  So if a
   * getItems() call without ITEM_FILTER_CLASS_occurrenceS is made, all
   * events and todos which have occurrences inside the range should
   * be returned, even if some of those events or todos themselves
   * live outside the range.
   *
   * @param aItemFilter ITEM_FILTER flags, or-ed together
   * @param aCount      Maximum number of items to return, or 0 for
   *                    an unbounded query.
   * @param aRangeStart Items starting at this time or after should be
   *                    returned.  If invalid, assume "since the beginning
   *                    of time".
   * @param aRangeEndEx Items starting before (not including) aRangeEndEx should be
   *                    returned.  If null, assume "until the end of time".
   * @return {ReadableStream<calIItemBase>}
   */
   jsval getItems(in unsigned long aItemFilter,
                  in unsigned long aCount,
                  in calIDateTime aRangeStart,
                  in calIDateTime aRangeEndEx);

  /**
   * Similar to getItems() but returns all results in a single array.
   * @param aItemFilter ITEM_FILTER flags, or-ed together
   * @param aCount      Maximum number of items to return, or 0 for
   *                    an unbounded query.
   * @param aRangeStart Items starting at this time or after should be
   *                    returned.  If invalid, assume "since the beginning
   *                    of time".
   * @param aRangeEndEx Items starting before (not including) aRangeEndEx should be
   *                    returned.  If null, assume "until the end of time".
   * @return {Promise<calIItemBase[]>}
   */
  Promise getItemsAsArray(in unsigned long aItemFilter,
                          in unsigned long aCount,
                          in calIDateTime aRangeStart,
                          in calIDateTime aRangeEndEx);

  /**
   * Refresh the datasource, and call the observers for any changes found.
   * If the provider doesn't know the details of the changes it must call
   * onLoad on its observers.
   *
   * @return            optional operation handle to track the operation
   */
  calIOperation refresh();

  /**
   * Turn on batch mode. Observers will get a notification of this.
   * They will still get notified for every individual change, but they are
   * free to ignore those notifications.
   * Use this when a lot of changes are about to happen, and it would be
   * useless to refresh the display (or the backend store) for every change.
   * Caller must make sure to also call endBatchMode. Make sure all errors
   * are caught!
   */
  void startBatch();

  /**
   * Turn off batch mode.
   */
  void endBatch();
};

/**
 * Used to allow multiple calendars (eg work and home) to be easily queried
 * and displayed as a single unit. All calendars are referenced by ID, i.e.
 * calendars need to have an ID when being added.
 */
[scriptable, uuid(6748fa00-79b5-4728-84f3-20dd47e0b031)]
interface calICompositeCalendar : calICalendar
{
  /**
   * Adds a calendar to the composite, if not already part of it.
   *
   * @param aCalendar the calendar to be added
   */
  void addCalendar(in calICalendar aCalendar);

  /**
   * Remove a calendar from the composite
   *
   * @param aCalendar the calendar to be removed
   */
  void removeCalendar(in calICalendar aCalendar);

  /**
   * If a calendar for the given ID exists in the CompositeCalendar,
   * return it; otherwise return null.
   *
   * @param aId id of calendar
   * @return calendar, or null if none
   */
  calICalendar getCalendarById(in AUTF8String aId);

  /* return a list of all calendars currently registered */
  Array<calICalendar> getCalendars();

  /**
   * In order for addItem() to be called on this object, it is first necessary
   * to set this attribute to specify which underlying calendar the item is
   * to be added to.
   */
  attribute calICalendar defaultCalendar;

  /**
   * If set, the composite will initialize itself from calICalendarManager
   * prefs keyed off of the provided prefPrefix, and update those prefs to
   * track changes in calendar membership and default calendar.
   */
  attribute ACString prefPrefix;

  /**
   * If returns true there is a process running that needs to displayed
   * by the statusObserver
   */
  readonly attribute boolean statusDisplayed;

  /**
   * Sets a statusobserver for status notifications like startMeteors() and StopMeteors().
   */
  void setStatusObserver(in calIStatusObserver aStatusObserver, in nsIDOMChromeWindow aWindow);
};

/**
 * Make a more general nsIObserverService2 and friends to support
 * nsISupports data and use that instead?
 *
 * NOTE: When adding methods here, please also add them in calUtils.jsm's
 * createAdapter() method.
 */
[scriptable, uuid(2953c9b2-2c73-11d9-80b6-00045ace3b8d)]
interface calIObserver : nsISupports
{
  void onStartBatch(in calICalendar aCalendar);
  void onEndBatch(in calICalendar aCalendar);
  void onLoad( in calICalendar aCalendar );
  void onAddItem( in calIItemBase aItem );
  void onModifyItem( in calIItemBase aNewItem, in calIItemBase aOldItem );
  void onDeleteItem( in calIItemBase aDeletedItem );
  void onError( in calICalendar aCalendar, in nsresult aErrNo, in AUTF8String aMessage );

  /// Called after a property is changed.
  void onPropertyChanged(in calICalendar aCalendar,
                         in AUTF8String aName,
                         in nsIVariant aValue,
                         in nsIVariant aOldValue);

  /// Called before the property is deleted.
  void onPropertyDeleting(in calICalendar aCalendar,
                          in AUTF8String aName);
};

/**
 * calICompositeObserver interface adds things to observe changes to
 * a calICompositeCalendar
 */
[scriptable, uuid(a3584c92-b8eb-4aa8-a638-e46a2e11d6a9)]
interface calICompositeObserver : calIObserver
{
  void onCalendarAdded( in calICalendar aCalendar );
  void onCalendarRemoved( in calICalendar aCalendar );
  void onDefaultCalendarChanged( in calICalendar aNewDefaultCalendar );
};

/**
 * Async operations are called back via this interface.  If you know that your
 * object is not going to get called back for either of these methods, having
 * them return NS_ERROR_NOT_IMPLEMENTED is reasonable.
 *
 * NOTE: When adding methods here, please also add them in calUtils.jsm's
 * createAdapter() method.
 */
[scriptable, uuid(ed3d87d8-2c77-11d9-8f5f-00045ace3b8d)]
interface calIOperationListener : nsISupports
{
  /**
   * For add, modify, and delete.
   *
   * @param aCalendar       the calICalendar on which the operation took place
   * @param aStatus         status code summarizing what happened
   * @param aOperationType  type of operation that was completed
   * @param aId             UUID of element that was changed
   * @param aDetail         not yet fully specified.  If aStatus is an error
   *                        result, this will probably be an extended error
   *                        string (eg one returned by a server).
   */
  void onOperationComplete(in calICalendar aCalendar,
                           in nsresult aStatus,
                           in unsigned long aOperationType,
                           in string aId,
                           in nsIVariant aDetail);
  const unsigned long ADD = 1;
  const unsigned long MODIFY = 2;
  const unsigned long DELETE = 3;
  const unsigned long GET = 4;

  /**
   * For getItem and getItems.
   *
   * @param aStatus   status code summarizing what happened.
   * @param aItemType type of interface returned in the array (@see
   *                  calICalendar::GetItems).
   * @param aDetail   not yet fully specified.  If aStatus is an error
   *                  result, this will probably be an extended error
   *                  string (eg one returned by a server).
   * @param aItems    array of immutable items
   *
   * Multiple onGetResults might be called
   */
  void onGetResult(in calICalendar aCalendar,
                   in nsresult aStatus,
                   in nsIIDRef aItemType,
                   in nsIVariant aDetail,
                   [iid_is(aItemType)] in Array<nsQIResult> aItems);
};
