// 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.Access;
import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.Schema;
import com.google.gwtorm.jdbc.Database;
import com.google.gwtorm.jdbc.JdbcSchema;
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 {
    <A extends Access<?, ?>> Class<A> create(GeneratedClassLoader loader,
        RelationModel rm) throws OrmException;
  }

  private final GeneratedClassLoader classLoader;
  private final JavaSchemaModel schema;
  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<S> superType,
      final AccessGenerator ag) {
    classLoader = loader;
    schema = schemaModel;
    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<? extends Access> 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 String consDesc =
        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {Type
            .getType(Database.class)});
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC, consName, consDesc, null, null);
    mv.visitCode();

    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ALOAD, 1);
    mv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(schemaSuperClass),
        consName, consDesc);

    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[] {Type
              .getType(JdbcSchema.class)}));
      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();
    }
  }
}
