// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.enterprise.adaptor;

import java.net.URI;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Map;

/**
 * Interface that allows at-will pushing of {@code DocId}s to the GSA.
 */
public interface DocIdPusher {
  /**
   * Push {@code DocId}s immediately and block until they are successfully
   * provided to the GSA or the error handler gives up. This method can take a
   * while in error conditions, but is not something that generally needs to be
   * avoided.
   *
   * <p>Equivalent to {@code pushDocIds(docIds, null)} and {@link
   * #pushRecords(Iterable)} with default values for each {@code Record}.
   *
   * @return {@code null} on success, otherwise the first DocId to fail
   * @throws InterruptedException if interrupted and no DocIds were sent
   * @see #pushDocIds(Iterable, ExceptionHandler)
   */
  public DocId pushDocIds(Iterable<DocId> docIds)
      throws InterruptedException;

  /**
   * Push {@code DocId}s immediately and block until they are successfully
   * provided to the GSA or the error handler gives up. This method can take a
   * while in error conditions, but is not something that generally needs to be
   * avoided.
   *
   * <p>If handler is {@code null}, then a default error handler is used.
   *
   * <p>Equivalent to {@link #pushRecords(Iterable, ExceptionHandler)}
   * with default values for each {@code Record}.
   *
   * @return {@code null} on success, otherwise the first DocId to fail
   * @throws InterruptedException if interrupted and no DocIds were sent
   */
  public DocId pushDocIds(Iterable<DocId> docIds, ExceptionHandler handler)
      throws InterruptedException;

  /**
   * Push {@code Record}s immediately and block until they are successfully
   * provided to the GSA or the error handler gives up. This method can take a
   * while in error conditions, but is not something that generally needs to be
   * avoided.
   *
   * <p>Equivalent to {@code pushRecords(records, null)}.
   *
   * @return {@code null} on success, otherwise the first Record to fail
   * @throws InterruptedException if interrupted and no Records were sent
   * @see #pushRecords(Iterable, ExceptionHandler)
   */
  public Record pushRecords(Iterable<Record> records)
      throws InterruptedException;

  /**
   * Push {@code Record}s immediately and block until they are successfully
   * provided to the GSA or the error handler gives up. This method can take a
   * while in error conditions, but is not something that generally needs to be
   * avoided.
   *
   * <p>If handler is {@code null}, then a default error handler is used.
   *
   * @return {@code null} on success, otherwise the first Record to fail
   * @throws InterruptedException if interrupted and no Records were sent
   */
  public Record pushRecords(Iterable<Record> records, ExceptionHandler handler)
      throws InterruptedException;

  /**
   * Push named resources immediately and block until they are successfully
   * provided to the GSA or the error handler gives up. This method can take a
   * while in error conditions, but is not something that generally needs to be
   * avoided.
   *
   * <p>Named resources are {@code DocId}s without any content or metadata, that
   * only exist for ACL inheritance. These {@code DocId} will never be visible
   * to the user and have no meaning outside of ACL processing.
   *
   * <p>If you plan on using the return code, then the provided map should have
   * a predictable iteration order, like {@link java.util.TreeMap}.
   *
   * <p>Equivalent to {@code pushNamedResources(resources, null)}.
   *
   * @return {@code null} on success, otherwise the first DocId to fail
   * @throws InterruptedException if interrupted and no resources were sent
   * @see #pushNamedResources(Map, ExceptionHandler)
   */
  public DocId pushNamedResources(Map<DocId, Acl> resources)
      throws InterruptedException;

  /**
   * Push named resources immediately and block until they are successfully
   * provided to the GSA or the error handler gives up. This method can take a
   * while in error conditions, but is not something that generally needs to be
   * avoided.
   *
   * <p>Named resources are {@code DocId}s without any content or metadata, that
   * only exist for ACL inheritance. These {@code DocId} will never be visible
   * to the user and have no meaning outside of ACL processing.
   *
   * <p>If you plan on using the return code, then the provided map should have
   * a predictable iteration order, like {@link java.util.TreeMap}.
   *
   * <p>If handler is {@code null}, then a default error handler is used.
   *
   * @return {@code null} on success, otherwise the first DocId to fail
   * @throws InterruptedException if interrupted and no resources were sent
   */
  public DocId pushNamedResources(Map<DocId, Acl> resources,
                                  ExceptionHandler handler)
      throws InterruptedException;

