// Copyright 2010 Google Inc.
//
// 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.gwtorm.nosql.generic;

import com.google.gwtorm.nosql.CounterShard;
import com.google.gwtorm.nosql.IndexKeyBuilder;
import com.google.gwtorm.nosql.IndexRow;
import com.google.gwtorm.nosql.NoSqlSchema;
import com.google.gwtorm.schema.SequenceModel;
import com.google.gwtorm.server.AtomicUpdate;
import com.google.gwtorm.server.ListResultSet;
import com.google.gwtorm.server.OrmDuplicateKeyException;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;
import com.google.gwtorm.server.Schema;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * Base implementation for {@link Schema} in a {@link GenericDatabase}.
 * <p>
 * NoSQL implementors must extend this class and provide implementations for the
 * abstract methods declared here. Each schema instance will wrap one thread's
 * connection to the data store. Therefore, unlike database, this class does not
 * need to be thread-safe.
 */
public abstract class GenericSchema extends NoSqlSchema {
  private final GenericDatabase<?, ?, ?> db;

  protected GenericSchema(final GenericDatabase<?, ?, ?> d) {
    super(d);
    db = d;
  }

  public void flush() {
  }

  /** @return the database that created this schema instance. */
  public GenericDatabase<?, ?, ?> getDatabase() {
    return db;
  }

  /**
   * Allocate a new unique value from a pool of values.
   * <p>
   * This method is only required to return a unique value per invocation.
   * Implementors may override the method to provide an implementation that
   * returns values out of order.
   * <p>
   * The default implementation of this method stores a {@link CounterShard}
   * under the row key {@code ".sequence." + poolName}, and updates it through
   * the atomic semantics of {@link #atomicUpdate(byte[], AtomicUpdate)}. If the
   * row does not yet exist, it is initialized and the value 1 is returned.
   *
   * @param poolName name of the value pool to allocate from. This is typically
   *        the name of a sequence in the schema.
   * @return a new unique value.
   * @throws OrmException a unique value cannot be obtained.
   */
  @Override
  protected long nextLong(final String poolName) throws OrmException {
    IndexKeyBuilder b = new IndexKeyBuilder();
    b.add(".sequence." + poolName);
    b.delimiter();
    try {
      final long[] res = new long[1];
      atomicUpdate(b.toByteArray(), new AtomicUpdate<byte[]>() {
        @Override
        public byte[] update(byte[] val) {
          CounterShard ctr;
          if (val != null) {
            ctr = CounterShard.CODEC.decode(val);
          } else {
            long start = 1;
            for (SequenceModel s : getDatabase().getSchemaModel()
                .getSequences()) {
              if (poolName.equals(s.getSequenceName())) {
                start = s.getSequence().startWith();
                if (start == 0) {
                  start = 1;
                }
                break;
              }
            }
            ctr = new CounterShard(start, Long.MAX_VALUE);
          }

          if (ctr.isEmpty()) {
            throw new NoMoreValues();
          }

          res[0] = ctr.next();
          return CounterShard.CODEC.encodeToByteString(ctr).toByteArray();
        }
      });
      return res[0];
    } catch (NoMoreValues err) {
      throw new OrmException("Counter '" + poolName + "' out of values");
    }
  }

  /**
   * Fetch one row's data.
   * <p>
   * The default implementation of this method creates a pair of keys and passes
   * them to {@link #scan(byte[], byte[], int, boolean)}. The {@code fromKey} is
   * the supplied {@code key}, while the {@code toKey} has '\0' appended onto
   * {@code key}. If more than one row matches in that range, the method throws
   * an exception.
   *
   * @param key key of the row to fetch and return.
   * @return the data stored under {@code key}; null if no row exists.
   * @throws OrmDuplicateKeyException more than one row was identified in the
   *         key scan.
   * @throws OrmException the data store cannot process the request.
   */
  public byte[] fetchRow(byte[] key) throws OrmDuplicateKeyException,
      OrmException {
    final byte[] fromKey = key;
    final byte[] toKey = new byte[key.length + 1];
    System.arraycopy(key, 0, toKey, 0, key.length);

    ResultSet<Row> r = scan(fromKey, toKey, 2, false);
    try {
      Iterator<Row> i = r.iterator();
      if (!i.hasNext()) {
        return null;
      }

      byte[] data = i.next().getValue();
      if (i.hasNext()) {
        throw new OrmDuplicateKeyException("Unexpected duplicate keys");
      }
      return data;
    } finally {
      r.close();
    }
  }

  /**
   * Fetch multiple rows at once.
   * <p>
   * The default implementation of this method is a simple iteration over each
   * key and executes a sequential fetch with {@link #fetchRow(byte[])}.
   *
   * @param keys keys to fetch and return.
   * @return iteration over the rows that exist and appear in {@code keys}.
   * @throws OrmException the data store cannot process the request.
   */
  public ResultSet<Row> fetchRows(Iterable<byte[]> keys) throws OrmException {
    List<Row> r = new ArrayList<>();
    for (byte[] key : keys) {
      byte[] val = fetchRow(key);
      if (val != null) {
        r.add(new Row(key, val));
      }
    }
    return new ListResultSet<>(r);
  }

