/*
 * 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 java.io.IOException;

import org.apache.drill.exec.compile.TemplateClassDefinition;
import org.apache.drill.exec.compile.sig.MappingSet;
import org.apache.drill.exec.server.options.OptionSet;

import com.google.common.base.Preconditions;
import com.sun.codemodel.JClassAlreadyExistsException;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JDefinedClass;

/**
 * A code generator is responsible for generating the Java source code required
 * to complete the implementation of an abstract template.
 * A code generator can contain one or more ClassGenerators that implement
 * outer and inner classes associated with a particular runtime generated instance.
 * <p>
 * Drill supports two ways to generate and compile the code from a code
 * generator: via byte-code manipulations or as "plain Java."
 * <p>
 * When using byte-code transformations, the code generator is used with a
 * class transformer to merge precompiled template code with runtime generated and
 * compiled query specific code to create a runtime instance.
 * <p>
 * The code generator can optionally be marked as "plain Java" capable.
 * This means that the generated code can be compiled directly as a Java
 * class without the normal byte-code manipulations. Plain Java allows
 * the option to persist, and debug, the generated code when building new
 * generated classes or otherwise working with generated code. To turn
 * on debugging, see the explanation in {@link org.apache.drill.exec.compile.ClassBuilder}.
 *
 * @param <T>
 *          The interface that results from compiling and merging the runtime
 *          code that is generated.
 */

public class CodeGenerator<T> {

  private static final String PACKAGE_NAME = "org.apache.drill.exec.test.generated";

  private final TemplateClassDefinition<T> definition;
  private final String className;
  private final String fqcn;

  private final JCodeModel model;
  private final ClassGenerator<T> rootGenerator;

  /**
   * True if the code generated for this class is suitable for compilation
   * as a plain Java class.
   */

  private boolean plainJavaCapable;

  /**
   * True if the code generated for this class should actually be compiled
   * via the plain Java mechanism. Considered only if the class is
   * capable of this technique.
   */

  private boolean usePlainJava;

  /**
   * Whether to write code to disk to aid in debugging. Should only be set
   * during development, never in production.
   */

  private boolean saveDebugCode;
  private String generatedCode;
  private String generifiedCode;

  CodeGenerator(TemplateClassDefinition<T> definition, OptionSet optionManager) {
    this(ClassGenerator.getDefaultMapping(), definition, optionManager);
  }

  CodeGenerator(MappingSet mappingSet, TemplateClassDefinition<T> definition, OptionSet optionManager) {
    Preconditions.checkNotNull(definition.getSignature(),
        "The signature for defintion %s was incorrectly initialized.", definition);
    this.definition = definition;
    this.className = definition.getExternalInterface().getSimpleName() + "Gen" + definition.getNextClassNumber();
    this.fqcn = PACKAGE_NAME + "." + className;
    try {
      this.model = new JCodeModel();
      JDefinedClass clazz = model._package(PACKAGE_NAME)._class(className);
      rootGenerator = new ClassGenerator<>(this, mappingSet,
        definition.getSignature(), new EvaluationVisitor(),
        clazz, model, optionManager);
    } catch (JClassAlreadyExistsException e) {
      throw new IllegalStateException(e);
    }
  }

  /**
   * Indicates that the code for this class can be generated using the
   * "Plain Java" mechanism based on inheritance. The byte-code
   * method is more lenient, so some code is missing some features such
   * as proper exception labeling, etc. Set this option to true once
   * the generation mechanism for a class has been cleaned up to work
   * via the plain Java mechanism.
   *
   * @param flag true if the code generated from this instance is
   * ready to be compiled as a plain Java class
   */

  public void plainJavaCapable(boolean flag) {
    plainJavaCapable = flag;
  }

  /**
   * Identifies that this generated class should be generated via the
   * plain Java mechanism. This flag only has meaning if the
   * generated class is capable of plain Java generation.
   *
   * @param flag true if the class should be generated and compiled
   * as a plain Java class (rather than via byte-code manipulations)
   */

  public void preferPlainJava(boolean flag) {
    usePlainJava = flag;
  }

  public boolean supportsPlainJava() {
    return plainJavaCapable;
  }

  public boolean isPlainJava() {
    return plainJavaCapable && usePlainJava;
  }

  /**
   * Debug-time option to persist the code for the generated class to permit debugging.
   * Has effect only when code is generated using the plain Java option. Code
   * is written to the code directory specified in {@link org.apache.drill.exec.compile.ClassBuilder}.
   * To debug code, set this option, then point your IDE to the code directory
   * when the IDE prompts you for the source code location.
   *
   * @param persist true to write the code to disk, false (the default) to keep
   * code only in memory.
   */
  public void saveCodeForDebugging(boolean persist) {
    if (supportsPlainJava()) {
      saveDebugCode = persist;
      usePlainJava = true;
    }
  }

  public boolean isCodeToBeSaved() {
     return saveDebugCode;
  }

  public ClassGenerator<T> getRoot() {
    return rootGenerator;
  }

  public void generate() {

    // If this generated class uses the "plain 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.

    if (isPlainJava()) {
      rootGenerator.preparePlainJava( );
    }

    rootGenerator.flushCode();

    SingleClassStringWriter w = new SingleClassStringWriter();
    try {
      model.build(w);
    } catch (IOException e) {
      // No I/O errors should occur during model building
      // unless something is terribly wrong.
      throw new IllegalStateException(e);
    }

    generatedCode = w.getCode().toString();
    generifiedCode = generatedCode.replaceAll(className, "GenericGenerated");
  }

  public String generateAndGet() throws IOException {
    generate();
    return generatedCode;
  }

  public String getGeneratedCode() {
    return generatedCode;
  }

  public TemplateClassDefinition<T> getDefinition() {
    return definition;
  }

  public String getMaterializedClassName() {
    return fqcn;
  }

  public String getClassName() { return className; }

  public static <T> CodeGenerator<T> get(TemplateClassDefinition<T> definition) {
    return get(definition, null);
  }

  public static <T> CodeGenerator<T> get(TemplateClassDefinition<T> definition, OptionSet optionManager) {
    return new CodeGenerator<T>(definition, optionManager);
  }

  public static <T> ClassGenerator<T> getRoot(TemplateClassDefinition<T> definition, OptionSet optionManager) {
    return get(definition, optionManager).getRoot();
  }

  public static <T> ClassGenerator<T> getRoot(MappingSet mappingSet, TemplateClassDefinition<T> definition, OptionSet optionManager) {
    return get(mappingSet, definition, optionManager).getRoot();
  }

  public static <T> CodeGenerator<T> get(MappingSet mappingSet, TemplateClassDefinition<T> definition, OptionSet optionManager) {
    return new CodeGenerator<T>(mappingSet, definition, optionManager);
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((definition == null) ? 0 : definition.hashCode());
    result = prime * result + ((generifiedCode == null) ? 0 : generifiedCode.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;
    }
    CodeGenerator<?> other = (CodeGenerator<?>) obj;
    if (definition == null) {
      if (other.definition != null){
        return false;
      }
    } else if (!definition.equals(other.definition)) {
      return false;
    }
    if (generifiedCode == null) {
      if (other.generifiedCode != null){
        return false;
      }

    } else if (!generifiedCode.equals(other.generifiedCode)) {
      return false;
    }
    return true;
  }
}