  /**
   * Blocking call to push group definitions to GSA ends in success or
   * when default error handler gives up.  Can take significant time
   * if errors arise.
   * 
   * <p>A group definition consists of a group being defined
   * and members, which is a list of users and groups.
   *
   * <p>If you plan on using the return code, then the provided map should have
   * a predictable iteration order, like {@link java.util.TreeMap}.
   *
   * @return {@code null} on success, otherwise the first GroupPrincipal to fail
   * @throws InterruptedException if interrupted
   */
  public GroupPrincipal pushGroupDefinitions(
      Map<GroupPrincipal, ? extends Collection<Principal>> defs,
      boolean caseSensitive) throws InterruptedException;

  /**
   * Blocking call to push group definitions to GSA ends in success or
   * when provided error handler gives up.  Can take significant time
   * if errors arise.
   * 
   * <p>A group definition consists of a group being defined
   * and members, which is a list of users and groups.
   *
   * <p>If you plan on using the return code, then the provided map should have
   * a predictable iteration order, like {@link java.util.TreeMap}.
   *
   * <p>If handler is {@code null}, then a default error handler is used.
   *
   * @return {@code null} on success, otherwise the first GroupPrincipal to fail
   * @throws InterruptedException if interrupted
   */
  public GroupPrincipal pushGroupDefinitions(
      Map<GroupPrincipal, ? extends Collection<Principal>> defs,
      boolean caseSensitive, ExceptionHandler handler)
      throws InterruptedException;

  /**
   * Immutable feed attributes for a document identified by its {@code DocId}.
   */
  public static final class Record implements DocIdSender.Item {
    private final DocId id;
    private final boolean delete;
    private final Date lastModified;
    private final URI link;
    private final boolean crawlImmediately;
    private final boolean crawlOnce;
    private final boolean lock;

    private Record(DocId docid, boolean delete, Date lastModified,
        URI link, boolean crawlImmediately, boolean crawlOnce, boolean lock) {
      this.id = docid;
      this.delete = delete;
      this.lastModified = lastModified;
      this.link = link;
      this.crawlImmediately = crawlImmediately;
      this.crawlOnce = crawlOnce;
      this.lock = lock;
    }

    /**
     * The identifier for the document this record is providing information for.
     *
     * @return non-{@code null} identifier for the document
     */
    public DocId getDocId() {
      return id;
    }

    /**
     * Whether the GSA is being informed the document has been deleted.
     */
    public boolean isToBeDeleted() {
      return delete;
    }

    /**
     * The last modified date of the document. This is used for determining that
     * the GSA's version is older and that the GSA should recrawl soon (instead
     * of natually discovering the modification). If {@code null}, then natural
     * crawling is the primary method of detecting modifications.
     */
    public Date getLastModified() {
      return lastModified;
    }

    /**
     * The URI that should be displayed to the user in search results. If {@code
     * null}, then the crawl URI representing the {@code DocId} is used.
     */
    public URI getResultLink() {
      return link;
    }

    /**
     * Informs the GSA that the document has been modified, and the GSA should
     * give high priority to recrawling the document.
     */
    public boolean isToBeCrawledImmediately() {
      return crawlImmediately;
    }

    /**
     * Informs the GSA that it should only crawl the document once. This
     * disables automatic detection of modifications by the GSA for this
     * document.
     */
    public boolean isToBeCrawledOnce() {
      return crawlOnce;
    }

    /**
     * Locks the document into the GSA's index. This informs the GSA that it
     * should choose to evict other documents from its index when the document
     * license limit is reached.
     */
    public boolean isToBeLocked() {
      return lock;
    }

    /**
     * Checks for equality based on all visible fields.
     */
    @Override
    public boolean equals(Object o) {
      boolean same = false;
      if (null != o && this.getClass().equals(o.getClass())) {
        Record other = (Record) o;
        same = this.id.equals(other.id)
            && (this.delete == other.delete)
            && (this.crawlImmediately == other.crawlImmediately)
            && (this.crawlOnce == other.crawlOnce)
            && (this.lock == other.lock)
            && equalsNullSafe(lastModified, other.lastModified)
            && equalsNullSafe(link, other.link);
      }
      return same;
    }

    /**
     * Generates hash code based on all visible fields.
     */
    @Override
    public int hashCode() {
      Object members[] = new Object[] { id, delete, lastModified, link,
          crawlImmediately, crawlOnce, lock };
      return Arrays.hashCode(members);
    }

