// Copyright 2010 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.nosql;

import com.google.gwtorm.client.Key;
import com.google.gwtorm.protobuf.CodecFactory;
import com.google.gwtorm.protobuf.ProtobufCodec;
import com.google.gwtorm.schema.ColumnModel;
import com.google.gwtorm.schema.KeyModel;
import com.google.gwtorm.schema.QueryModel;
import com.google.gwtorm.schema.QueryParser;
import com.google.gwtorm.schema.RelationModel;
import com.google.gwtorm.schema.Util;
import com.google.gwtorm.server.CodeGenSupport;
import com.google.gwtorm.server.GeneratedClassLoader;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;

import org.antlr.runtime.tree.Tree;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/** Generates a concrete implementation of a {@link NoSqlAccess} extension. */
class AccessGen implements Opcodes {
  private static final Type string = Type.getType(String.class);
  private static final Type protobufCodec = Type.getType(ProtobufCodec.class);
  private static final Type indexFunction = Type.getType(IndexFunction.class);
  private static final Type object = Type.getType(Object.class);
  private static final Type ormKey = Type.getType(Key.class);
  private static final Type byteArray = Type.getType(byte[].class);
  private static final Type ormException = Type.getType(OrmException.class);
  private static final Type resultSet = Type.getType(ResultSet.class);
  private static final Type indexKeyBuilder =
      Type.getType(IndexKeyBuilder.class);

  private static final String F_OBJECT_CODEC = "objectCodec";
  private static final String F_INDEXES = "indexes";

  private final GeneratedClassLoader classLoader;
  private final RelationModel model;
  private final Class<?> modelClass;
  private final Type schemaType;
  private final Type accessType;
  private final Type entityType;
  private final KeyModel key;

  private ClassWriter cw;
  private String implClassName;
  private String implTypeName;

  AccessGen(final GeneratedClassLoader loader, final RelationModel rm,
      final Class<? extends NoSqlSchema> schemaClazz,
      @SuppressWarnings("rawtypes")
      final Class<? extends NoSqlAccess> accessClazz) throws OrmException {
    classLoader = loader;
    model = rm;

    try {
      modelClass =
          Class.forName(model.getEntityTypeClassName(), true, classLoader);
    } catch (ClassNotFoundException cnfe) {
      throw new OrmException("Cannot locate model class", cnfe);
    }

    schemaType = Type.getType(schemaClazz);
    accessType = Type.getType(accessClazz);
    entityType = Type.getType(modelClass);

    key = model.getPrimaryKey();
    if (key == null) {
      throw new OrmException("Relation " + rm.getMethodName()
          + " has no primary key");
    }
  }

  Class<?> create() throws OrmException {
    init();
    implementStaticFields();
    implementConstructor();
    implementGetString("getRelationName", model.getRelationName());
    implementGetRelationID();
    implementGetObjectCodec();
    implementGetIndexes();

    implementPrimaryKey();
    implementEncodePrimaryKey();
    implementKeyQuery(key);

    for (final QueryModel q : model.getQueries()) {
      implementQuery(q);
    }
    implementQuery(new QueryModel(model, "iterateAllEntities", ""));

    cw.visitEnd();
    classLoader.defineClass(implClassName, cw.toByteArray());

    final Class<?> c = loadClass();
    initObjectCodec(c);
    initQueryIndexes(c);
    return c;
  }

  @SuppressWarnings({"unchecked", "rawtypes"})
  private void initObjectCodec(final Class<?> clazz) throws OrmException {
    ProtobufCodec oc = CodecFactory.encoder(modelClass);
    if (model.getRelationID() > 0) {
      oc = new RelationCodec(model.getRelationID(), oc);
    }

    try {
      final Field e = clazz.getDeclaredField(F_OBJECT_CODEC);
      e.setAccessible(true);
      e.set(null, oc);
    } catch (IllegalArgumentException err) {
      throw new OrmException("Cannot setup ProtobufCodec", err);
    } catch (IllegalStateException err) {
      throw new OrmException("Cannot setup ProtobufCodec", err);
    } catch (IllegalAccessException err) {
      throw new OrmException("Cannot setup ProtobufCodec", err);
    } catch (SecurityException err) {
      throw new OrmException("Cannot setup ProtobufCodec", err);
    } catch (NoSuchFieldException err) {
      throw new OrmException("Cannot setup ProtobufCodec", err);
    }
  }

