// 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 org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

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('.', '/'));
  }
}
