// 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.schema.Util;

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

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/** Generates a factory to efficiently create new Schema instances. */
public class SchemaConstructorGen<T extends Schema> implements Opcodes {
  private static final String CTX = "schemaArg";

  private final GeneratedClassLoader classLoader;
  private final Class<T> schemaImpl;
  private final Object schemaArg;
  private ClassWriter cw;
  private String implClassName;
  private String implTypeName;

  public SchemaConstructorGen(final GeneratedClassLoader loader,
      final Class<T> c, final Object f) {
    classLoader = loader;
    schemaImpl = c;
    schemaArg = f;
  }

  public void defineClass() throws OrmException {
    init();
    declareFactoryField();
    implementConstructor();
    implementNewInstance();
    cw.visitEnd();
    classLoader.defineClass(implClassName, cw.toByteArray());
  }


  public SchemaFactory<T> create() throws OrmException {
    defineClass();
    try {
      final Class<?> c = Class.forName(implClassName, true, classLoader);
      final Constructor<?> n = c.getDeclaredConstructors()[0];
      return cast(n.newInstance(new Object[] {schemaArg}));
    } catch (InstantiationException e) {
      throw new OrmException("Cannot create schema factory", e);
    } catch (IllegalAccessException e) {
      throw new OrmException("Cannot create schema factory", e);
    } catch (ClassNotFoundException e) {
      throw new OrmException("Cannot create schema factory", e);
    } catch (IllegalArgumentException e) {
      throw new OrmException("Cannot create schema factory", e);
    } catch (InvocationTargetException e) {
      throw new OrmException("Cannot create schema factory", e);
    }
  }

  @SuppressWarnings("unchecked")
  private SchemaFactory<T> cast(final Object newInstance) {
    return (SchemaFactory<T>) newInstance;
  }

  private void init() {
    implClassName =
        schemaImpl.getName() + "_Factory_" + 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(Object.class), new String[] {Type
        .getInternalName(SchemaFactory.class)});
  }

  private void declareFactoryField() {
    cw.visitField(ACC_PRIVATE | ACC_FINAL, CTX,
        Type.getType(schemaArg.getClass()).getDescriptor(), null, null)
        .visitEnd();
  }

  private void implementConstructor() {
    final Type ft = Type.getType(schemaArg.getClass());
    final String consName = "<init>";
    final String consDesc =
        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {ft});
    final MethodVisitor mv;
    mv = cw.visitMethod(ACC_PUBLIC, consName, consDesc, null, null);
    mv.visitCode();

    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(Object.class),
        consName, Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {}));

    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ALOAD, 1);
    mv.visitFieldInsn(PUTFIELD, implTypeName, CTX, ft.getDescriptor());

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

  private void implementNewInstance() {
    final Type ft = Type.getType(schemaArg.getClass());
    final String typeName = Type.getType(schemaImpl).getInternalName();
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC | ACC_FINAL, "open", Type
            .getMethodDescriptor(Type.getType(Schema.class), new Type[] {}),
            null, null);
    mv.visitCode();

    Constructor<?> c = schemaImpl.getDeclaredConstructors()[0];
    Type argType = Type.getType(c.getParameterTypes()[0]);

    mv.visitTypeInsn(NEW, typeName);
    mv.visitInsn(DUP);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, implTypeName, CTX, ft.getDescriptor());
    mv.visitMethodInsn(INVOKESPECIAL, typeName, "<init>", Type
        .getMethodDescriptor(Type.VOID_TYPE, new Type[] {argType}));
    mv.visitInsn(ARETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
  }
}
