// 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.schema.ColumnModel;
import com.google.gwtorm.schema.QueryModel;
import com.google.gwtorm.schema.QueryParser;
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 org.antlr.runtime.tree.Tree;
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.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/** Generates {@link IndexFunction} implementations. */
class IndexFunctionGen<T> implements Opcodes {
  private static final Type string = Type.getType(String.class);
  private static final Type object = Type.getType(Object.class);
  private static final Type indexKeyBuilder =
      Type.getType(IndexKeyBuilder.class);

  private final GeneratedClassLoader classLoader;
  private final QueryModel query;
  private final List<QueryModel.OrderBy> myFields;
  private final Class<T> pojo;
  private final Type pojoType;

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

  IndexFunctionGen(final GeneratedClassLoader loader, final QueryModel qm,
      final Class<T> t) {
    classLoader = loader;
    query = qm;

    myFields = new ArrayList<>();

    // Only add each parameter column once, but in the order used.
    // This avoids a range test on the same column from duplicating
    // the data in the index record.
    //
    for (ColumnModel m : leaves(query.getParameters())) {
      QueryModel.OrderBy o = new QueryModel.OrderBy(m, false);
      if (!myFields.contains(o)) {
        myFields.add(o);
      }
    }

    // Skip ORDER BY columns that match with the parameters, then
    // add anything else onto the end.
    //
    int p = 0;
    Iterator<QueryModel.OrderBy> orderby = orderByLeaves(query.getOrderBy()).iterator();
    while (p < myFields.size() && orderby.hasNext()) {
      QueryModel.OrderBy o = orderby.next();
      if (!myFields.get(p).equals(o)) {
        myFields.add(o);
        break;
      }
      p++;
    }
    while (orderby.hasNext()) {
      myFields.add(orderby.next());
    }

    pojo = t;
    pojoType = Type.getType(pojo);
  }

  private static List<ColumnModel> leaves(List<ColumnModel> in) {
    ArrayList<ColumnModel> r = new ArrayList<>(in.size());
    for (ColumnModel m : in) {
      if (m.isNested()) {
        r.addAll(m.getAllLeafColumns());
      } else {
        r.add(m);
      }
    }
    return r;
  }

  private static List<QueryModel.OrderBy> orderByLeaves(List<QueryModel.OrderBy> in) {
    ArrayList<QueryModel.OrderBy> r = new ArrayList<>(in.size());
    for (QueryModel.OrderBy m : in) {
      if (m.column.isNested()) {
        for (ColumnModel c : m.column.getAllLeafColumns()) {
          r.add(new QueryModel.OrderBy(c, m.descending));
        }
      } else {
        r.add(m);
      }
    }
    return r;
  }

  IndexFunction<T> create() throws OrmException {
    init();
    implementConstructor();
    implementGetName();
    implementIncludes();
    implementEncode();
    cw.visitEnd();
    classLoader.defineClass(implClassName, cw.toByteArray());

    try {
      final Class<?> c = Class.forName(implClassName, true, classLoader);
      return cast(c.newInstance());
    } catch (InstantiationException e) {
      throw new OrmException("Cannot create new encoder", e);
    } catch (IllegalAccessException e) {
      throw new OrmException("Cannot create new encoder", e);
    } catch (ClassNotFoundException e) {
      throw new OrmException("Cannot create new encoder", e);
    }
  }

  @SuppressWarnings("unchecked")
  private static <T> IndexFunction<T> cast(final Object c) {
    return (IndexFunction<T>) c;
  }

