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

import static org.apache.drill.exec.compile.sig.GeneratorMapping.GM;

import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import io.netty.buffer.DrillBuf;
import org.apache.calcite.util.Pair;
import org.apache.drill.common.exceptions.DrillRuntimeException;
import org.apache.drill.common.expression.LogicalExpression;
import org.apache.drill.common.types.TypeProtos;
import org.apache.drill.common.types.TypeProtos.DataMode;
import org.apache.drill.common.types.TypeProtos.MajorType;
import org.apache.drill.exec.ExecConstants;
import org.apache.drill.exec.compile.sig.CodeGeneratorArgument;
import org.apache.drill.exec.compile.sig.CodeGeneratorMethod;
import org.apache.drill.exec.compile.sig.GeneratorMapping;
import org.apache.drill.exec.compile.sig.MappingSet;
import org.apache.drill.exec.compile.sig.SignatureHolder;
import org.apache.drill.exec.exception.SchemaChangeException;
import org.apache.drill.exec.expr.fn.WorkspaceReference;
import org.apache.drill.exec.expr.holders.ValueHolder;
import org.apache.drill.exec.record.TypedFieldId;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import com.sun.codemodel.JBlock;
import com.sun.codemodel.JCatchBlock;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JClassAlreadyExistsException;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JExpr;
import com.sun.codemodel.JExpression;
import com.sun.codemodel.JFieldRef;
import com.sun.codemodel.JInvocation;
import com.sun.codemodel.JLabel;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JMod;
import com.sun.codemodel.JTryBlock;
import com.sun.codemodel.JType;
import com.sun.codemodel.JVar;
import org.apache.drill.exec.server.options.OptionSet;

public class ClassGenerator<T> {

  public static final GeneratorMapping DEFAULT_SCALAR_MAP = GM("doSetup", "doEval", null, null);
  public static final GeneratorMapping DEFAULT_CONSTANT_MAP = GM("doSetup", "doSetup", null, null);
  public static final String INNER_CLASS_FIELD_NAME = "innerClassField";

  public enum BlockType {SETUP, EVAL, RESET, CLEANUP}

  private final SignatureHolder sig;
  private final EvaluationVisitor evaluationVisitor;
  private final Map<ValueVectorSetup, JVar> vvDeclaration = Maps.newHashMap();
  private final Map<String, ClassGenerator<T>> innerClasses = Maps.newHashMap();
  private final List<TypedFieldId> workspaceTypes = Lists.newArrayList();
  private final Map<WorkspaceReference, JVar> workspaceVectors = Maps.newHashMap();
  private final Map<Pair<Integer, JVar>, Function<DrillBuf, ? extends ValueHolder>> constantVars;
  private final CodeGenerator<T> codeGenerator;

  public final JDefinedClass clazz;

  private final JCodeModel model;
  private final OptionSet optionManager;

  private ClassGenerator<T> innerClassGenerator;
  private LinkedList<SizedJBlock>[] blocks;
  private LinkedList<SizedJBlock>[] oldBlocks;

  private JVar innerClassField;

