/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.drill.exec.compile.bytecode;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

import com.carrotsearch.hppc.ObjectIntHashMap;
import com.carrotsearch.hppc.cursors.ObjectIntCursor;
import com.google.common.collect.Lists;

class ValueHolderIden {
//  private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ValueHolderIden.class);

  // the index of a field is the number in which it appears within the holder
  private final ObjectIntHashMap<String> fieldMap; // field name -> index
  private final Type[] types; // the type of each field in the holder, by index
  private final String[] names; // the name of each field in the holder, by index
  private final int[] offsets; // the offset of each field in the holder, by index
  private final Type type; // type of the holder itself

  public ValueHolderIden(Class<?> c) {
    Field[] fields = c.getFields();

    // Find the non-static member variables
    List<Field> fldList = Lists.newArrayList();
    for (Field f : fields) {
      if (!Modifier.isStatic(f.getModifiers())) {
        fldList.add(f);
      }
    }

    this.type = Type.getType(c);

    this.types = new Type[fldList.size()];
    this.names = new String[fldList.size()];
    this.offsets = new int[fldList.size()];
    fieldMap = new ObjectIntHashMap<String>(fldList.size());
    int i = 0; // index of the next holder member variable
    int offset = 0; // offset of the next holder member variable
    for (Field f : fldList) {
      types[i] = Type.getType(f.getType());
      names[i] = f.getName();
      offsets[i] = offset;
      fieldMap.put(f.getName(), i);

      // the next offset and index
      offset += types[i].getSize();
      i++;
    }
  }

  public void dump(final StringBuilder sb) {
    sb.append("ValueHolderIden: type=" + type + '\n');
    for (ObjectIntCursor<String> oic : fieldMap) {
      sb.append("  " + oic.key + ": i=" + oic.value + ", type=" + types[oic.value] +
          ", offset=" + offsets[oic.value] + '\n');
    }
  }

  private static void initType(int offset, Type t, DirectSorter v) {
    switch(t.getSort()) {
    case Type.BOOLEAN:
    case Type.BYTE:
    case Type.CHAR:
    case Type.SHORT:
    case Type.INT:
      v.visitInsn(Opcodes.ICONST_0);
      v.directVarInsn(Opcodes.ISTORE, offset);
      break;
    case Type.LONG:
      v.visitInsn(Opcodes.LCONST_0);
      v.directVarInsn(Opcodes.LSTORE, offset);
      break;
    case Type.FLOAT:
      v.visitInsn(Opcodes.FCONST_0);
      v.directVarInsn(Opcodes.FSTORE, offset);
      break;
    case Type.DOUBLE:
      v.visitInsn(Opcodes.DCONST_0);
      v.directVarInsn(Opcodes.DSTORE, offset);
      break;
    case Type.OBJECT:
      v.visitInsn(Opcodes.ACONST_NULL);
      v.directVarInsn(Opcodes.ASTORE, offset);
      break;
    default:
      throw new UnsupportedOperationException();
    }
  }

  /**
   * Add the locals necessary to replace the members of a holder of this type.
   *
   * @param adder the method visitor to use to add the necessary instructions
   * @param defaultFirst the default index to return for the first variable
   *   if we don't find another one
   * @return the index of the first local variable (standing in for the first holder member)
   */
  private int addLocals(final DirectSorter adder, final int defaultFirst) {
    int first = defaultFirst;
    for (int i = 0; i < types.length; i++) {
      int varIndex = adder.newLocal(types[i]);
      if (i == 0) {
        first = varIndex; // first offset
      }
    }

    return first;
  }

  public ValueHolderSub getHolderSub(DirectSorter adder) {
    final int first = addLocals(adder, -1);
    return new ValueHolderSub(first);
  }

  public ValueHolderSub getHolderSubWithDefinedLocals(int first) {
    return new ValueHolderSub(first);
  }

  /**
   * Return the DUP or DUP2 opcode appropriate for the given type.
   *
   * @param type the type
   * @return the DUP/DUP2 opcode to use for type
   */
  private static int getDupOpcode(final Type type) {
    assert type.getSize() >= 1;
    return type.getSize() == 1 ? Opcodes.DUP : Opcodes.DUP2;
  }