  @SuppressWarnings({"unchecked", "rawtypes"})
  private void initQueryIndexes(final Class<?> clazz) throws OrmException {
    final Collection<QueryModel> queries = model.getQueries();
    final ArrayList<IndexFunction> indexes = new ArrayList<>();
    for (QueryModel m : queries) {
      if (needsIndexFunction(m)) {
        indexes.add(new IndexFunctionGen(classLoader, m, modelClass).create());
      }
    }

    try {
      Field e = clazz.getDeclaredField(F_INDEXES);
      e.setAccessible(true);
      e.set(null, indexes.toArray(new IndexFunction[indexes.size()]));

      for (IndexFunction<?> f : indexes) {
        e = clazz.getDeclaredField("index_" + f.getName());
        e.setAccessible(true);
        e.set(null, f);
      }
    } catch (IllegalArgumentException err) {
      throw new OrmException("Cannot setup query IndexFunctions", err);
    } catch (IllegalStateException err) {
      throw new OrmException("Cannot setup query IndexFunctions", err);
    } catch (IllegalAccessException err) {
      throw new OrmException("Cannot setup query IndexFunctions", err);
    } catch (SecurityException err) {
      throw new OrmException("Cannot setup query IndexFunctions", err);
    } catch (NoSuchFieldException err) {
      throw new OrmException("Cannot setup query IndexFunctions", err);
    }
  }

  private Class<?> loadClass() throws OrmException {
    try {
      return Class.forName(implClassName, false, classLoader);
    } catch (ClassNotFoundException err) {
      throw new OrmException("Cannot load generated class", err);
    }
  }