  /**
   * Assume that field has 3 indexes within the constant pull: index of the<br>
   * CONSTANT_Fieldref_info + CONSTANT_Fieldref_info.name_and_type_index + CONSTANT_NameAndType_info.name_index.
   * CONSTANT_NameAndType_info.descriptor_index has limited range of values,
   * CONSTANT_Fieldref_info.class_index is the same for a single class, they will
   * be taken into account later.
   * <p>
   * Local variable has 1 index within the constant pool.
   * {@link org.objectweb.asm.MethodWriter#visitLocalVariable(String, String, String, Label, Label, int)}
   * <p>
   * For upper estimation of max index value, suppose that each field and local
   * variable uses different literal values that have two indexes, then the
   * number of occupied indexes within the constant pull is<br>
   * fieldCount * 3 + fieldCount * 2 + (index - fieldCount) * 3 => fieldCount * 2 + index * 3
   * <p>
   * Assumed that method has 3 indexes within the constant pull: index of the
   * CONSTANT_Methodref_info + CONSTANT_Methodref_info.name_and_type_index +
   * CONSTANT_NameAndType_info.name_index.
   * <p>
   * For the upper estimation of number of split methods suppose that each
   * expression in the method uses single variable. Suppose that the max number
   * of indexes within the constant pull occupied by fields and local variables
   * is M, the number of split methods is N, number of abstract methods in the
   * template is A, then splitted methods count is<br>
   * N = (M - A * N * 3) / 50 => N = M / (50 + A * 3)
   * <p>
   * Additionally should be taken into account class references; fields and
   * methods from the template, so reserves 1000 for them.
   * <p>
   * Then the size of the occupied part in the constant pull is<br>
   * (fieldCount * 2 + index * 3 + 1000) * (1 + 3 / (50 + A * 3))
   */
  private long maxIndex;

  private int index;
  private int labelIndex;
  private MappingSet mappings;

  public static MappingSet getDefaultMapping() {
    return new MappingSet("inIndex", "outIndex", DEFAULT_CONSTANT_MAP, DEFAULT_SCALAR_MAP);
  }

  @SuppressWarnings("unchecked")
  ClassGenerator(CodeGenerator<T> codeGenerator, MappingSet mappingSet, SignatureHolder signature,
                 EvaluationVisitor eval, JDefinedClass clazz, JCodeModel model,
                 OptionSet optionManager) throws JClassAlreadyExistsException {
    this.codeGenerator = codeGenerator;
    this.clazz = clazz;
    this.mappings = mappingSet;
    this.sig = signature;
    this.evaluationVisitor = eval;
    this.model = model;
    this.optionManager = optionManager;
    constantVars = new HashMap<>();

    blocks = new LinkedList[sig.size()];
    for (int i =0; i < sig.size(); i++) {
      blocks[i] = Lists.newLinkedList();
    }
    rotateBlock();

    for (SignatureHolder child : signature.getChildHolders()) {
      Class<?> innerClass = child.getSignatureClass();
      String innerClassName = innerClass.getSimpleName();

      // Create the inner class as private final. If the template (super) class
      // is static, then make the subclass static as well. Note the conversion
      // from the JDK Modifier values to the JCodeModel JMod values: the
      // values are different.

      int mods = JMod.FINAL;
      if ((innerClass.getModifiers() & Modifier.STATIC) != 0) {
        mods += JMod.STATIC;
      }
      JDefinedClass innerClazz = clazz._class(mods, innerClassName);
      innerClasses.put(innerClassName, new ClassGenerator<>(codeGenerator, mappingSet, child, eval, innerClazz, model, optionManager));
    }
    long maxExprsNumber = optionManager != null ? optionManager.getOption(ExecConstants.CODE_GEN_EXP_IN_METHOD_SIZE_VALIDATOR) : 50;
    maxIndex = Math.round((0xFFFF / (1 + 3. / (3L * sig.size() + maxExprsNumber)) - 1000) / 3);
  }

  public ClassGenerator<T> getInnerGenerator(String name) {
    ClassGenerator<T> inner = innerClasses.get(name);
    Preconditions.checkNotNull(inner);
    return inner;
  }

  public MappingSet getMappingSet() {
    return mappings;
  }

  public void setMappingSet(MappingSet mappings) {
    if (innerClassGenerator != null) {
      innerClassGenerator.setMappingSet(mappings);
    }
    this.mappings = mappings;
  }

  public CodeGenerator<T> getCodeGenerator() {
    return codeGenerator;
  }

  private GeneratorMapping getCurrentMapping() {
    return mappings.getCurrentMapping();
  }

  public JBlock getBlock(String methodName) {
    JBlock blk = this.blocks[sig.get(methodName)].getLast().getBlock();
    Preconditions.checkNotNull(blk, "Requested method name of %s was not available for signature %s.",  methodName, this.sig);
    return blk;
  }

