// 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.ColumnModel;
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

public class CodeGenSupport implements Opcodes {
  public final MethodVisitor mv;
  private ColumnModel col;
  private int dupOnSet;
  private int columnIdx;
  private Type entityType;

  private int lastLocal = 2;
  private List<Integer> freeLocals = new ArrayList<>(4);

  public CodeGenSupport(final MethodVisitor method) {
    mv = method;
  }

  public void push(final int val) {
    switch (val) {
      case -1:
        mv.visitInsn(ICONST_M1);
        break;
      case 0:
        mv.visitInsn(ICONST_0);
        break;
      case 1:
        mv.visitInsn(ICONST_1);
        break;
      case 2:
        mv.visitInsn(ICONST_2);
        break;
      case 3:
        mv.visitInsn(ICONST_3);
        break;
      case 4:
        mv.visitInsn(ICONST_4);
        break;
      case 5:
        mv.visitInsn(ICONST_5);
        break;
      default:
        if (Byte.MIN_VALUE >= val && val < Byte.MAX_VALUE) {
          mv.visitIntInsn(BIPUSH, val);
        } else if (Short.MIN_VALUE >= val && val < Short.MAX_VALUE) {
          mv.visitIntInsn(SIPUSH, val);
        } else {
          mv.visitLdcInsn(Integer.valueOf(val));
        }
        break;
    }
  }

  public void loadVar(final Type type, final int index) {
    mv.visitVarInsn(type.getOpcode(ILOAD), index);
  }

  public int newLocal() {
    if (freeLocals.isEmpty()) {
      return ++lastLocal;
    }
    return freeLocals.remove(freeLocals.size() - 1);
  }

  public void freeLocal(final int index) {
    freeLocals.add(index);
  }

  public void setEntityType(final Type et) {
    entityType = et;
  }

  public void setFieldReference(final ColumnModel cm) {
    col = cm;
    dupOnSet = -1;
    columnIdx++;
  }

  public void resetColumnIndex(final int s) {
    columnIdx = s;
  }

  public int getColumnIndex() {
    return columnIdx;
  }

  public ColumnModel getFieldReference() {
    return col;
  }

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

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

  public void pushColumnIndex() {
    push(columnIdx);
  }

  public void invokePreparedStatementSet(final String sqlTypeName) {
    final Method m;
    try {
      m =
          PreparedStatement.class.getMethod(
              "set" + sqlTypeName,
              Integer.TYPE,
              ResultSet.class.getMethod("get" + sqlTypeName, Integer.TYPE).getReturnType());
    } catch (SecurityException e) {
      throw new RuntimeException("java.sql has no " + sqlTypeName);
    } catch (NoSuchMethodException e) {
      throw new RuntimeException("java.sql has no " + sqlTypeName, e);
    }
    mv.visitMethodInsn(
        INVOKEINTERFACE,
        Type.getInternalName(PreparedStatement.class),
        m.getName(),
        Type.getMethodDescriptor(m));
  }

  public void invokeResultSetGet(final String sqlTypeName) {
    final Method m;
    try {
      m = ResultSet.class.getMethod("get" + sqlTypeName, Integer.TYPE);
    } catch (SecurityException e) {
      throw new RuntimeException("java.sql has no " + sqlTypeName);
    } catch (NoSuchMethodException e) {
      throw new RuntimeException("java.sql has no " + sqlTypeName, e);
    }
    mv.visitMethodInsn(
        INVOKEINTERFACE,
        Type.getInternalName(ResultSet.class),
        m.getName(),
        Type.getMethodDescriptor(m));
  }

  public void fieldSetBegin() {
    pushEntity();
    if (col.getParent() != null) {
      appendGetField(col.getParent());
    }
  }

  public void fieldSetEnd() {
    final Type c = containerClass(col);
    if (dupOnSet >= 0) {
      mv.visitInsn(DUP);
      mv.visitVarInsn(ASTORE, dupOnSet);
    }
    mv.visitFieldInsn(
        PUTFIELD, c.getInternalName(), col.getFieldName(), toType(col).getDescriptor());
  }

  public void setDupOnFieldSetEnd(final int varIdx) {
    dupOnSet = varIdx;
  }

  public void pushFieldValue() {
    pushEntity();
    appendGetField(col);
  }

  protected void appendGetField(final ColumnModel c) {
    if (c.getParent() != null) {
      appendGetField(c.getParent());
    }
    final Type t = containerClass(c);
    mv.visitFieldInsn(GETFIELD, t.getInternalName(), c.getFieldName(), toType(c).getDescriptor());
  }

  private Type containerClass(final ColumnModel c) {
    if (c.getParent() == null) {
      return entityType;
    }
    final String n = c.getParent().getNestedClassName();
    return Type.getObjectType(n.replace('.', '/'));
  }

  public static Type toType(final ColumnModel c) {
    if (c.isSqlPrimitive()) {
      return Type.getType(c.getPrimitiveType());
    }
    return Type.getObjectType(c.getNestedClassName().replace('.', '/'));
  }
}
