// 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.heap;

import com.google.gwtorm.nosql.generic.GenericDatabase;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.Schema;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.UnknownFieldSet;

import java.io.PrintWriter;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Toy in-memory implementation of a NoSQL database.
 * <p>
 * Implements a simple NoSQL database with a standard {@link java.util.TreeMap}
 * held inside of this JVM process. All operations occur on the TreeMap, with no
 * durability across database restarts. Therefore this implementation is only
 * suitable for simple tests.
 *
 * @param <T> type of the application schema.
 */
@SuppressWarnings("rawtypes")
abstract class TreeMapDatabase<T extends Schema, S extends TreeMapSchema, A extends TreeMapAccess>
    extends GenericDatabase<T, S, A> {

  /** Lock that protects reads and writes of {@link #table}. */
  final Lock lock;

  /** The NoSQL database storage. */
  final SortedMap<byte[], byte[]> table;

  /**
   * Initialize a new database and generate the implementation.
   *
   * @param schemaBaseType class that the generated Schema implementation should
   *        extend in order to provide data store connectivity.
   * @param accessBaseType class that the generated Access implementations
   *        should extend in order to provide single-relation access for each
   *        schema instance.
   * @param appSchema the application schema interface that must be implemented
   *        and constructed on demand.
   * @throws OrmException the schema cannot be created because of an annotation
   *         error in the interface definitions.
   */
  protected TreeMapDatabase(final Class<S> schemaBaseType,
      final Class<A> accessBaseType, final Class<T> appSchema)
      throws OrmException {
    super(schemaBaseType, accessBaseType, appSchema);

    lock = new ReentrantLock(true);
    table = new TreeMap<>(HeapKeyComparator.INSTANCE);
  }

  /**
   * Try to print the database contents in human readable format.
   *
   * @param pw writer to print the database out to.
   */
  public void dump(PrintWriter pw) {
    lock.lock();
    try {
      for (Map.Entry<byte[], byte[]> ent : table.entrySet()) {
        String key = format(ent.getKey());

        String val;
        try {
          UnknownFieldSet proto = UnknownFieldSet.parseFrom(ent.getValue());
          val = proto.toString();
        } catch (InvalidProtocolBufferException notProto) {
          val = format(ent.getValue());
        }

        if (val.contains("\n")) {
          pw.println(key + ":\n" + "  " + val.replaceAll("\n", "\n  "));
        } else {
          pw.println(key + ": " + val);
        }
      }
    } finally {
      lock.unlock();
    }
  }

  private static String format(byte[] bin) {
    StringBuilder s = new StringBuilder(bin.length);
    for (int i = 0; i < bin.length; i++) {
      byte b = bin[i];
      switch (b) {
        case 0x00:
          s.append("\\0");
          break;

        case 0x01:
          s.append("\\1");
          break;

        case -1:
          s.append("\\xff");
          break;

        case '\r':
          s.append("\\r");
          break;

        default:
          s.append((char) b);
          break;
      }
    }
    return s.toString();
  }
}