  public JBlock getBlock(BlockType type) {
    return getBlock(getCurrentMapping().getMethodName(type));
  }

  public JBlock getSetupBlock() {
    return getBlock(getCurrentMapping().getMethodName(BlockType.SETUP));
  }

  public JBlock getEvalBlock() {
    return getBlock(getCurrentMapping().getMethodName(BlockType.EVAL));
  }

  public JBlock getResetBlock() {
    return getBlock(getCurrentMapping().getMethodName(BlockType.RESET));
  }

  public JBlock getCleanupBlock() {
    return getBlock(getCurrentMapping().getMethodName(BlockType.CLEANUP));
  }

  public void nestEvalBlock(JBlock block) {
    String methodName = getCurrentMapping().getMethodName(BlockType.EVAL);
    evaluationVisitor.newScope();
    this.blocks[sig.get(methodName)].addLast(new SizedJBlock(block));
  }

  public void unNestEvalBlock() {
    String methodName = getCurrentMapping().getMethodName(BlockType.EVAL);
    evaluationVisitor.leaveScope();
    this.blocks[sig.get(methodName)].removeLast();
  }

  public JLabel getEvalBlockLabel (String prefix) {
    return getEvalBlock().label(prefix + labelIndex++);
  }

  /**
   * Creates an inner braced and indented block
   * @param type type of the created block
   * @return a newly created inner block
   */
  private JBlock createInnerBlock(BlockType type) {
    final JBlock currBlock = getBlock(type);
    final JBlock innerBlock = new JBlock();
    currBlock.add(innerBlock);
    return innerBlock;
  }

  /**
   * Creates an inner braced and indented block for evaluation of the expression.
   * @return a newly created inner eval block
   */
  protected JBlock createInnerEvalBlock() {
    return createInnerBlock(BlockType.EVAL);
  }

  public JVar declareVectorValueSetupAndMember(String batchName, TypedFieldId fieldId) {
    return declareVectorValueSetupAndMember(DirectExpression.direct(batchName), fieldId);
  }

  /**
   * Creates class variable for the value vector using metadata from {@code fieldId}
   * and initializes it using setup blocks.
   *
   * @param batchName expression for invoking {@code getValueAccessorById} method
   * @param fieldId   metadata of the field that should be declared
   * @return a newly generated class field
   */
  public JVar declareVectorValueSetupAndMember(DirectExpression batchName, TypedFieldId fieldId) {
    // declares field in the inner class if innerClassGenerator has been created
    if (innerClassGenerator != null) {
      return innerClassGenerator.declareVectorValueSetupAndMember(batchName, fieldId);
    }
    final ValueVectorSetup setup = new ValueVectorSetup(batchName, fieldId);
//    JVar var = this.vvDeclaration.get(setup);
//    if(var != null) return var;

    Class<?> valueVectorClass = fieldId.getIntermediateClass();
    JClass vvClass = model.ref(valueVectorClass);
    JClass retClass = vvClass;
    String vectorAccess = "getValueVector";
    if (fieldId.isHyperReader()) {
      retClass = retClass.array();
      vectorAccess = "getValueVectors";
    }

    JVar vv = declareClassField("vv", retClass);
    JClass t = model.ref(SchemaChangeException.class);
    JType objClass = model.ref(Object.class);
    JBlock b = getSetupBlock();

    JVar fieldArr = b.decl(model.INT.array(), "fieldIds" + index++, JExpr.newArray(model.INT, fieldId.getFieldIds().length));
    int[] fieldIndices = fieldId.getFieldIds();
    for (int i = 0; i < fieldIndices.length; i++) {
       b.assign(fieldArr.component(JExpr.lit(i)), JExpr.lit(fieldIndices[i]));
    }

    JInvocation invoke = batchName
        .invoke("getValueAccessorById")
        .arg(vvClass.dotclass())
        .arg(fieldArr);

    JVar obj = b.decl(
        objClass,
        getNextVar("tmp"),
        invoke.invoke(vectorAccess));

    b._if(obj.eq(JExpr._null()))._then()._throw(JExpr._new(t).arg(JExpr.lit(
        String.format("Failure while loading vector %s with id: %s.", vv.name(), fieldId.toString()))));
    //b.assign(vv, JExpr.cast(retClass, ((JExpression) JExpr.cast(wrapperClass, obj)).invoke(vectorAccess)));
    b.assign(vv, JExpr.cast(retClass, obj));
    vvDeclaration.put(setup, vv);

    return vv;
  }