  /**
   * Transfer the member variables of this holder to local variables.
   *
   * <p>If this is used, the maximum stack size must be increased by one
   * to accommodate the extra DUP instruction this will generate.
   *
   * @param adder a visitor that will be called to add the necessary instructions
   * @param localVariable the offset of the first local variable to use
   */
  public void transferToLocal(final DirectSorter adder, final int localVariable) {
    for (int i = 0; i < types.length; i++) {
      final Type t = types[i];
      if (i + 1 < types.length) {
        adder.visitInsn(Opcodes.DUP); // not size dependent: always the objectref from which we'll GETFIELD
        }
      adder.visitFieldInsn(Opcodes.GETFIELD, type.getInternalName(), names[i], t.getDescriptor());
      adder.directVarInsn(t.getOpcode(Opcodes.ISTORE), localVariable + offsets[i]);
    }
  }

  /**
   * Create local variables and transfer the members of a holder to them.
   *
   * @param adder the method visitor to use to add the variables
   * @return the index of the first variable added
   */
  public int createLocalAndTransfer(final DirectSorter adder) {
    final int first = addLocals(adder, 0);
    transferToLocal(adder, first);
    return first;
  }

  public class ValueHolderSub {
    private int first; // TODO: deal with transfer() so this can be made final

    @Override
    public String toString() {
      return "ValueHolderSub(" + first + ")";
    }

    public ValueHolderSub(int first) {
      assert first != -1 : "Create Holder for sub that doesn't have any fields.";
      this.first = first;
    }

    public ValueHolderIden iden() {
      return ValueHolderIden.this;
    }

    public void init(DirectSorter mv) {
      for (int i = 0; i < types.length; i++) {
        initType(first + offsets[i], types[i], mv);
      }
    }

    public int first() {
      return first;
    }

    private int getFieldIndex(final String name, final InstructionModifier mv) {
      if (!fieldMap.containsKey(name)) {
        throw new IllegalArgumentException(String.format(
            "Unknown name '%s' on line %d.", name, mv.getLastLineNumber()));
      }
      return fieldMap.get(name); // using lget() is not thread-safe
    }

    public void addInsn(String name, InstructionModifier mv, int opcode) {
      switch (opcode) {
      case Opcodes.GETFIELD:
        addKnownInsn(name, mv, Opcodes.ILOAD);
        return;

      case Opcodes.PUTFIELD:
        addKnownInsn(name, mv, Opcodes.ISTORE);
      }
    }

    // TODO: do we really need this? Instead of moving the variables, can't we just
    // use the original locations in the subsequent references?
    public void transfer(InstructionModifier mv, int newStart) {
      // if the new location is the same as the current position, there's nothing to do
      if (first == newStart) {
        return;
      }

      for (int i = 0; i < types.length; i++) {
        mv.directVarInsn(types[i].getOpcode(Opcodes.ILOAD), first + offsets[i]);
        mv.directVarInsn(types[i].getOpcode(Opcodes.ISTORE), newStart + offsets[i]);
      }

      this.first = newStart;
    }

    private void addKnownInsn(String name, InstructionModifier mv, int analogOpcode) {
      int f = getFieldIndex(name, mv);
      Type t = types[f];
      mv.directVarInsn(t.getOpcode(analogOpcode), first + offsets[f]);
    }

    /**
     *
     * @param adder
     * @param owner
     * @param name
     * @param desc
     * @return amount of additional stack space that will be required for this instruction stream
     */
    public int transferToExternal(final DirectSorter adder, final String owner,
        final String name, final String desc) {
      // create a new object and assign it to the desired field.
      adder.visitTypeInsn(Opcodes.NEW, type.getInternalName());
      adder.visitInsn(getDupOpcode(type));
      adder.visitMethodInsn(Opcodes.INVOKESPECIAL, type.getInternalName(), "<init>", "()V", false);

      // now we need to set all of the values of this new object.
      int additionalStack = 0;
      for (int i = 0; i < types.length; i++) {
        final Type t = types[i];

        // dup the object where we are putting the field.
        adder.visitInsn(getDupOpcode(type)); // dup for every as we want to save in place at end.
        adder.directVarInsn(t.getOpcode(Opcodes.ILOAD), first + offsets[i]);
        adder.visitFieldInsn(Opcodes.PUTFIELD, type.getInternalName(), names[i], t.getDescriptor());

        /*
         * The above substitutes a reference to a scalar in a holder with a direct reference to
         * the scalar.
         *
         * In the case of longs or doubles, this requires more stack space than was used before;
         * if we were moving a reference to a holder with a long, we were previously moving the
         * reference. But now we're moving the long, which is twice as big. So we may need more
         * stack space than has currently been allocated.
         */
        if (t.getSize() > additionalStack) {
          additionalStack = t.getSize();
        }
      }

      // lastly we save it to the desired field.
      adder.visitFieldInsn(Opcodes.PUTFIELD, owner, name, desc);

      return additionalStack;
    }
  }
}