    /**
     * Generates a string representation of this instance useful for debugging
     * that contains all visible fields.
     */
    @Override
    public String toString() {
      return "Record(docid=" + id.getUniqueId()
          + ",delete=" + delete
          + ",lastModified=" + lastModified
          + ",resultLink=" + link
          + ",crawlImmediately=" + crawlImmediately
          + ",crawlOnce=" + crawlOnce
          + ",lock=" + lock + ")";
    }

    private static boolean equalsNullSafe(Object a, Object b) {
      boolean same;
      if (null == a && null == b) {
        same = true;
      } else if (null != a && null != b) {
        same = a.equals(b);
      } else {
        same = false;
      }
      return same;
    }

    /**
     * Builder to create instances of Record.
     */
    public static class Builder {
      private DocId docid = null;
      private boolean delete = false;
      private Date lastModified = null;
      private URI link = null;
      private boolean crawlImmediately = false;
      private boolean crawlOnce = false;
      private boolean lock = false;

      /**
       * Create mutable builder for building {@link Record} instances.
       *
       * @param id non-{@code null} identifier for the document being described
       */
      public Builder(DocId id) {
        if (null == id) {
          throw new NullPointerException();
        }
        docid = id;
      }

      /**
       * Create mutable builder initialized to values provided by {@code
       * startPoint}. This is useful for making changes to an existing {@code
       * Record}.
       */
      public Builder(Record startPoint) {
        this.docid = startPoint.id;
        this.delete = startPoint.delete;
        this.lastModified = startPoint.lastModified;
        this.link = startPoint.link;
        this.crawlImmediately = startPoint.crawlImmediately;
        this.crawlOnce = startPoint.crawlOnce;
        this.lock = startPoint.lock;
      }

      /**
       * Set the identifier for the document this record is providing
       * information for. This replaces the value provided to the constructor.
       *
       * @param id non-{@code null} identifier for the document
       * @return the same instance of the builder, for chaining calls
       */
      public Builder setDocId(DocId id) {
        if (null == id) {
          throw new NullPointerException();
        }
        this.docid = id;
        return this;
      }

      /**
       * Set whether the GSA is being informed the document has been deleted.
       * When {@code false}, the GSA is being informed the document exists. The
       * default is {@code false}.
       *
       * @return the same instance of the builder, for chaining calls
       */
      public Builder setDeleteFromIndex(boolean b) {
        this.delete = b;
        return this;
      }

      /**
       * Provides the last-modified date of the document. This is used by the
       * GSA to learn that the document has been modified since the GSA last
       * retrieved the document's contents. When {@code null}, the GSA must use
       * its natural crawling of content to discover changes. The default is
       * {@code null}.
       *
       * @return the same instance of the builder, for chaining calls
       */
      public Builder setLastModified(Date lastModified) {
        this.lastModified = lastModified;
        return this;
      }

      /**
       * Set the URI to be displayed to the user in search results. If {@code
       * null}, then the crawl URI representing the {@code DocId} is used. The
       * default is {@code null}.
       *
       * @return the same instance of the builder, for chaining calls
       */
      public Builder setResultLink(URI link) {
        this.link = link;
        return this;
      }

      /**
       * Inform the GSA that the document has been modified, and that the GSA
       * should give high priority to recrawling the document. The default is
       * {@code false}.
       *
       * @return the same instance of the builder, for chaining calls
       */
      public Builder setCrawlImmediately(boolean crawlImmediately) {
        this.crawlImmediately = crawlImmediately;
        return this;
      }

      /**
       * Instruct the GSA to not recrawl the document after the initial
       * retrieval. The default is {@code false}.
       *
       * @return the same instance of the builder, for chaining calls
       */
      public Builder setCrawlOnce(boolean crawlOnce) {
        this.crawlOnce = crawlOnce;
        return this;
      }

      /**
       * Instruct the GSA to "lock" the document into its index. This causes
       * other documents to be evicted from the index when the document license
       * limit is reached. The default is {@code false}.
       *
       * @return the same instance of the builder, for chaining calls
       */
      public Builder setLock(boolean lock) {
        this.lock = lock;
        return this;
      }

      /** Creates single instance of Record.  Does not reset builder. */
      public Record build() {
        return new Record(docid, delete, lastModified,
            link, crawlImmediately, crawlOnce, lock);
      }
    }
  }
}