  public enum BlkCreateMode {
    /** Create new block */
    TRUE,
    /** Do not create block; put into existing block. */
    FALSE,
    /** Create new block only if # of expressions added hit upper-bound
     * ({@link ExecConstants#CODE_GEN_EXP_IN_METHOD_SIZE}). */
    TRUE_IF_BOUND
  }

  public HoldingContainer addExpr(LogicalExpression ex) {
    // default behavior is always to put expression into new block.
    return addExpr(ex, BlkCreateMode.TRUE);
  }

  public HoldingContainer addExpr(LogicalExpression ex, BlkCreateMode mode) {
    if (mode == BlkCreateMode.TRUE || mode == BlkCreateMode.TRUE_IF_BOUND) {
      rotateBlock(mode);
    }

    for (LinkedList<SizedJBlock> b : blocks) {
      b.getLast().incCounter();
    }

    return evaluationVisitor.addExpr(ex, this);
  }

  public void rotateBlock() {
    // default behavior is always to create new block.
    rotateBlock(BlkCreateMode.TRUE);
  }

  /**
   * Assigns {@link #blocks} from the last nested {@link #innerClassGenerator} to {@link this#blocks}
   * recursively if {@link #innerClassGenerator} has been created.
   */
  private void setupValidBlocks() {
    if (createNestedClass()) {
      // blocks from the last inner class should be used
      setupInnerClassBlocks();
    }
  }

  /**
   * Creates {@link #innerClassGenerator} with inner class
   * if {@link #hasMaxIndexValue()} returns {@code true}.
   *
   * @return true if splitting happened.
   */
  private boolean createNestedClass() {
    if (hasMaxIndexValue()) {
      // all new fields will be declared in the class from innerClassGenerator
      if (innerClassGenerator == null) {
        try {
          JDefinedClass innerClazz = clazz._class(JMod.NONE, clazz.name() + "0");
          innerClassGenerator = new ClassGenerator<>(codeGenerator, mappings, sig, evaluationVisitor, innerClazz, model, optionManager);
        } catch (JClassAlreadyExistsException e) {
          throw new DrillRuntimeException(e);
        }
        oldBlocks = blocks;
        innerClassGenerator.index = index;
        innerClassGenerator.maxIndex += index;
        // blocks from the inner class should be used
        setupInnerClassBlocks();
        innerClassField = clazz.field(JMod.NONE, model.ref(innerClassGenerator.clazz.name()), INNER_CLASS_FIELD_NAME);
        return true;
      }
      return innerClassGenerator.createNestedClass();
    }
    return false;
  }

  /**
   * Checks that {@link #index} has reached its max value.
   *
   * @return true if {@code index + clazz.fields().size() * 2 / 3} is greater than {@code maxIndex}
   */
  private boolean hasMaxIndexValue() {
    return index + clazz.fields().size() * 2 / 3 > maxIndex;
  }

  /**
   * Gets blocks from the last inner {@link ClassGenerator innerClassGenerator}
   * and assigns it to the {@link this#blocks} recursively.
   */
  private void setupInnerClassBlocks() {
    if (innerClassGenerator != null) {
      innerClassGenerator.setupInnerClassBlocks();
      blocks = innerClassGenerator.blocks;
    }
  }

