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

import com.google.gwtorm.client.KeyUtil;
import com.google.gwtorm.schema.RelationModel;
import com.google.gwtorm.schema.SchemaModel;
import com.google.gwtorm.schema.java.JavaSchemaModel;
import com.google.gwtorm.server.GeneratedClassLoader;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.Schema;
import com.google.gwtorm.server.SchemaConstructorGen;
import com.google.gwtorm.server.SchemaFactory;
import com.google.gwtorm.server.SchemaGen;
import com.google.gwtorm.server.StandardKeyEncoder;

/**
 * Base class for NoSQL typed databases.
 *
 * <p>Applications should use the database class to create instances of their Schema extension
 * interface, and thus open and connect to the data store.
 *
 * <p>Creating a new database instance is expensive, due to the type analysis and code generation
 * performed to implement the Schema and Access interfaces. Applications should create and cache
 * their database instance for the life of the application.
 *
 * <p>Database instances are thread-safe, but returned Schema instances are not.
 *
 * <p>This class must be further extended by the NoSQL implementation to configure the connectivity
 * with the data store and supply the correct subclass of {@link NoSqlSchema} that knows how to
 * interact with the data store.
 *
 * @param <T> type of the application's Schema.
 * @param <S> type of the implementation's base for Schema implementations.
 * @param <A> type of the implementation's base for Access implementations.
 */
@SuppressWarnings("rawtypes")
public abstract class NoSqlDatabase<T extends Schema, S extends NoSqlSchema, A extends NoSqlAccess>
    implements SchemaFactory<T> {
  static {
    KeyUtil.setEncoderImpl(new StandardKeyEncoder());
  }

  private final SchemaModel schemaModel;
  private final SchemaFactory<T> implFactory;

  /**
   * 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 NoSqlDatabase(
      final Class<S> schemaBaseType, final Class<A> accessBaseType, final Class<T> appSchema)
      throws OrmException {
    schemaModel = new JavaSchemaModel(appSchema);
    final GeneratedClassLoader loader = newLoader(appSchema);
    final Class<T> impl = generate(schemaBaseType, accessBaseType, loader);
    implFactory = new SchemaConstructorGen<>(loader, impl, this).create();
  }

  @Override
  public T open() throws OrmException {
    return implFactory.open();
  }

  /** @return the derived model of the application's schema. */
  public SchemaModel getSchemaModel() {
    return schemaModel;
  }

  @SuppressWarnings("unchecked")
  private Class<T> generate(
      final Class<S> schemaBaseType,
      final Class<A> accessBaseType,
      final GeneratedClassLoader loader)
      throws OrmException {
    return new SchemaGen(
            loader,
            schemaModel,
            getClass(),
            schemaBaseType,
            new SchemaGen.AccessGenerator() {
              @Override
              public Class<?> create(GeneratedClassLoader loader, RelationModel rm)
                  throws OrmException {
                return new AccessGen(loader, rm, schemaBaseType, accessBaseType).create();
              }
            })
        .create();
  }

  private static <T> GeneratedClassLoader newLoader(final Class<T> schema) {
    return new GeneratedClassLoader(schema.getClassLoader());
  }
}
