// 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.Access;
import com.google.gwtorm.client.Key;
import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.impl.ListResultSet;
import com.google.gwtorm.jdbc.JdbcAccess;
import com.google.gwtorm.jdbc.JdbcSchema;
import com.google.gwtorm.schema.ColumnModel;
import com.google.gwtorm.schema.KeyModel;
import com.google.gwtorm.schema.QueryModel;
import com.google.gwtorm.schema.RelationModel;
import com.google.gwtorm.schema.Util;
import com.google.gwtorm.schema.sql.SqlDialect;

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

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/** Generates a concrete implementation of an {@link Access} extension. */
public class AccessGen implements Opcodes {
  private static final String REL_ALIAS = "T";

  private static enum DmlType {
    INSERT("bindOneInsert"),

    UPDATE("bindOneUpdate"),

    DELETE("bindOneDelete");

    final String methodName;

    DmlType(final String m) {
      methodName = m;
    }
  }

  private final GeneratedClassLoader classLoader;
  private final SchemaGen.RelationGen info;
  private final RelationModel model;
  private final SqlDialect dialect;

  private ClassWriter cw;
  private String superTypeName;
  private String implClassName;
  private String implTypeName;
  private Type entityType;


  public AccessGen(final GeneratedClassLoader loader,
      final SchemaGen.RelationGen ri) {
    classLoader = loader;
    info = ri;
    model = info.model;
    dialect = ri.getDialect();
    entityType =
        Type.getObjectType(model.getEntityTypeClassName().replace('.', '/'));
  }

  public void defineClass() throws OrmException {
    init();
    implementConstructor();
    implementGetString("getRelationName", model.getRelationName());
    implementGetString("getInsertOneSql", model.getInsertOneSql(dialect));

    if (model.getPrimaryKey() != null) {
      if (model.getDependentColumns().isEmpty()) {
        implementMissingGetString("getUpdateOneSql", "update");
      } else {
        implementGetString("getUpdateOneSql", model.getUpdateOneSql(dialect));
      }
      implementGetString("getDeleteOneSql", model.getDeleteOneSql(dialect));
    } else {
      implementMissingGetString("getUpdateOneSql", "update");
      implementMissingGetString("getDeleteOneSql", "delete");
    }

    implementPrimaryKey();
    implementGetOne();
    implementNewEntityInstance();
    implementBindOne(DmlType.INSERT);
    implementBindOne(DmlType.UPDATE);
    implementBindOne(DmlType.DELETE);
    implementBindOneFetch();

    if (model.getPrimaryKey() != null) {
      implementKeyQuery(model.getPrimaryKey());
    }
    for (final KeyModel key : model.getSecondaryKeys()) {
      implementKeyQuery(key);
    }

    for (final QueryModel q : model.getQueries()) {
      implementQuery(q);
    }

    cw.visitEnd();
    classLoader.defineClass(implClassName, cw.toByteArray());
    info.accessClassName = implClassName;
  }