  /**
   * Create a new code block, closing the current block.
   *
   * @param mode the {@link BlkCreateMode block create mode}
   * for the new block.
   */
  private void rotateBlock(BlkCreateMode mode) {
    boolean blockRotated = false;
    for (LinkedList<SizedJBlock> b : blocks) {
      if (mode == BlkCreateMode.TRUE ||
          (mode == BlkCreateMode.TRUE_IF_BOUND &&
            optionManager != null &&
            b.getLast().getCount() > optionManager.getOption(ExecConstants.CODE_GEN_EXP_IN_METHOD_SIZE_VALIDATOR))) {
        b.add(new SizedJBlock(new JBlock(true, true)));
        blockRotated = true;
      }
    }
    if (blockRotated) {
      evaluationVisitor.previousExpressions.clear();
      setupValidBlocks();
    }
  }

  /**
   * Creates methods from the signature {@code sig} with body from the
   * appropriate {@code blocks}.
   */
  void flushCode() {
    if (innerClassGenerator != null) {
      blocks = oldBlocks;
      innerClassGenerator.flushCode();
    }
    int i = 0;
    for (CodeGeneratorMethod method : sig) {
      JMethod outer = clazz.method(JMod.PUBLIC, model._ref(method.getReturnType()), method.getMethodName());
      for (CodeGeneratorArgument arg : method) {
        outer.param(arg.getType(), arg.getName());
      }
      for (Class<?> c : method.getThrowsIterable()) {
        outer._throws(model.ref(c));
      }
      outer._throws(SchemaChangeException.class);

      int methodIndex = 0;
      int exprsInMethod = 0;
      boolean isVoidMethod = method.getReturnType() == void.class;
      for (SizedJBlock sb : blocks[i++]) {
        JBlock b = sb.getBlock();
        if (!b.isEmpty()) {
          if (optionManager != null &&
              exprsInMethod > optionManager.getOption(ExecConstants.CODE_GEN_EXP_IN_METHOD_SIZE_VALIDATOR)) {
            JMethod inner = clazz.method(JMod.PRIVATE, model._ref(method.getReturnType()), method.getMethodName() + methodIndex);
            JInvocation methodCall = JExpr.invoke(inner);
            for (CodeGeneratorArgument arg : method) {
              inner.param(arg.getType(), arg.getName());
              methodCall.arg(JExpr.direct(arg.getName()));
            }
            for (Class<?> c : method.getThrowsIterable()) {
              inner._throws(model.ref(c));
            }
            inner._throws(SchemaChangeException.class);

            if (isVoidMethod) {
              outer.body().add(methodCall);
            } else {
              outer.body()._return(methodCall);
            }
            outer = inner;
            exprsInMethod = 0;
            ++methodIndex;
          }
          outer.body().add(b);
          exprsInMethod += sb.getCount();
        }
      }
      if (innerClassField != null) {
        // creates inner class instance and initializes innerClassField
        if (method.getMethodName().equals("__DRILL_INIT__")) {
          JInvocation rhs = JExpr._new(innerClassGenerator.clazz);
          JBlock block = new JBlock().assign(innerClassField, rhs);
          outer.body().add(block);
        }

        List<JType> argTypes = new ArrayList<>();
        for (CodeGeneratorArgument arg : method) {
          argTypes.add(model._ref(arg.getType()));
        }
        JMethod inner = innerClassGenerator.clazz.getMethod(method.getMethodName(), argTypes.toArray(new JType[0]));

        if (inner != null) {
          // removes empty method from the inner class
          if (inner.body().isEmpty()) {
            innerClassGenerator.clazz.methods().remove(inner);
            continue;
          }

          JInvocation methodCall = innerClassField.invoke(inner);
          for (CodeGeneratorArgument arg : method) {
            methodCall.arg(JExpr.direct(arg.getName()));
          }
          if (isVoidMethod) {
            outer.body().add(methodCall);
          } else {
            outer.body()._return(methodCall);
          }
        }
      }
    }

    for(ClassGenerator<T> child : innerClasses.values()) {
      child.flushCode();
    }
  }

  public JCodeModel getModel() {
    return model;
  }