  private void init() {
    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,
        accessType.getInternalName(), new String[] {model
            .getAccessInterfaceName().replace('.', '/')});
  }

  private void implementStaticFields() {
    cw.visitField(ACC_PRIVATE | ACC_STATIC, F_OBJECT_CODEC,
        protobufCodec.getDescriptor(), null, null).visitEnd();
    cw.visitField(ACC_PRIVATE | ACC_STATIC, F_INDEXES,
        Type.getType(IndexFunction[].class).getDescriptor(), null, null)
        .visitEnd();

    for (final QueryModel q : model.getQueries()) {
      if (needsIndexFunction(q)) {
        cw.visitField(ACC_PRIVATE | ACC_STATIC, "index_" + q.getName(),
            indexFunction.getDescriptor(), null, null).visitEnd();
      }
    }
  }

  private void implementConstructor() {
    final String consName = "<init>";
    final String consDesc =
        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {schemaType});
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC, consName, consDesc, null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ALOAD, 1);
    mv.visitMethodInsn(INVOKESPECIAL, accessType.getInternalName(), 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(string, new Type[] {}), null, null);
    mv.visitCode();
    mv.visitLdcInsn(returnValue);
    mv.visitInsn(ARETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
  }

  private void implementGetRelationID() {
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC | ACC_FINAL, "getRelationID", Type
            .getMethodDescriptor(Type.INT_TYPE, new Type[] {}), null, null);
    mv.visitCode();
    new CodeGenSupport(mv).push(model.getRelationID());
    mv.visitInsn(IRETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
  }

  private void implementGetObjectCodec() {
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC | ACC_FINAL, "getObjectCodec", Type
            .getMethodDescriptor(protobufCodec, new Type[] {}), null, null);
    mv.visitCode();
    mv.visitFieldInsn(GETSTATIC, implTypeName, F_OBJECT_CODEC, protobufCodec
        .getDescriptor());
    mv.visitInsn(ARETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
  }

  private void implementGetIndexes() {
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC | ACC_FINAL, "getIndexes", Type
            .getMethodDescriptor(Type.getType(IndexFunction[].class),
                new Type[] {}), null, null);
    mv.visitCode();
    mv.visitFieldInsn(GETSTATIC, implTypeName, F_INDEXES, Type.getType(
        IndexFunction[].class).getDescriptor());
    mv.visitInsn(ARETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
  }

  private void implementPrimaryKey() {
    final ColumnModel f = key.getField();
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC | ACC_FINAL, "primaryKey", Type
            .getMethodDescriptor(ormKey, new Type[] {object}), null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 1);
    mv.visitTypeInsn(CHECKCAST, entityType.getInternalName());
    mv.visitFieldInsn(GETFIELD, entityType.getInternalName(), f.getFieldName(),
        CodeGenSupport.toType(f).getDescriptor());
    mv.visitInsn(ARETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
  }

  private void implementEncodePrimaryKey() throws OrmException {
    final List<ColumnModel> pCols = Collections.singletonList(key.getField());
    final Type argType = CodeGenSupport.toType(key.getField());
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC | ACC_FINAL, "encodePrimaryKey", Type
            .getMethodDescriptor(Type.VOID_TYPE, new Type[] {indexKeyBuilder,
                ormKey}), null, null);
    mv.visitCode();

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

    final QueryCGS cgs =
        new QueryCGS(mv, new Type[] {argType}, pCols, new int[] {2}, 1);
    for (ColumnModel f : pCols) {
      IndexFunctionGen.encodeField(new QueryModel.OrderBy(f, false), mv, cgs);
    }

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

  private void implementKeyQuery(KeyModel key) {
    final Type keyType = CodeGenSupport.toType(key.getField());
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC | ACC_FINAL, key.getName(), Type
            .getMethodDescriptor(entityType, new Type[] {keyType}), null,
            new String[] {Type.getType(OrmException.class).getInternalName()});
    mv.visitCode();

    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ALOAD, 1);
    mv.visitMethodInsn(INVOKESPECIAL, accessType.getInternalName(), "get", Type
        .getMethodDescriptor(object, new Type[] {ormKey}));
    mv.visitTypeInsn(CHECKCAST, entityType.getInternalName());

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

  private void implementQuery(final QueryModel info) throws OrmException {
    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 MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC | ACC_FINAL, info.getName(), Type
            .getMethodDescriptor(resultSet, pTypes), null,
            new String[] {ormException.getInternalName()});
    mv.visitCode();

    final List<Tree> ops = compareOpsOnly(info.getParseTree());

    // Generate fromKey
    //
    final int fromBuf = nextVar++;
    mv.visitTypeInsn(NEW, indexKeyBuilder.getInternalName());
    mv.visitInsn(DUP);
    mv.visitMethodInsn(INVOKESPECIAL, indexKeyBuilder.getInternalName(),
        "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {}));
    mv.visitVarInsn(ASTORE, fromBuf);

    QueryCGS cgs = new QueryCGS(mv, pTypes, pCols, pVars, fromBuf);
    encodeFields(info, ops, mv, cgs, true /* fromKey */);

    // Generate toKey
    //
    final int toBuf = nextVar++;
    mv.visitTypeInsn(NEW, indexKeyBuilder.getInternalName());
    mv.visitInsn(DUP);
    mv.visitMethodInsn(INVOKESPECIAL, indexKeyBuilder.getInternalName(),
        "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {}));
    mv.visitVarInsn(ASTORE, toBuf);

    cgs = new QueryCGS(mv, pTypes, pCols, pVars, toBuf);
    encodeFields(info, ops, mv, cgs, false /* fromKey */);
    cgs.infinity();

    // Make the scan call
    //
    mv.visitVarInsn(ALOAD, 0);
    if (needsIndexFunction(info)) {
      mv.visitFieldInsn(GETSTATIC, implTypeName, "index_" + info.getName(),
          indexFunction.getDescriptor());
    }

    mv.visitVarInsn(ALOAD, fromBuf);
    mv.visitMethodInsn(INVOKEVIRTUAL, indexKeyBuilder.getInternalName(),
        "toByteArray", Type.getMethodDescriptor(byteArray, new Type[] {}));

    mv.visitVarInsn(ALOAD, toBuf);
    mv.visitMethodInsn(INVOKEVIRTUAL, indexKeyBuilder.getInternalName(),
        "toByteArray", Type.getMethodDescriptor(byteArray, new Type[] {}));

    // Set the limit on the number of results.
    //
    if (info.hasLimit()) {
      if (hasLimitParam) {
        mv.visitVarInsn(ILOAD, pVars[pTypes.length - 1]);
      } else {
        cgs.push(info.getStaticLimit());
      }
    } else {
      cgs.push(0);
    }

    // Only keep order if there is an order by clause present
    //
    cgs.push(info.hasOrderBy() ? 1 : 0);

    if (needsIndexFunction(info)) {
      mv.visitMethodInsn(INVOKEVIRTUAL, accessType.getInternalName(),
          "scanIndex", Type.getMethodDescriptor(resultSet, new Type[] {
              indexFunction, byteArray, byteArray, Type.INT_TYPE,
              Type.BOOLEAN_TYPE}));
    } else {
      // No where and no order by clause? Use the primary key instead.
      //
      mv.visitMethodInsn(INVOKEVIRTUAL, accessType.getInternalName(),
          "scanPrimaryKey", Type.getMethodDescriptor(resultSet, new Type[] {
              byteArray, byteArray, Type.INT_TYPE, Type.BOOLEAN_TYPE}));
    }

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

  private boolean needsIndexFunction(final QueryModel info) {
    return info.hasWhere() || info.hasOrderBy();
  }

  private void encodeFields(QueryModel qm, List<Tree> query, MethodVisitor mv,
      QueryCGS cgs, boolean fromKey) throws OrmException {
    final boolean toKey = !fromKey;
    Tree lastNode = null;

    for (Tree node : query) {
      switch (node.getType()) {
        case QueryParser.GE:
          if (fromKey) {
            checkLastNode(qm, lastNode);
            encodeField(node, mv, cgs);
            cgs.delimiter();
            lastNode = node;
          }
          break;

        case QueryParser.GT:
          if (fromKey) {
            checkLastNode(qm, lastNode);
            encodeField(node, mv, cgs);
            cgs.delimiter();
            cgs.infinity();
            lastNode = node;
          }
          break;

        case QueryParser.EQ:
          checkLastNode(qm, lastNode);
          encodeField(node, mv, cgs);
          cgs.delimiter();
          break;

        case QueryParser.LE:
          if (toKey) {
            checkLastNode(qm, lastNode);
            encodeField(node, mv, cgs);
            cgs.delimiter();
            lastNode = node;
          }
          break;

        case QueryParser.LT:
          if (toKey) {
            checkLastNode(qm, lastNode);
            encodeField(node, mv, cgs);
            cgs.delimiter();
            cgs.nul();
            lastNode = node;
          }
          break;

        default:
          throw new OrmException("Unsupported query token in "
              + model.getMethodName() + "." + qm.getName() + ": "
              + node.toStringTree());
      }

      cgs.nextParameter();
    }
  }

  private void checkLastNode(QueryModel qm, Tree lastNode) throws OrmException {
    if (lastNode != null) {
      throw new OrmException(lastNode.getText() + " must be last operator in "
          + model.getMethodName() + "." + qm.getName());
    }
  }

  private void encodeField(Tree node, MethodVisitor mv, QueryCGS cgs)
      throws OrmException {
    ColumnModel f = ((QueryParser.Column) node.getChild(0)).getField();
    IndexFunctionGen.encodeField(new QueryModel.OrderBy(f, false), mv, cgs);
  }

  private List<Tree> compareOpsOnly(Tree node) throws OrmException {
    if (node == null) {
      return Collections.emptyList();
    }

    switch (node.getType()) {
      case 0: // nil node used to join other nodes together
      case QueryParser.WHERE:
      case QueryParser.AND: {
        List<Tree> res = new ArrayList<>();
        for (int i = 0; i < node.getChildCount(); i++) {
          res.addAll(compareOpsOnly(node.getChild(i)));
        }
        return res;
      }

      case QueryParser.GT:
      case QueryParser.GE:
      case QueryParser.EQ:
      case QueryParser.LE:
      case QueryParser.LT: {
        final Tree lhs = node.getChild(0);
        final Tree rhs = node.getChild(1);
        if (lhs.getType() != QueryParser.ID) {
          throw new OrmException("Unsupported query token");
        }
        if (rhs.getType() == QueryParser.PLACEHOLDER) {
          return Collections.singletonList(node);
        }
        break;
      }

      case QueryParser.ORDER:
      case QueryParser.LIMIT:
        break;

      default:
        throw new OrmException("Unsupported query token " + node.toStringTree());
    }
    return Collections.emptyList();
  }

  private final class QueryCGS extends IndexFunctionGen.EncodeCGS {
    private final Type[] pTypes;
    private final List<ColumnModel> pCols;
    private final int[] pVars;
    private final int bufvar;
    private int currentp;

    private QueryCGS(MethodVisitor method, Type[] pTypes,
        List<ColumnModel> pCols, int[] pVars, int bufvar) {
      super(method);
      this.pTypes = pTypes;
      this.pCols = pCols;
      this.pVars = pVars;
      this.bufvar = bufvar;
    }

    void nextParameter() {
      currentp++;
    }

    @Override
    void pushBuilder() {
      mv.visitVarInsn(ALOAD, bufvar);
    }

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

    @Override
    protected void appendGetField(final ColumnModel c) {
      if (currentp < pTypes.length && pCols.get(currentp).equals(c)) {
        loadVar(pTypes[currentp], pVars[currentp]);
      } else {
        super.appendGetField(c);
      }
    }
  }
}