  private void init() {
    superTypeName = Type.getInternalName(JdbcAccess.class);
    implClassName =
        model.getEntityTypeClassName() + "_Access_" + model.getMethodName()
            + "_" + 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[] {model.getAccessInterfaceName().replace(
            '.', '/')});
  }

  private void implementConstructor() {
    final String consName = "<init>";
    final String consDesc =
        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {Type
            .getType(JdbcSchema.class)});
    final MethodVisitor mv;
    mv = cw.visitMethod(ACC_PUBLIC, consName, consDesc, null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ALOAD, 1);
    mv.visitMethodInsn(INVOKESPECIAL, superTypeName, consName, consDesc);
    mv.visitInsn(RETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
  }

  private void implementGetString(final String methodName,
      final String returnValue) {
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC | ACC_FINAL, methodName, Type
            .getMethodDescriptor(Type.getType(String.class), new Type[] {}),
            null, null);
    mv.visitCode();
    mv.visitLdcInsn(returnValue);
    mv.visitInsn(ARETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
  }

  private void implementMissingGetString(final String methodName,
      final String why) {
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC | ACC_FINAL, methodName, Type
            .getMethodDescriptor(Type.getType(String.class), new Type[] {}),
            null, null);
    mv.visitCode();
    throwUnsupported(mv, model.getMethodName() + " does not support " + why);
    mv.visitInsn(RETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
  }

  private void throwUnsupported(final MethodVisitor mv, final String message) {
    final Type eType = Type.getType(UnsupportedOperationException.class);
    mv.visitTypeInsn(NEW, eType.getInternalName());
    mv.visitInsn(DUP);
    mv.visitLdcInsn(message);
    mv.visitMethodInsn(INVOKESPECIAL, eType.getInternalName(), "<init>", Type
        .getMethodDescriptor(Type.VOID_TYPE, new Type[] {Type
            .getType(String.class)}));
    mv.visitInsn(ATHROW);
  }

  private void implementPrimaryKey() {
    final KeyModel pk = model.getPrimaryKey();
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC | ACC_FINAL, "primaryKey", Type
            .getMethodDescriptor(Type.getType(Key.class), new Type[] {Type
                .getType(Object.class)}), null, null);
    mv.visitCode();
    if (pk != null && pk.getField().isNested()) {
      final ColumnModel pkf = pk.getField();
      mv.visitVarInsn(ALOAD, 1);
      mv.visitTypeInsn(CHECKCAST, entityType.getInternalName());
      mv.visitFieldInsn(GETFIELD, entityType.getInternalName(), pkf
          .getFieldName(), CodeGenSupport.toType(pkf).getDescriptor());
    } else {
      mv.visitInsn(ACONST_NULL);
    }
    mv.visitInsn(ARETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
  }

  private void implementGetOne() {
    final KeyModel pk = model.getPrimaryKey();

    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC | ACC_FINAL, "get", Type.getMethodDescriptor(
            Type.getType(Object.class), new Type[] {Type.getType(Key.class)}),
            null, new String[] {Type.getType(OrmException.class)
                .getInternalName()});
    mv.visitCode();
    if (pk != null && pk.getField().isNested()) {
      final Type keyType = CodeGenSupport.toType(pk.getField());
      mv.visitVarInsn(ALOAD, 0);
      mv.visitVarInsn(ALOAD, 1);
      mv.visitTypeInsn(CHECKCAST, keyType.getInternalName());
      mv.visitMethodInsn(INVOKEVIRTUAL, implTypeName, pk.getName(), Type
          .getMethodDescriptor(entityType, new Type[] {keyType}));
      mv.visitInsn(ARETURN);
    } else {
      throwUnsupported(mv, model.getMethodName() + " does not support get(Key)");
    }
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
  }

  private void implementNewEntityInstance() {
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC | ACC_FINAL, "newEntityInstance", Type
            .getMethodDescriptor(Type.getType(Object.class), new Type[] {}),
            null, null);
    mv.visitCode();
    mv.visitTypeInsn(NEW, entityType.getInternalName());
    mv.visitInsn(DUP);
    mv.visitMethodInsn(INVOKESPECIAL, entityType.getInternalName(), "<init>",
        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {}));
    mv.visitInsn(ARETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
  }

  private void implementBindOne(final DmlType type) {
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC | ACC_FINAL, type.methodName, Type
            .getMethodDescriptor(Type.VOID_TYPE, new Type[] {
                Type.getType(PreparedStatement.class),
                Type.getType(Object.class)}), null, new String[] {Type.getType(
            SQLException.class).getInternalName()});
    mv.visitCode();

    if (type != DmlType.INSERT && model.getPrimaryKey() == null) {
      throwUnsupported(mv, model.getMethodName() + " has no primary key");
      mv.visitInsn(RETURN);
      mv.visitMaxs(-1, -1);
      mv.visitEnd();
    }

    mv.visitVarInsn(ALOAD, 2);
    mv.visitTypeInsn(CHECKCAST, entityType.getInternalName());
    mv.visitVarInsn(ASTORE, 2);

    final CodeGenSupport cgs = new CodeGenSupport(mv);
    cgs.setEntityType(entityType);

    for (final ColumnModel col : model.getRowVersionColumns()) {
      cgs.setFieldReference(col);
      cgs.fieldSetBegin();
      cgs.pushFieldValue();
      mv.visitInsn(ICONST_1);
      mv.visitInsn(IADD);
      cgs.fieldSetEnd();
    }
    cgs.resetColumnIndex(0);

    if (type != DmlType.DELETE) {
      final List<ColumnModel> cols = new ArrayList<ColumnModel>();
      cols.addAll(model.getDependentFields());
      cols.addAll(model.getRowVersionFields());
      for (final ColumnModel field : cols) {
        if (field.isNested() && field.isNotNull()) {
          for (final ColumnModel c : field.getAllLeafColumns()) {
            cgs.setFieldReference(c);
            dialect.getSqlTypeInfo(c).generatePreparedStatementSet(cgs);
          }
        } else if (field.isNested()) {
          final int colIdx = cgs.getColumnIndex();
          final Label isnull = new Label();
          final Label end = new Label();

          cgs.setFieldReference(field);
          cgs.pushFieldValue();
          mv.visitJumpInsn(IFNULL, isnull);
          cgs.resetColumnIndex(colIdx);
          for (final ColumnModel c : field.getAllLeafColumns()) {
            cgs.setFieldReference(c);
            dialect.getSqlTypeInfo(c).generatePreparedStatementSet(cgs);
          }
          mv.visitJumpInsn(GOTO, end);

          mv.visitLabel(isnull);
          cgs.resetColumnIndex(colIdx);
          for (final ColumnModel c : field.getAllLeafColumns()) {
            cgs.setFieldReference(c);
            dialect.getSqlTypeInfo(c).generatePreparedStatementNull(cgs);
          }

          mv.visitLabel(end);
        } else {
          cgs.setFieldReference(field);
          dialect.getSqlTypeInfo(field).generatePreparedStatementSet(cgs);
        }
      }
    }

    for (final ColumnModel col : model.getPrimaryKeyColumns()) {
      cgs.setFieldReference(col);
      dialect.getSqlTypeInfo(col).generatePreparedStatementSet(cgs);
    }
    if (type != DmlType.INSERT) {
      for (final ColumnModel col : model.getRowVersionColumns()) {
        cgs.setFieldReference(col);
        cgs.pushSqlHandle();
        cgs.pushColumnIndex();
        cgs.pushFieldValue();
        mv.visitInsn(ICONST_1);
        mv.visitInsn(ISUB);
        cgs.invokePreparedStatementSet("Int");
      }
    }

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

  private void implementBindOneFetch() {
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC | ACC_FINAL, "bindOneFetch", Type
            .getMethodDescriptor(Type.VOID_TYPE, new Type[] {
                Type.getType(ResultSet.class), Type.getType(Object.class)}),
            null, new String[] {Type.getType(SQLException.class)
                .getInternalName()});
    mv.visitCode();

    mv.visitVarInsn(ALOAD, 2);
    mv.visitTypeInsn(CHECKCAST, entityType.getInternalName());
    mv.visitVarInsn(ASTORE, 2);

    final CodeGenSupport cgs = new CodeGenSupport(mv);
    cgs.setEntityType(entityType);

    if (model.getPrimaryKey() != null
        && model.getPrimaryKey().getField().isNested()) {
      final ColumnModel pkf = model.getPrimaryKey().getField();
      final Type vType = CodeGenSupport.toType(pkf);
      final int oldIdx = cgs.getColumnIndex();
      cgs.setFieldReference(pkf);
      cgs.fieldSetBegin();
      mv.visitTypeInsn(NEW, vType.getInternalName());
      mv.visitInsn(DUP);
      mv.visitMethodInsn(INVOKESPECIAL, vType.getInternalName(), "<init>", Type
          .getMethodDescriptor(Type.VOID_TYPE, new Type[] {}));
      cgs.fieldSetEnd();
      cgs.resetColumnIndex(oldIdx);
    }

    final List<ColumnModel> cols = new ArrayList<ColumnModel>();
    cols.addAll(model.getDependentFields());
    cols.addAll(model.getRowVersionFields());
    cols.addAll(model.getPrimaryKeyColumns());
    for (final ColumnModel field : cols) {
      if (field.isNested()) {
        int oldIdx = cgs.getColumnIndex();
        final Type vType = CodeGenSupport.toType(field);

        cgs.setFieldReference(field);
        cgs.fieldSetBegin();
        mv.visitTypeInsn(NEW, vType.getInternalName());
        mv.visitInsn(DUP);
        mv.visitMethodInsn(INVOKESPECIAL, vType.getInternalName(), "<init>",
            Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {}));
        cgs.fieldSetEnd();

        cgs.resetColumnIndex(oldIdx);
        for (final ColumnModel c : field.getAllLeafColumns()) {
          cgs.setFieldReference(c);
          dialect.getSqlTypeInfo(c).generateResultSetGet(cgs);
        }

        if (!field.isNotNull()) {
          final Label islive = new Label();
          cgs.pushSqlHandle();
          mv.visitMethodInsn(INVOKEINTERFACE, Type.getType(ResultSet.class)
              .getInternalName(), "wasNull", Type.getMethodDescriptor(
              Type.BOOLEAN_TYPE, new Type[] {}));
          mv.visitJumpInsn(IFEQ, islive);
          oldIdx = cgs.getColumnIndex();
          cgs.setFieldReference(field);
          cgs.fieldSetBegin();
          mv.visitInsn(ACONST_NULL);
          cgs.fieldSetEnd();
          cgs.resetColumnIndex(oldIdx);
          mv.visitLabel(islive);
        }
      } else {
        cgs.setFieldReference(field);
        dialect.getSqlTypeInfo(field).generateResultSetGet(cgs);
      }
    }

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

  private void implementKeyQuery(final KeyModel info) {
    final Type keyType = CodeGenSupport.toType(info.getField());
    final StringBuilder query = new StringBuilder();
    query.append(model.getSelectSql(dialect, REL_ALIAS));
    query.append(" WHERE ");
    int nth = 1;
    for (final Iterator<ColumnModel> i = info.getAllLeafColumns().iterator(); i
        .hasNext();) {
      final ColumnModel c = i.next();
      query.append(REL_ALIAS);
      query.append('.');
      query.append(c.getColumnName());
      query.append('=');
      query.append(dialect.getParameterPlaceHolder(nth++));
      if (i.hasNext()) {
        query.append(" AND ");
      }
    }

    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC | ACC_FINAL, info.getName(), Type
            .getMethodDescriptor(entityType, new Type[] {keyType}), null,
            new String[] {Type.getType(OrmException.class).getInternalName()});
    mv.visitCode();

    final int keyvar = 1, psvar = keyvar + keyType.getSize();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitLdcInsn(query.toString());
    mv.visitMethodInsn(INVOKEVIRTUAL, superTypeName, "prepareStatement", Type
        .getMethodDescriptor(Type.getType(PreparedStatement.class),
            new Type[] {Type.getType(String.class)}));
    mv.visitVarInsn(ASTORE, psvar);

    final CodeGenSupport cgs = new CodeGenSupport(mv) {
      @Override
      public void pushSqlHandle() {
        mv.visitVarInsn(ALOAD, psvar);
      }

      @Override
      public void pushFieldValue() {
        appendGetField(getFieldReference());
      }

      @Override
      protected void appendGetField(final ColumnModel c) {
        if (c.getParent() == null) {
          loadVar(keyType, keyvar);
        } else {
          super.appendGetField(c);
        }
      }
    };
    for (final ColumnModel c : info.getAllLeafColumns()) {
      cgs.setFieldReference(c);
      dialect.getSqlTypeInfo(c).generatePreparedStatementSet(cgs);
    }

    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ALOAD, psvar);
    mv.visitMethodInsn(INVOKEVIRTUAL, superTypeName, "queryOne", Type
        .getMethodDescriptor(Type.getType(Object.class), new Type[] {Type
            .getType(PreparedStatement.class)}));
    mv.visitTypeInsn(CHECKCAST, entityType.getInternalName());
    mv.visitInsn(ARETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
  }

  private void implementQuery(final QueryModel info) {
    final List<ColumnModel> pCols = info.getParameters();
    final boolean hasLimitParam = info.hasLimitParameter();
    final Type[] pTypes = new Type[pCols.size() + (hasLimitParam ? 1 : 0)];
    final int[] pVars = new int[pTypes.length];
    int nextVar = 1;
    for (int i = 0; i < pCols.size(); i++) {
      pTypes[i] = CodeGenSupport.toType(pCols.get(i));
      pVars[i] = nextVar;
      nextVar += pTypes[i].getSize();
    }
    if (hasLimitParam) {
      pTypes[pTypes.length - 1] = Type.INT_TYPE;
      pVars[pTypes.length - 1] = nextVar;
      nextVar += Type.INT_TYPE.getSize();
    }

    final int psvar = nextVar++;
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC | ACC_FINAL, info.getName(), Type
            .getMethodDescriptor(Type
                .getType(com.google.gwtorm.client.ResultSet.class), pTypes),
            null, new String[] {Type.getType(OrmException.class)
                .getInternalName()});
    mv.visitCode();

    mv.visitVarInsn(ALOAD, 0);
    mv.visitLdcInsn(info.getSelectSql(dialect, REL_ALIAS));
    mv.visitMethodInsn(INVOKEVIRTUAL, superTypeName, "prepareStatement", Type
        .getMethodDescriptor(Type.getType(PreparedStatement.class),
            new Type[] {Type.getType(String.class)}));
    mv.visitVarInsn(ASTORE, psvar);

    final int argIdx[] = new int[] {0};
    final CodeGenSupport cgs = new CodeGenSupport(mv) {
      @Override
      public void pushSqlHandle() {
        mv.visitVarInsn(ALOAD, psvar);
      }

      @Override
      public void pushFieldValue() {
        appendGetField(getFieldReference());
      }

      @Override
      protected void appendGetField(final ColumnModel c) {
        final int n = argIdx[0];
        if (c == pCols.get(n)) {
          loadVar(pTypes[n], pVars[n]);
        } else {
          super.appendGetField(c);
        }
      }
    };
    for (final ColumnModel c : pCols) {
      if (c.isNested()) {
        for (final ColumnModel n : c.getAllLeafColumns()) {
          cgs.setFieldReference(n);
          dialect.getSqlTypeInfo(n).generatePreparedStatementSet(cgs);
        }
      } else {
        cgs.setFieldReference(c);
        dialect.getSqlTypeInfo(c).generatePreparedStatementSet(cgs);
      }
      argIdx[0]++;
    }

    if (info.hasLimit()) {
      if (hasLimitParam || !dialect.selectHasLimit()) {
        mv.visitVarInsn(ALOAD, psvar);
        if (hasLimitParam) {
          mv.visitVarInsn(ILOAD, pVars[pTypes.length - 1]);
        } else {
          cgs.push(info.getStaticLimit());
        }
        mv.visitMethodInsn(INVOKEINTERFACE, Type.getType(
            PreparedStatement.class).getInternalName(), "setMaxRows", Type
            .getMethodDescriptor(Type.VOID_TYPE, new Type[] {Type.INT_TYPE}));
      }
    }

    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ALOAD, psvar);
    mv.visitMethodInsn(INVOKEVIRTUAL, superTypeName, "queryList", Type
        .getMethodDescriptor(Type.getType(ListResultSet.class),
            new Type[] {Type.getType(PreparedStatement.class)}));
    mv.visitInsn(ARETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
  }
}