  public String getNextVar() {
    return "v" + index++;
  }

  public String getNextVar(String prefix) {
    return prefix + index++;
  }

  public JVar declareClassField(String prefix, JType t) {
    return declareClassField(prefix, t, null);
  }

  public JVar declareClassField(String prefix, JType t, JExpression init) {
    if (innerClassGenerator != null && hasMaxIndexValue()) {
      return innerClassGenerator.declareClassField(prefix, t, init);
    }
    return clazz.field(JMod.NONE, t, getNextVar(prefix), init);
  }

  public Pair<Integer, JVar> declareClassConstField(String prefix, JType t,
                                                    Function<DrillBuf, ? extends ValueHolder> function) {
    return declareClassConstField(prefix, t, null, function);
  }

  /**
   * Declare a constant field for the class.
   * The class field innerClassField will be created if innerClassGenerator exists.
   *
   * @param prefix the prefix name of class field
   * @param t the type of class field
   * @param init init expression
   * @param function holds the constant value which
   * returns a value holder must be set to the class field when the class instance created.
   * @return the depth of nested class, class field
   */
  public Pair<Integer, JVar> declareClassConstField(String prefix, JType t, JExpression init,
                                                    Function<DrillBuf, ? extends ValueHolder> function) {
    JVar var;
    int depth = 1;
    if (innerClassGenerator != null) {
      Pair<Integer, JVar> nested = innerClassGenerator.declareClassConstField(prefix, t, init, function);
      depth = nested.getKey() + 1;
      var = nested.getValue();
    } else {
      var = clazz.field(JMod.NONE, t, getNextVar(prefix), init);
    }
    Pair<Integer, JVar> depthVar = Pair.of(depth, var);
    constantVars.put(depthVar, function);
    return depthVar;
  }

  public Map<Pair<Integer, JVar>, Function<DrillBuf, ? extends ValueHolder>> getConstantVars() {
    return constantVars;
  }

  public HoldingContainer declare(MajorType t) {
    return declare(t, true);
  }

  public HoldingContainer declare(MajorType t, boolean includeNewInstance) {
    return declare(t, "out", includeNewInstance);
  }

  /**
   * Adds a local variable declaration based on given name and type.
   *
   * @param t major type
   * @param name variable name
   * @param includeNewInstance whether to create new instance
   * @return holder instance
   */
  public HoldingContainer declare(MajorType t, String name, boolean includeNewInstance) {
    JType holderType = getHolderType(t);
    JVar var;
    if (includeNewInstance) {
      var = getEvalBlock().decl(holderType, getNextVar(name), JExpr._new(holderType));
    } else {
      var = getEvalBlock().decl(holderType, getNextVar(name));
    }
    JFieldRef outputSet = null;
    if (t.getMode() == DataMode.OPTIONAL) {
      outputSet = var.ref("isSet");
    }
    return new HoldingContainer(t, var, var.ref("value"), outputSet);
  }

  public List<TypedFieldId> getWorkspaceTypes() {
    return workspaceTypes;
  }

  public Map<WorkspaceReference, JVar> getWorkspaceVectors() {
    return workspaceVectors;
  }