  private void init() {
    superTypeName = Type.getInternalName(IndexFunction.class);
    implClassName =
        pojo.getName() + "_IndexFunction_" + query.getName() + "_"
            + 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[] {});
  }

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

    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKESPECIAL, superTypeName, consName, consDesc);

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

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

  private void implementIncludes() throws OrmException {
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC, "includes", Type.getMethodDescriptor(
            Type.BOOLEAN_TYPE, new Type[] {object}), null, null);
    mv.visitCode();
    final IncludeCGS cgs = new IncludeCGS(mv);
    cgs.setEntityType(pojoType);

    mv.visitVarInsn(ALOAD, 1);
    mv.visitTypeInsn(CHECKCAST, pojoType.getInternalName());
    mv.visitVarInsn(ASTORE, 1);

    Set<ColumnModel> checked = new HashSet<>();
    for (QueryModel.OrderBy orderby : myFields) {
      checkNotNullFields(Collections.singleton(orderby.column), checked, mv, cgs);
    }

    final Tree parseTree = query.getParseTree();
    if (parseTree != null) {
      checkConstants(parseTree, mv, cgs);
    }

    cgs.push(1);
    mv.visitInsn(IRETURN);

    mv.visitLabel(cgs.no);
    cgs.push(0);
    mv.visitInsn(IRETURN);

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

  private static void checkNotNullFields(Collection<ColumnModel> myFields,
      Set<ColumnModel> checked, MethodVisitor mv, IncludeCGS cgs)
      throws OrmException {
    for (ColumnModel f : myFields) {
      if (f.isNested()) {
        checkNotNullFields(f.getNestedColumns(), checked, mv, cgs);
      } else {
        checkNotNullScalar(mv, checked, cgs, f);
      }
    }
  }

  private static void checkNotNullScalar(MethodVisitor mv,
      Set<ColumnModel> checked, IncludeCGS cgs, ColumnModel f)
      throws OrmException {
    checkParentNotNull(f.getParent(), checked, mv, cgs);
    cgs.setFieldReference(f);

    switch (Type.getType(f.getPrimitiveType()).getSort()) {
      case Type.BOOLEAN:
      case Type.BYTE:
      case Type.SHORT:
      case Type.CHAR:
      case Type.INT:
      case Type.LONG:
        break;

      case Type.ARRAY:
      case Type.OBJECT: {
        if (f.getPrimitiveType() == byte[].class) {
          cgs.pushFieldValue();
          mv.visitJumpInsn(IFNULL, cgs.no);

        } else if (f.getPrimitiveType() == String.class) {
          cgs.pushFieldValue();
          mv.visitJumpInsn(IFNULL, cgs.no);

        } else if (f.getPrimitiveType() == java.sql.Timestamp.class
            || f.getPrimitiveType() == java.util.Date.class
            || f.getPrimitiveType() == java.sql.Date.class) {
          cgs.pushFieldValue();
          mv.visitJumpInsn(IFNULL, cgs.no);

        } else {
          throw new OrmException("Type " + f.getPrimitiveType()
              + " not supported for field " + f.getPathToFieldName());
        }
        break;
      }

      default:
        throw new OrmException("Type " + f.getPrimitiveType()
            + " not supported for field " + f.getPathToFieldName());
    }
  }

  private static void checkParentNotNull(ColumnModel f,
      Set<ColumnModel> checked, MethodVisitor mv, IncludeCGS cgs) {
    if (f != null && checked.add(f)) {
      checkParentNotNull(f.getParent(), checked, mv, cgs);
      cgs.setFieldReference(f);
      cgs.pushFieldValue();
      mv.visitJumpInsn(IFNULL, cgs.no);
    }
  }

  private void checkConstants(Tree node, MethodVisitor mv, IncludeCGS cgs)
      throws OrmException {
    switch (node.getType()) {
      // These don't impact the constant evaluation
      case QueryParser.ORDER:
      case QueryParser.LIMIT:
        break;

      case 0: // nil node used to join other nodes together
      case QueryParser.WHERE:
      case QueryParser.AND:
        for (int i = 0; i < node.getChildCount(); i++) {
          checkConstants(node.getChild(i), mv, cgs);
        }
        break;

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

        cgs.setFieldReference(((QueryParser.Column) lhs).getField());
        switch (rhs.getType()) {
          case QueryParser.PLACEHOLDER:
            // Parameter evaluated at runtime
            break;

          case QueryParser.TRUE:
            cgs.pushFieldValue();
            mv.visitJumpInsn(IFEQ, cgs.no);
            break;

          case QueryParser.FALSE:
            cgs.pushFieldValue();
            mv.visitJumpInsn(IFNE, cgs.no);
            break;

          case QueryParser.CONSTANT_INTEGER:
            cgs.pushFieldValue();
            cgs.push(Integer.parseInt(rhs.getText()));
            mv.visitJumpInsn(IF_ICMPNE, cgs.no);
            break;

          case QueryParser.CONSTANT_STRING:
            if (cgs.getFieldReference().getPrimitiveType() == Character.TYPE) {
              cgs.push(dequote(rhs.getText()).charAt(0));
              cgs.pushFieldValue();
              mv.visitJumpInsn(IF_ICMPNE, cgs.no);
            } else {
              mv.visitLdcInsn(dequote(rhs.getText()));
              cgs.pushFieldValue();
              mv.visitMethodInsn(INVOKEVIRTUAL, string.getInternalName(),
                  "equals", Type.getMethodDescriptor(Type.BOOLEAN_TYPE,
                      new Type[] {object}));
              mv.visitJumpInsn(IFEQ, cgs.no);
            }
            break;
        }
        break;
      }

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

  private static String dequote(String text) {
    return text.substring(1, text.length() - 1);
  }

  private void implementEncode() throws OrmException {
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC, "encode", Type.getMethodDescriptor(
            Type.VOID_TYPE, new Type[] {indexKeyBuilder, object}), null, null);
    mv.visitCode();
    final EncodeCGS cgs = new EncodeCGS(mv);
    cgs.setEntityType(pojoType);

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

    encodeFields(myFields, mv, cgs);

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

  static void encodeFields(Collection<QueryModel.OrderBy> myFields,
      final MethodVisitor mv, final EncodeCGS cgs) throws OrmException {
    Iterator<QueryModel.OrderBy> i = myFields.iterator();
    while (i.hasNext()) {
      QueryModel.OrderBy f = i.next();
      encodeScalar(f, mv, cgs);
      if (i.hasNext()) {
        cgs.delimiter();
      }
    }
  }

  static void encodeField(QueryModel.OrderBy f, final MethodVisitor mv,
      final EncodeCGS cgs) throws OrmException {
    if (f.column.isNested()) {
      encodeFields(orderByLeaves(Collections.singletonList(f)), mv, cgs);
    } else {
      encodeScalar(f, mv, cgs);
    }
  }

  private static void encodeScalar(QueryModel.OrderBy f, final MethodVisitor mv,
      final EncodeCGS cgs) throws OrmException {
    String method = f.descending ? "desc" : "add";
    ColumnModel c = f.column;
    cgs.setFieldReference(c);

    switch (Type.getType(c.getPrimitiveType()).getSort()) {
      case Type.BOOLEAN:
      case Type.BYTE:
      case Type.SHORT:
      case Type.CHAR:
      case Type.INT:
        cgs.pushBuilder();
        cgs.pushFieldValue();
        mv.visitInsn(I2L);
        mv.visitMethodInsn(INVOKEVIRTUAL, indexKeyBuilder.getInternalName(),
            method, Type.getMethodDescriptor(Type.VOID_TYPE,
                new Type[] {Type.LONG_TYPE}));
        break;

      case Type.LONG:
        cgs.pushBuilder();
        cgs.pushFieldValue();
        mv.visitMethodInsn(INVOKEVIRTUAL, indexKeyBuilder.getInternalName(),
            method, Type.getMethodDescriptor(Type.VOID_TYPE,
                new Type[] {Type.LONG_TYPE}));
        break;

      case Type.ARRAY:
      case Type.OBJECT: {
        if (c.getPrimitiveType() == byte[].class) {
          cgs.pushBuilder();
          cgs.pushFieldValue();
          mv.visitMethodInsn(INVOKEVIRTUAL, indexKeyBuilder.getInternalName(),
              method, Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {Type
                  .getType(byte[].class)}));

        } else if (c.getPrimitiveType() == String.class) {
          cgs.pushBuilder();
          cgs.pushFieldValue();
          mv.visitMethodInsn(INVOKEVIRTUAL, indexKeyBuilder.getInternalName(),
              method, Type.getMethodDescriptor(Type.VOID_TYPE,
                  new Type[] {string}));

        } else if (c.getPrimitiveType() == java.sql.Timestamp.class
            || c.getPrimitiveType() == java.util.Date.class
            || c.getPrimitiveType() == java.sql.Date.class) {
          cgs.pushBuilder();
          cgs.pushFieldValue();
          String tsType = Type.getType(c.getPrimitiveType()).getInternalName();
          mv.visitMethodInsn(INVOKEVIRTUAL, tsType, "getTime", Type
              .getMethodDescriptor(Type.LONG_TYPE, new Type[] {}));
          mv.visitMethodInsn(INVOKEVIRTUAL, indexKeyBuilder.getInternalName(),
              method, Type.getMethodDescriptor(Type.VOID_TYPE,
                  new Type[] {Type.LONG_TYPE}));
        } else {
          throw new OrmException("Type " + c.getPrimitiveType()
              + " not supported for field " + c.getPathToFieldName());
        }
        break;
      }

      default:
        throw new OrmException("Type " + c.getPrimitiveType()
            + " not supported for field " + c.getPathToFieldName());
    }
  }

  private static final class IncludeCGS extends CodeGenSupport {
    final Label no = new Label();

    private IncludeCGS(MethodVisitor method) {
      super(method);
    }

    @Override
    public void pushEntity() {
      mv.visitVarInsn(ALOAD, 1);
    }
  }

  static class EncodeCGS extends CodeGenSupport {
    EncodeCGS(MethodVisitor method) {
      super(method);
    }

    void infinity() {
      pushBuilder();
      mv.visitMethodInsn(INVOKEVIRTUAL, indexKeyBuilder.getInternalName(),
          "infinity", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {}));
    }

    void delimiter() {
      pushBuilder();
      mv.visitMethodInsn(INVOKEVIRTUAL, indexKeyBuilder.getInternalName(),
          "delimiter", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {}));
    }

    void nul() {
      pushBuilder();
      mv.visitMethodInsn(INVOKEVIRTUAL, indexKeyBuilder.getInternalName(),
          "nul", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {}));
    }

    void pushBuilder() {
      mv.visitVarInsn(ALOAD, 1);
    }

    @Override
    public void pushEntity() {
      mv.visitVarInsn(ALOAD, 2);
    }
  }
}
