/*
 * Copyright 2015-2017 MarkLogic Corporation
 *
 * 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.marklogic.client.datamovement;

import com.marklogic.client.DatabaseClient;
import com.marklogic.client.query.QueryDefinition;
import com.marklogic.client.query.StringQueryDefinition;
import com.marklogic.client.query.StructuredQueryDefinition;
import com.marklogic.client.query.RawCombinedQueryDefinition;
import com.marklogic.client.datamovement.impl.DataMovementManagerImpl;

import java.util.Iterator;

/**
 * DataMovementManager is the starting point for getting new instances of
 * QueryBatcher and WriteBatcher, configured with a DatabaseClient and
 * ForestConfiguration.  On instantiation, it will immediately call
 * readForestConfig to obtain the ForestConfiguration from which it can create
 * host-specific DatabaseClient instances for each applicable host.  Applicable
 * hosts are those with forests for the database specified in the
 * DatabaseClient.  If not specified, the database is the default database for
 * the port in the DatabaseClient.  Call {@link #release()
 * dataMovementMangaer.release()} when you're done with your
 * DataMovementManager instance to free resources associated with those
 * host-specific DatabaseClient instances.
 *
 * Sample Usage:
 *
 *     DataMovementManager dataMovementManager = databaseClient.newDataMovementManager();
 *     WriteBatcher batcher = dataMovementManager.newWriteBatcher();
 *     dataMovementManager.startJob(batcher);
 *     . . .
 *     dataMovementManager.stopJob(batcher);
 *     dataMovementManager.release();
 */
public interface DataMovementManager {
  /** Calls release() on all host-specific DatabaseClient instances (but not on
   * the DatabaseClient instance used to create this DataMovementManager
   * instance).
   */
  public void release();

  /**
   * Begins job tracking on the WriteBatcher.  Calling startJob is not
   * required on a WriteBatcher if you don't intend to ever call stopJob or
   * look at the JobReport.
   * @param batcher the WriteBatcher instance which has to be started
   * @return a JobTicket which can be used to track the job
   */
  public JobTicket startJob(WriteBatcher batcher);

  /**
   * Starts the QueryBatcher job.
   * @param batcher the QueryBatcher instance which has to be started
   * @return a JobTicket which can be used to track the job
   */
  public JobTicket startJob(QueryBatcher batcher);

  /**
   * Not yet implemented 
   * @param ticket the JobTicket for which the report has to be generated
   * @return the report for the job
   */
  public JobReport getJobReport(JobTicket ticket);

  /**
   * Immediately cancel all queued tasks, prevent new tasks from being added
   * to the queue, and begin to free all resources.  In-process tasks cannot be
   * cancelled because they talk to the REST server which does not have such a
   * mechanism.  This does not block until all in-process tasks are finished,
   * for that use QueryBatcher.awaitCancellation() or WriteBatcher.awaitCancellation().
   *
   * @param ticket indicates the job to stop
   */
  public void stopJob(JobTicket ticket);

  /**
   * Immediately cancel all queued tasks, prevent new tasks from being added
   * to the queue, and begin to free all resources.  In-process tasks cannot be
   * cancelled because they talk to the REST server which does not have such a
   * mechanism.  This does not block until all in-process tasks are finished,
   * for that use QueryBatcher.awaitCancellation() or WriteBatcher.awaitCancellation().
   *
   * @param batcher the batcher instance to stop
   */
  public void stopJob(Batcher batcher);

  /**
   * Create a new WriteBatcher instance.
   *
   * @return the new WriteBatcher instance
   */
  public WriteBatcher newWriteBatcher();

  /**
   * Create a new QueryBatcher instance configured to retrieve uris that
   * match this query.
   *
   * @param query the query used to find matching uris
   *
   * @return the new QueryBatcher instance
   */
  public QueryBatcher newQueryBatcher(StructuredQueryDefinition query);

  /**
   * Create a new QueryBatcher instance configured to retrieve uris that
   * match this query.
   *
   * @param query the query used to find matching uris
   *
   * @return the new QueryBatcher instance
   */
  public QueryBatcher newQueryBatcher(StringQueryDefinition query);

  /**
   * Create a new QueryBatcher instance configured to retrieve uris that
   * match this query.
   *
   * @param query the query used to find matching uris
   *
   * @return the new QueryBatcher instance
   */
  public QueryBatcher newQueryBatcher(RawCombinedQueryDefinition query);

  /**
   * Create a new QueryBatcher instance configured to retrieve uris from
   * this Iterator.  This is helpful when deleting documents when one cannot
   * set the server's [merge timestamp][].  For more discussion, see {@link
   * QueryBatcher}.
   *
   * [merge timestamp]: https://docs.marklogic.com/guide/app-dev/point_in_time#id_32468
   *
   * @param iterator the provider of uris
   *
   * @return the new QueryBatcher instance
   */
  public QueryBatcher newQueryBatcher(Iterator<String> iterator);

  /**
   * Update the ForestConfiguration with the latest from the server.
   *
   * @return the latest ForestConfiguration from the server
   */
  public ForestConfiguration readForestConfig();
}

@@ -5384,28 +5384,28 @@
 from
+ this
 %0D%0A   * 
-this 
 Iterator
 .  T
@@ -5400,24 +5400,189 @@
 Iterator
+.  This form enables the uris (actually any String) to come from%0D%0A   * any source, whereas the other form requires the uris to come from the%0D%0A   * results of a query
 .  This 
 is helpf
@@ -5573,16 +5573,21 @@
 .  This 
+form 
 is helpf
@@ -5625,21 +5625,21 @@
  one
+%0D%0A   *
  cannot
-%0D%0A   *
  set
@@ -5702,21 +5702,21 @@
  see
+%0D%0A   *
  %7B@link
-%0D%0A   *
  Que
@@ -5725,16 +5725,110 @@
 Batcher%7D
+.%0D%0A   *%0D%0A   * The Iterator needn't be thread-safe as it is only iterated from one%0D%0A   * thread
 .%0D%0A   *%0D

add mention that Iterator doesn't need to be thread-safe