/*
 * 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.util.List;

import org.apache.drill.exec.compile.CompilationConfig;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.TypeInsnNode;
import org.objectweb.asm.tree.analysis.AnalyzerException;
import org.objectweb.asm.tree.analysis.BasicInterpreter;
import org.objectweb.asm.tree.analysis.BasicValue;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

public class ReplacingInterpreter extends BasicInterpreter {
//  private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ReplacingInterpreter.class);

  private final String className; // fully qualified internal class name
  private int index = 0;
  private final List<ReplacingBasicValue> valueList;

  public ReplacingInterpreter(final String className, final List<ReplacingBasicValue> valueList) {
    super(CompilationConfig.ASM_API_VERSION);
    this.className = className;
    this.valueList = valueList;
  }

  @Override
  public BasicValue newValue(final Type t) {
    if (t != null) {
      final ValueHolderIden iden = HOLDERS.get(t.getDescriptor());
      if (iden != null) {
        final ReplacingBasicValue v = ReplacingBasicValue.create(t, iden, index++, valueList);
        v.markFunctionReturn();
        return v;
      }

      // We need to track use of the "this" objectref
      if ((t.getSort() == Type.OBJECT) && className.equals(t.getInternalName())) {
        final ReplacingBasicValue rbValue = ReplacingBasicValue.create(t, null, 0, valueList);
        rbValue.setThis();
        return rbValue;
      }
    }

    return super.newValue(t);
  }

  @Override
  public BasicValue newOperation(final AbstractInsnNode insn) throws AnalyzerException {
    if (insn.getOpcode() == Opcodes.NEW) {
      final TypeInsnNode t = (TypeInsnNode) insn;

      // if this is for a holder class, we'll replace it
      final ValueHolderIden iden = HOLDERS.get(t.desc);
      if (iden != null) {
        return ReplacingBasicValue.create(Type.getObjectType(t.desc), iden, index++, valueList);
      }
    }

    return super.newOperation(insn);
  }

  @Override
  public void returnOperation(AbstractInsnNode insn, BasicValue value, BasicValue expected) {
    if (value instanceof ReplacingBasicValue) {
      ((ReplacingBasicValue) value).markFunctionReturn();
    }
  }

  @Override
  public BasicValue unaryOperation(final AbstractInsnNode insn, final BasicValue value)
      throws AnalyzerException {
    /*
     * We're looking for the assignment of an operator member variable that's a holder to a local
     * objectref. If we spot that, we can't replace the local objectref (at least not
     * until we do the work to replace member variable holders).
     *
     * Note that a GETFIELD does not call newValue(), as would happen for a local variable, so we're
     * emulating that here.
     */
    if ((insn.getOpcode() == Opcodes.GETFIELD) && (value instanceof ReplacingBasicValue)) {
      final ReplacingBasicValue possibleThis = (ReplacingBasicValue) value;
      if (possibleThis.isThis()) {
        final FieldInsnNode fieldInsn = (FieldInsnNode) insn;
        if (HOLDERS.get(fieldInsn.desc) != null) {
          final BasicValue fetchedField = super.unaryOperation(insn, value);
          final ReplacingBasicValue replacingValue =
              ReplacingBasicValue.create(fetchedField.getType(), null, -1, valueList);
          replacingValue.setAssignedToMember();
          return replacingValue;
        }
      }
    }

    return super.unaryOperation(insn,  value);
  }

  @Override
  public BasicValue binaryOperation(final AbstractInsnNode insn,
      final BasicValue value1, final BasicValue value2) throws AnalyzerException {
    /*
     * We're looking for the assignment of a local holder objectref to a member variable.
     * If we spot that, then the local holder can't be replaced, since we don't (yet)
     * have the mechanics to replace the member variable with the holder's members or
     * to assign all of them when this happens.
     */
    if (insn.getOpcode() == Opcodes.PUTFIELD) {
      if (value2.isReference() && (value1 instanceof ReplacingBasicValue)) {
        final ReplacingBasicValue possibleThis = (ReplacingBasicValue) value1;
        if (possibleThis.isThis() && (value2 instanceof ReplacingBasicValue)) {
          // if this is a reference for a holder class, we can't replace it
          if (HOLDERS.get(value2.getType().getDescriptor()) != null) {
            final ReplacingBasicValue localRef = (ReplacingBasicValue) value2;
            localRef.setAssignedToMember();
          }
        }
      }
    }

    return super.binaryOperation(insn, value1, value2);
  }

  @Override
  public BasicValue naryOperation(final AbstractInsnNode insn,
      final List<? extends BasicValue> values) throws AnalyzerException {
    if (insn instanceof MethodInsnNode) {
      boolean skipOne = insn.getOpcode() != Opcodes.INVOKESTATIC;

      // Note if the argument is a holder, and is used as a function argument
      for(BasicValue value : values) {
        // if non-static method, skip over the receiver
        if (skipOne) {
          skipOne = false;
          continue;
        }

        if (value instanceof ReplacingBasicValue) {
          final ReplacingBasicValue argument = (ReplacingBasicValue) value;
          argument.setFunctionArgument();
        }
      }
    }

    return super.naryOperation(insn,  values);
  }

  @Override
  public BasicValue ternaryOperation(AbstractInsnNode insn, BasicValue value1, BasicValue value2, BasicValue value3) throws AnalyzerException {
    // prevents scalar replacement for the case when a holder is stored to the array element
    if (insn.getOpcode() == AASTORE && value3 instanceof ReplacingBasicValue) {
      ReplacingBasicValue argument = (ReplacingBasicValue) value3;
      argument.setAssignedToMember();
    }
    return super.ternaryOperation(insn, value1, value2, value3);
  }

  private static String desc(Class<?> c) {
    final Type t = Type.getType(c);
    return t.getDescriptor();
  }

  static {
    ImmutableMap.Builder<String, ValueHolderIden> builder = ImmutableMap.builder();
    ImmutableSet.Builder<String> setB = ImmutableSet.builder();
    for (Class<?> c : ScalarReplacementTypes.CLASSES) {
      String desc = desc(c);
      setB.add(desc);
      String desc2 = desc.substring(1, desc.length() - 1);
      ValueHolderIden vhi = new ValueHolderIden(c);
      builder.put(desc, vhi);
      builder.put(desc2, vhi);
    }
    HOLDER_DESCRIPTORS = setB.build();
    HOLDERS = builder.build();
  }

  private final static ImmutableMap<String, ValueHolderIden> HOLDERS;
  public final static ImmutableSet<String> HOLDER_DESCRIPTORS;
}
