// 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.jdbc.gen;

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 com.google.gwtorm.schema.sql.SqlDialect;
import com.google.gwtorm.server.GeneratedClassLoader;

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

import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;

/** Generates a concrete implementation of a {@link Schema} extension. */
public class SchemaGen implements Opcodes {
  private final GeneratedClassLoader classLoader;
  private final JavaSchemaModel schema;
  private final SqlDialect dialect;
  private List<RelationGen> relations;
  private ClassWriter cw;
  private String superTypeName;
  private String implClassName;
  private String implTypeName;

  public SchemaGen(final GeneratedClassLoader loader,
      final JavaSchemaModel schemaModel, final SqlDialect sqlDialect) {
    classLoader = loader;
    schema = schemaModel;
    dialect = sqlDialect;
  }

  public void defineClass() throws OrmException {
    defineRelationClasses();

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

  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 RelationGen g = new RelationGen(rel);
      relations.add(g);
      new AccessGen(classLoader, g).defineClass();
    }
  }

  private void init() {
    superTypeName = Type.getInternalName(JdbcSchema.class);
    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,
        superTypeName, 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), Type.getType(Connection.class)});
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC, consName, consDesc, null, null);
    mv.visitCode();

    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ALOAD, 1);
    mv.visitVarInsn(ALOAD, 2);
    mv.visitMethodInsn(INVOKESPECIAL, superTypeName, 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(dialect.getNextSequenceValueSql(seq.getSequenceName()));
      mv.visitMethodInsn(INVOKEVIRTUAL, superTypeName, "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();
    }
  }

  class RelationGen {
    final RelationModel model;
    String accessClassName;
    Type accessType;

    RelationGen(final RelationModel model) {
      this.model = model;
    }

    SqlDialect getDialect() {
      return SchemaGen.this.dialect;
    }

    void implementField() {
      accessType = Type.getObjectType(accessClassName.replace('.', '/'));
      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();
    }
  }
}