  /**
   * Prepare the generated class for use as a plain-old Java class
   * (to be compiled by a compiler and directly loaded without a
   * byte-code merge. Three additions are necessary:
   * <ul>
   * <li>The class must extend its template as we won't merge byte
   * codes.</li>
   * <li>A constructor is required to call the <tt>__DRILL_INIT__</tt>
   * method. If this is a nested class, then the constructor must
   * include parameters defined by the base class.</li>
   * <li>For each nested class, create a method that creates an
   * instance of that nested class using a well-defined name. This
   * method overrides the base class method defined for this purpose.</li>
   */
  public void preparePlainJava() {

    // If this generated class uses the "straight Java" technique
    // (no byte code manipulation), then the class must extend the
    // template so it plays by normal Java rules for finding the
    // template methods via inheritance rather than via code injection.

    Class<?> baseClass = sig.getSignatureClass();
    clazz._extends(baseClass);

    // Create a constuctor for the class: either a default one,
    // or (for nested classes) one that passes along arguments to
    // the super class constructor.

    Constructor<?>[] ctors = baseClass.getConstructors();
    for (Constructor<?> ctor : ctors) {
      addCtor(ctor.getParameterTypes());
    }

    // Some classes have no declared constructor, but we need to generate one
    // anyway.

    if ( ctors.length == 0 ) {
      addCtor( new Class<?>[] {} );
    }

    // Repeat for inner classes.

    for(ClassGenerator<T> child : innerClasses.values()) {
      child.preparePlainJava();

      // If there are inner classes, then we need to generate a "shim" method
      // to instantiate that class.
      //
      // protected TemplateClass.TemplateInnerClass newTemplateInnerClass( args... ) {
      //    return new GeneratedClass.GeneratedInnerClass( args... );
      // }
      //
      // The name is special, it is "new" + inner class name. The template must
      // provide a method of this name that creates the inner class instance.

      String innerClassName = child.clazz.name();
      JMethod shim = clazz.method(JMod.PROTECTED, child.sig.getSignatureClass(), "new" + innerClassName);
      JInvocation childNew = JExpr._new(child.clazz);
      Constructor<?>[] childCtors = child.sig.getSignatureClass().getConstructors();
      Class<?>[] params;
      if (childCtors.length==0) {
        params = new Class<?>[0];
      } else {
        params = childCtors[0].getParameterTypes();
      }
      for (int i = 1; i < params.length; i++) {
        Class<?> p = params[i];
        childNew.arg(shim.param(model._ref(p), "arg" + i));
      }
      shim.body()._return(JExpr._this().invoke("injectMembers").arg(childNew));
    }
  }

  /**
   * The code generator creates a method called __DRILL_INIT__ which takes the
   * place of the constructor when the code goes though the byte code merge.
   * For Plain-old Java, we call the method from a constructor created for
   * that purpose. (Generated code, fortunately, never includes a constructor,
   * so we can create one.) Since the init block throws an exception (which
   * should never occur), the generated constructor converts the checked
   * exception into an unchecked one so as to not require changes to the
   * various places that create instances of the generated classes.
   *
   * Example:<code><pre>
   * public StreamingAggregatorGen1() {
   *       try {
   *         __DRILL_INIT__();
   *     } catch (SchemaChangeException e) {
   *         throw new UnsupportedOperationException(e);
   *     }
   * }</pre></code>
   *
   * Note: in Java 8 we'd use the <tt>Parameter</tt> class defined in Java's
   * introspection package. But, Drill prefers Java 7 which only provides
   * parameter types.
   */
  private void addCtor(Class<?>[] parameters) {
    JMethod ctor = clazz.constructor(JMod.PUBLIC);
    JBlock body = ctor.body();

    // If there are parameters, need to pass them to the super class.
    if (parameters.length > 0) {
      JInvocation superCall = JExpr.invoke("super");

      // This case only occurs for nested classes, and all nested classes
      // in Drill are inner classes. Don't pass along the (hidden)
      // this$0 field.

      for (int i = 1; i < parameters.length; i++) {
        Class<?> p = parameters[i];
        superCall.arg(ctor.param(model._ref(p), "arg" + i));
      }
      body.add(superCall);
    }
    JTryBlock tryBlock = body._try();
    tryBlock.body().invoke(SignatureHolder.DRILL_INIT_METHOD);
    JCatchBlock catchBlock = tryBlock._catch(model.ref(SchemaChangeException.class));
    catchBlock.body()._throw(JExpr._new(model.ref(UnsupportedOperationException.class)).arg(catchBlock.param("e")));
  }

  private static class ValueVectorSetup {
    final DirectExpression batch;
    final TypedFieldId fieldId;

