// Copyright 2008 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.server;

import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.Schema;
import com.google.gwtorm.schema.RelationModel;
import com.google.gwtorm.schema.SequenceModel;
import com.google.gwtorm.schema.Util;
import com.google.gwtorm.schema.java.JavaSchemaModel;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

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

/** Generates a concrete implementation of a {@link Schema} extension. */
public class SchemaGen<S extends AbstractSchema> implements Opcodes {
  public interface AccessGenerator {
    Class<?> create(GeneratedClassLoader loader, RelationModel rm)
        throws OrmException;
  }

  private final GeneratedClassLoader classLoader;
  private final JavaSchemaModel schema;
  private final Class<?> databaseClass;
  private final Class<S> schemaSuperClass;
  private final AccessGenerator accessGen;
  private List<RelationGen> relations;
  private ClassWriter cw;
  private String implClassName;
  private String implTypeName;

  public SchemaGen(final GeneratedClassLoader loader,
      final JavaSchemaModel schemaModel, final Class<?> databaseType,
      final Class<S> superType, final AccessGenerator ag) {
    classLoader = loader;
    schema = schemaModel;
    databaseClass = databaseType;
    schemaSuperClass = superType;
    accessGen = ag;
  }

  public Class<Schema> create() throws OrmException {
    defineRelationClasses();

    init();
    implementRelationFields();
    implementConstructor();
    implementSequenceMethods();
    implementRelationMethods();
    cw.visitEnd();
    classLoader.defineClass(getImplClassName(), cw.toByteArray());
    return loadClass();
  }

  @SuppressWarnings("unchecked")
  private Class<Schema> loadClass() throws OrmException {
    try {
      final Class<?> c = Class.forName(getImplClassName(), false, classLoader);
      return (Class<Schema>) c;
    } catch (ClassNotFoundException err) {
      throw new OrmException("Cannot load generated class", err);
    }
  }

  String getSchemaClassName() {
    return schema.getSchemaClassName();
  }

  String getImplClassName() {
    return implClassName;
  }

  String getImplTypeName() {
    return implTypeName;
  }

  private void defineRelationClasses() throws OrmException {
    relations = new ArrayList<RelationGen>();
    for (final RelationModel rel : schema.getRelations()) {
      final Class<?> a = accessGen.create(classLoader, rel);
      relations.add(new RelationGen(rel, a));
    }
  }

  private void init() {
    implClassName = getSchemaClassName() + "_Schema_" + Util.createRandomName();
    implTypeName = implClassName.replace('.', '/');

    cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    cw.visit(V1_3, ACC_PUBLIC | ACC_FINAL | ACC_SUPER, implTypeName, null, Type
        .getInternalName(schemaSuperClass), new String[] {getSchemaClassName()
        .replace('.', '/')});
  }

  private void implementRelationFields() {
    for (final RelationGen info : relations) {
      info.implementField();
    }
  }

  private void implementConstructor() {
    final String consName = "<init>";
    final Type superType = Type.getType(schemaSuperClass);
    final Type dbType = Type.getType(databaseClass);

    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC, consName, Type.getMethodDescriptor(
            Type.VOID_TYPE, new Type[] {dbType}), null, null);
    mv.visitCode();

    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ALOAD, 1);
    mv.visitMethodInsn(INVOKESPECIAL, superType.getInternalName(), consName,
        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {Type
            .getType(schemaSuperClass.getDeclaredConstructors()[0]
                .getParameterTypes()[0])}));

    for (final RelationGen info : relations) {
      mv.visitVarInsn(ALOAD, 0);
      mv.visitTypeInsn(NEW, info.accessType.getInternalName());
      mv.visitInsn(DUP);
      mv.visitVarInsn(ALOAD, 0);
      mv.visitMethodInsn(INVOKESPECIAL, info.accessType.getInternalName(),
          consName, Type.getMethodDescriptor(Type.VOID_TYPE,
              new Type[] {superType}));
      mv.visitFieldInsn(PUTFIELD, implTypeName, info
          .getAccessInstanceFieldName(), info.accessType.getDescriptor());
    }

    mv.visitInsn(RETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
  }

  private void implementSequenceMethods() {
    for (final SequenceModel seq : schema.getSequences()) {
      final Type retType = Type.getType(seq.getResultType());
      final MethodVisitor mv =
          cw
              .visitMethod(ACC_PUBLIC, seq.getMethodName(), Type
                  .getMethodDescriptor(retType, new Type[] {}), null,
                  new String[] {Type.getType(OrmException.class)
                      .getInternalName()});
      mv.visitCode();

      mv.visitVarInsn(ALOAD, 0);
      mv.visitLdcInsn(seq.getSequenceName());
      mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(schemaSuperClass),
          "nextLong", Type.getMethodDescriptor(Type.getType(Long.TYPE),
              new Type[] {Type.getType(String.class)}));
      if (retType.getSize() == 1) {
        mv.visitInsn(L2I);
        mv.visitInsn(IRETURN);
      } else {
        mv.visitInsn(LRETURN);
      }
      mv.visitMaxs(-1, -1);
      mv.visitEnd();
    }
  }

  private void implementRelationMethods() {
    for (final RelationGen info : relations) {
      info.implementMethod();
    }
  }

  private class RelationGen {
    final RelationModel model;
    final Type accessType;

    RelationGen(final RelationModel model, final Class<?> accessClass) {
      this.model = model;
      this.accessType = Type.getType(accessClass);
    }

    void implementField() {
      cw.visitField(ACC_PRIVATE | ACC_FINAL, getAccessInstanceFieldName(),
          accessType.getDescriptor(), null, null).visitEnd();
    }

    String getAccessInstanceFieldName() {
      return "access_" + model.getMethodName();
    }

    void implementMethod() {
      final MethodVisitor mv =
          cw.visitMethod(ACC_PUBLIC | ACC_FINAL, model.getMethodName(), Type
              .getMethodDescriptor(Type.getObjectType(model
                  .getAccessInterfaceName().replace('.', '/')), new Type[] {}),
              null, null);
      mv.visitCode();
      mv.visitVarInsn(ALOAD, 0);
      mv.visitFieldInsn(GETFIELD, implTypeName, getAccessInstanceFieldName(),
          accessType.getDescriptor());
      mv.visitInsn(ARETURN);
      mv.visitMaxs(-1, -1);
      mv.visitEnd();
    }
  }
}