  /**
   * Scan a range of keys and return any matching objects.
   * <p>
   * To fetch a single record with a scan, set {@code toKey} to the same array
   * as {@code fromKey}, but append a trailing NUL byte (0x00). The caller
   * should validate that the returned ResultSet contains no more than 1 row.
   * <p>
   * The resulting iteration does not support remove.
   * <p>
   * Each iteration element is a map entry, describing the row key and the row
   * value. The map entry's value cannot be changed.
   *
   * @param fromKey key to start the scan on. This is inclusive.
   * @param toKey key to stop the scan on. This is exclusive.
   * @param limit maximum number of results to return.
   * @param order if true the order will be preserved, false if the result order
   *        order can be arbitrary.
   * @return result iteration for the requested range. The result set may be
   *         lazily filled, or filled completely.
   * @throws OrmException an error occurred preventing the scan from completing.
   */
  public abstract ResultSet<Row> scan(byte[] fromKey, byte[] toKey, int limit,
      boolean order) throws OrmException;

  /**
   * Atomically insert one row, failing if the row already exists.
   * <p>
   * The default implementation of this method relies upon the atomic nature of
   * the {@link #atomicUpdate(byte[], AtomicUpdate)} primitive to test for the
   * row's existence, and create the row only if it is not found.
   *
   * @param key key of the new row to insert.
   * @param newData data of the new row.
   * @throws OrmDuplicateKeyException another row already exists with the
   *         specified key.
   * @throws OrmException the data store cannot process the request right now,
   *         for example due to a network connectivity problem.
   */
  public void insert(byte[] key, final byte[] newData)
      throws OrmDuplicateKeyException, OrmException {
    try {
      atomicUpdate(key, new AtomicUpdate<byte[]>() {
        @Override
        public byte[] update(byte[] oldData) {
          if (oldData != null) {
            throw new KeyExists();
          }
          return newData;
        }
      });
    } catch (KeyExists err) {
      throw new OrmDuplicateKeyException("Duplicate key");
    }
  }

  /**
   * Update a single row, inserting it if it does not exist.
   * <p>
   * Unlike insert, this method always succeeds.
   *
   * @param key key of the row to update, or insert if missing.
   * @param data data to store at this row.
   * @throws OrmException the data store cannot process the request, for example
   *         due to a network connectivity problem.
   */
  public abstract void upsert(byte[] key, byte[] data) throws OrmException;

  /**
   * Delete the row stored under the given key.
   * <p>
   * If the row does not exist, this method must complete successfully anyway.
   * The intent of the caller is to ensure the row does not exist when the
   * method completes, and a row that did not exist satisfies that intent.
   *
   * @param key the key to delete.
   * @throws OrmException the data store cannot perform the removal.
   */
  public abstract void delete(byte[] key) throws OrmException;

  /**
   * Atomically read and update a single row.
   * <p>
   * Unlike schema's atomicUpdate() method, this method must handle missing
   * rows. Implementations must be logically equivalent to the following, but
   * performed atomically within the scope of the single row key:
   *
   * <pre>
   * byte[] oldData = get(key);
   * byte[] newData = update.update(oldData);
   * if (newData != null) {
   *   upsert(key, newData);
   * } else if (oldData != null) {
   *   remove(key);
   * }
   * return data;
   * </pre>
   * <p>
   * Secondary index row updates are assumed to never be part of the atomic
   * update transaction. This is an intentional design decision to fit with many
   * NoSQL product's limitations to support only single-row atomic updates.
   * <p>
   * The {@code update} method may be invoked multiple times before the
   * operation is considered successful. This permits an implementation to
   * perform an opportunistic update attempt, and retry the update if the same
   * row was modified by another concurrent worker.
   *
   * @param key the row key to read, update and return.
   * @param update action to perform on the row's data element. The action may
   *        be passed null if the row doesn't exist.
   * @throws OrmException the database cannot perform the update.
   */
  public abstract void atomicUpdate(byte[] key, AtomicUpdate<byte[]> update)
      throws OrmException;

  /**
   * Check (and delete) an index row if its a fossil.
   * <p>
   * As index rows are written ahead of the main data row being written out,
   * scans sometimes see an index row that does not match the data row. These
   * are ignored for a short period ({@link GenericDatabase#getMaxFossilAge()})
   * to allow the primary data row to eventually get written out. If however the
   * writer never finished the update, these index rows are stale and need to be
   * pruned. Any index row older than the fossil age is removed by this method.
   *
   * @param now timestamp when the current scan started.
   * @param key the index row key.
   * @param row the index row data.
   */
  public void maybeFossilCollectIndexRow(long now, byte[] key, IndexRow row) {
    if (row.getTimestamp() + db.getMaxFossilAge() <= now) {
      fossilCollectIndexRow(key, row);
    }
  }

  /**
   * Delete the given fossil index row.
   * <p>
   * This method is logically the same as {@link #delete(byte[])}, but its
   * separated out to permit asynchronous delivery of the delete events since
   * these are arriving during an index scan and are less time-critical than
   * other delete operations.
   * <p>
   * The default implementation of this method calls {@link #delete(byte[])}.
   *
   * @param key index key to remove.
   * @param row the index row data.
   */
  protected void fossilCollectIndexRow(byte[] key, IndexRow row) {
    try {
      delete(key);
    } catch (OrmException e) {
      // Ignore a fossil delete error.
    }
  }

  @SuppressWarnings("serial")
  private static class KeyExists extends RuntimeException {
  }

  @SuppressWarnings("serial")
  private static class NoMoreValues extends RuntimeException {
  }
}