    public ValueVectorSetup(DirectExpression batch, TypedFieldId fieldId) {
      super();
      this.batch = batch;
      this.fieldId = fieldId;
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((batch == null) ? 0 : batch.hashCode());
      result = prime * result + ((fieldId == null) ? 0 : fieldId.hashCode());
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj) {
        return true;
      }
      if (obj == null) {
        return false;
      }
      if (getClass() != obj.getClass()) {
        return false;
      }
      ValueVectorSetup other = (ValueVectorSetup) obj;
      if (batch == null) {
        if (other.batch != null) {
          return false;
        }
      } else if (!batch.equals(other.batch)) {
        return false;
      }
      if (fieldId == null) {
        if (other.fieldId != null) {
          return false;
        }
      } else if (!fieldId.equals(other.fieldId)) {
        return false;
      }
      return true;
    }
  }

  /**
   * Represents a (Nullable)?(Type)Holder instance. Allows code
   * gen to declare, set, work with and retrieve values from a holder.
   * Holders exploit scalar replacement in Drill (or in Java): that
   * the holder can, via code rewrites, be replaced by scalars that
   * do the same job.
   */
  // TODO: Might be better modeled as a set of classes for the special
  // kinds of holders rather than a generic class and many if-statements.
  public static class HoldingContainer {
    private final JVar holder;
    private final JFieldRef value;
    private final JFieldRef isSet;
    private final MajorType type;
    private boolean isConstant;
    private final boolean singularRepeated;
    private final boolean isReader;

    public HoldingContainer(MajorType t, JVar holder, JFieldRef value, JFieldRef isSet) {
      this(t, holder, value, isSet, false, false);
    }

    public HoldingContainer(MajorType t, JVar holder, JFieldRef value, JFieldRef isSet, boolean singularRepeated, boolean isReader) {
      this.holder = holder;
      this.value = value;
      this.isSet = isSet;
      this.type = t;
      this.isConstant = false;
      this.singularRepeated = singularRepeated;
      this.isReader = isReader;
    }

    public HoldingContainer(HoldingContainer from) {
      this.holder = from.holder;
      this.value =from. value;
      this.isSet = from.isSet;
      this.type = from.type;
      this.isConstant = from.isConstant;
      this.singularRepeated = from.singularRepeated;
      this.isReader = from.isReader;
    }

    public boolean isReader() {
      return isReader;
    }

    public boolean isSingularRepeated() {
      return singularRepeated;
    }

    public HoldingContainer setConstant(boolean isConstant) {
      this.isConstant = isConstant;
      return this;
    }

    public JFieldRef f(String name) {
      return holder.ref(name);
    }

    public boolean isConstant() {
      return isConstant;
    }

    public JVar getHolder() {
      return holder;
    }

    public JFieldRef getValue() {
      return value;
    }

    public MajorType getMajorType() {
      return type;
    }

    public JFieldRef getIsSet() {
      Preconditions.checkNotNull(isSet,
          "You cannot access the isSet variable when operating on a non-nullable output value.");
      return isSet;
    }

    public boolean isOptional() {
      return type.getMode() == DataMode.OPTIONAL;
    }

    public boolean isRepeated() {
      return type.getMode() == DataMode.REPEATED;
    }

    public TypeProtos.MinorType getMinorType() {
      return type.getMinorType();
    }

    /**
     * Convert holder to a string for debugging use.
     */
    @Override
    public String toString() {
      DebugStringBuilder buf = new DebugStringBuilder(this);
      if (isConstant()) {
        buf.append("const ");
      }
      buf.append(holder.type().name())
        .append(" ")
        .append(holder.name())
        .append(", ")
        .append(type.getMode().name())
        .append(" ")
        .append(type.getMinorType().name())
        .append(", ");
      holder.generate(buf.formatter());
      if (value != null) {
        buf.append(", ");
        value.generate(buf.formatter());
      }
      return buf.toString();
    }
  }

  public JType getHolderType(MajorType t) {
    return TypeHelper.getHolderType(model, t.getMinorType(), t.getMode());
  }
}
