/**
* 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.hadoop.yarn.webapp.hamlet;

import com.google.common.collect.Sets;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Locale;
import java.util.Set;
import java.util.regex.Pattern;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.hadoop.yarn.webapp.WebAppException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Generates a specific hamlet implementation class from a spec class
 * using a generic hamlet implementation class.
 */
public class HamletGen {
  static final Logger LOG = LoggerFactory.getLogger(HamletGen.class);
  static final Options opts = new Options();
  static {
    opts.addOption("h", "help", false, "Print this help message").
         addOption("s", "spec-class", true,
                   "The class that holds the spec interfaces. e.g. HamletSpec").
         addOption("i", "impl-class", true,
                   "An implementation class. e.g. HamletImpl").
         addOption("o", "output-class", true, "Output class name").
         addOption("p", "output-package", true, "Output package name");
  };

  static final Pattern elementRegex = Pattern.compile("^[A-Z][A-Z0-9]*$");

  int bytes = 0;
  PrintWriter out;
  final Set<String> endTagOptional = Sets.newHashSet();
  final Set<String> inlineElements = Sets.newHashSet();
  Class<?> top; // html top-level interface
  String hamlet; // output class simple name;
  boolean topMode;

  /**
   * Generate a specific Hamlet implementation from a spec.
   * @param specClass holds hamlet interfaces. e.g. {@link HamletSpec}
   * @param implClass a generic hamlet implementation. e.g. {@link HamletImpl}
   * @param outputName name of the output class. e.g. {@link Hamlet}
   * @param outputPkg package name of the output class.
   * @throws IOException
   */
  public void generate(Class<?> specClass, Class<?> implClass,
                       String outputName, String outputPkg) throws IOException {
    LOG.info("Generating {} using {} and {}", new Object[]{outputName,
             specClass, implClass});
    out = new PrintWriter(outputName +".java", "UTF-8");
    hamlet = basename(outputName);
    String pkg = pkgName(outputPkg, implClass.getPackage().getName());
    puts(0, "// Generated by HamletGen. Do NOT edit!\n",
         "package ", pkg, ";\n",
         "import java.io.PrintWriter;\n",
         "import java.util.EnumSet;\n",
         "import static java.util.EnumSet.*;\n",
         "import static ", implClass.getName(), ".EOpt.*;\n",
         "import org.apache.hadoop.yarn.webapp.SubView;");
    String implClassName = implClass.getSimpleName();
    if (!implClass.getPackage().getName().equals(pkg)) {
      puts(0, "import ", implClass.getName(), ';');
    }
    puts(0, "\n",
         "public class ", hamlet, " extends ", implClassName,
         " implements ", specClass.getSimpleName(), "._Html {\n",
         "  public ", hamlet, "(PrintWriter out, int nestLevel,",
         " boolean wasInline) {\n",
         "    super(out, nestLevel, wasInline);\n",
         "  }\n\n", // inline is context sensitive
         "  static EnumSet<EOpt> opt(boolean endTag, boolean inline, ",
         "boolean pre) {\n",
         "    EnumSet<EOpt> opts = of(ENDTAG);\n",
         "    if (!endTag) opts.remove(ENDTAG);\n",
         "    if (inline) opts.add(INLINE);\n",
         "    if (pre) opts.add(PRE);\n",
         "    return opts;\n",
         "  }");
    initLut(specClass);
    genImpl(specClass, implClassName, 1);
    LOG.info("Generating {} methods", hamlet);
    genMethods(hamlet, top, 1);
    puts(0, "}");
    out.close();
    LOG.info("Wrote {} bytes to {}.java", bytes, outputName);
  }

  String basename(String path) {
    return path.substring(path.lastIndexOf('/') + 1);
  }

  String pkgName(String pkg, String defaultPkg) {
    if (pkg == null || pkg.isEmpty()) return defaultPkg;
    return pkg;
  }

  void initLut(Class<?> spec) {
    endTagOptional.clear();
    inlineElements.clear();
    for (Class<?> cls : spec.getClasses()) {
      Annotation a = cls.getAnnotation(HamletSpec.Element.class);
      if (a != null && !((HamletSpec.Element) a).endTag()) {
        endTagOptional.add(cls.getSimpleName());
      }
      if (cls.getSimpleName().equals("Inline")) {
        for (Method method : cls.getMethods()) {
          String retName = method.getReturnType().getSimpleName();
          if (isElement(retName)) {
            inlineElements.add(retName);
          }
        }
      }
    }
  }

  void genImpl(Class<?> spec, String implClassName, int indent) {
    String specName = spec.getSimpleName();
    for (Class<?> cls : spec.getClasses()) {
      String className = cls.getSimpleName();
      if (cls.isInterface()) {
        genFactoryMethods(cls, indent);
      }
      if (isElement(className)) {
        LOG.info("Generating class {}<T>", className);
        puts(indent, "\n",
             "public class ", className, "<T extends _>",
             " extends EImp<T> implements ", specName, ".", className, " {\n",
             "  public ", className, "(String name, T parent,",
             " EnumSet<EOpt> opts) {\n",
             "    super(name, parent, opts);\n",
             "  }");
        genMethods(className, cls, indent + 1);
        puts(indent, "}");
      } else if (className.equals("_Html")) {
        top = cls;
      }
    }
  }

  void genFactoryMethods(Class<?> cls, int indent) {
    for (Method method : cls.getDeclaredMethods()) {
      String retName = method.getReturnType().getSimpleName();
      String methodName = method.getName();
      if (methodName.charAt(0) == '$') continue;
      if (isElement(retName) && method.getParameterTypes().length == 0) {
        genFactoryMethod(retName, methodName, indent);
      }
    }
  }

  void genMethods(String className, Class<?> cls, int indent) {
    topMode = (top != null && cls.equals(top));
    for (Method method : cls.getMethods()) {
      String retName = method.getReturnType().getSimpleName();
      if (method.getName().charAt(0) == '$') {
        genAttributeMethod(className, method, indent);
      } else if (isElement(retName)) {
        genNewElementMethod(className, method, indent);
      } else {
        genCurElementMethod(className, method, indent);
      }
    }
  }

  void genAttributeMethod(String className, Method method, int indent) {
    String methodName = method.getName();
    String attrName = methodName.substring(1).replace('_', '-');
    Type[] params = method.getGenericParameterTypes();
    echo(indent, "\n",
         "@Override\n",
         "public ", className, topMode ? " " : "<T> ", methodName, "(");
    if (params.length == 0) {
      puts(0, ") {");
      puts(indent,
           "  addAttr(\"", attrName, "\", null);\n",
           "  return this;\n", "}");
    } else if (params.length == 1) {
      String typeName = getTypeName(params[0]);
      puts(0, typeName, " value) {");
      if (typeName.equals("EnumSet<LinkType>")) {
        puts(indent,
             "  addRelAttr(\"", attrName, "\", value);\n",
             "  return this;\n", "}");
      } else if (typeName.equals("EnumSet<Media>")) {
        puts(indent,
             "  addMediaAttr(\"", attrName, "\", value);\n",
             "  return this;\n", "}");
      } else {
        puts(indent,
             "  addAttr(\"", attrName, "\", value);\n",
             "  return this;\n", "}");
      }
    } else {
      throwUnhandled(className, method);
    }
  }

  String getTypeName(Type type) {
    if (type instanceof Class<?>) {
      return ((Class<?>)type).getSimpleName();
    }
    ParameterizedType pt = (ParameterizedType) type;
    return ((Class<?>)pt.getRawType()).getSimpleName() +"<"+
        ((Class<?>)pt.getActualTypeArguments()[0]).getSimpleName() +">";
  }

  void genFactoryMethod(String retName, String methodName, int indent) {
    puts(indent, "\n",
         "private <T extends _> ", retName, "<T> ", methodName,
         "_(T e, boolean inline) {\n",
         "  return new ", retName, "<T>(\"", retName.toLowerCase(Locale.US),
         "\", e, opt(", !endTagOptional.contains(retName), ", inline, ",
         retName.equals("PRE"), ")); }");
  }

  void genNewElementMethod(String className, Method method, int indent) {
    String methodName = method.getName();
    String retName = method.getReturnType().getSimpleName();
    Class<?>[] params = method.getParameterTypes();
    echo(indent, "\n",
         "@Override\n",
         "public ", retName, "<", className, topMode ? "> " : "<T>> ",
         methodName, "(");
    if (params.length == 0) {
      puts(0, ") {");
      puts(indent,
           topMode ? "" : "  closeAttrs();\n",
           "  return ", retName.toLowerCase(Locale.US), "_(this, ",
           isInline(className, retName), ");\n", "}");
    } else if (params.length == 1) {
      puts(0, "String selector) {");
      puts(indent,
           "  return setSelector(", methodName, "(), selector);\n", "}");
    } else {
      throwUnhandled(className, method);
    }
  }

  boolean isInline(String container, String className) {
    if ((container.equals("BODY") || container.equals(hamlet) ||
         container.equals("HEAD") || container.equals("HTML")) &&
        (className.equals("INS") || className.equals("DEL") ||
         className.equals("SCRIPT"))) {
      return false;
    }
    return inlineElements.contains(className);
  }

  void genCurElementMethod(String className, Method method, int indent) {
    String methodName = method.getName();
    Class<?>[] params = method.getParameterTypes();
    if (topMode || params.length > 0) {
      echo(indent, "\n",
         "@Override\n",
         "public ", className, topMode ? " " : "<T> ", methodName, "(");
    }
    if (params.length == 0) {
      if (topMode) {
        puts(0, ") {");
        puts(indent, "  return this;\n", "}");
      }
    } else if (params.length == 1) {
      if (methodName.equals("base")) {
        puts(0, "String href) {");
        puts(indent,
             "  return base().$href(href)._();\n", "}");
      } else if (methodName.equals("script")) {
        puts(0, "String src) {");
        puts(indent,
             "  return setScriptSrc(script(), src)._();\n", "}");
      } else if (methodName.equals("style")) {
        puts(0, "Object... lines) {");
        puts(indent,
             "  return style().$type(\"text/css\")._(lines)._();\n", "}");
      } else if (methodName.equals("img")) {
        puts(0, "String src) {");
        puts(indent,
             "  return ", methodName, "().$src(src)._();\n", "}");
      } else if (methodName.equals("br") || methodName.equals("hr") ||
                 methodName.equals("col")) {
        puts(0, "String selector) {");
        puts(indent,
             "  return setSelector(", methodName, "(), selector)._();\n", "}");
      }  else if (methodName.equals("link")) {
        puts(0, "String href) {");
        puts(indent,
             "  return setLinkHref(", methodName, "(), href)._();\n", "}");
      } else if (methodName.equals("_")) {
        if (params[0].getSimpleName().equals("Class")) {
          puts(0, "Class<? extends SubView> cls) {");
          puts(indent,
               "  ", topMode ? "subView" : "_v", "(cls);\n",
               "  return this;\n", "}");
        } else {
          puts(0, "Object... lines) {");
          puts(indent,
               "  _p(", needsEscaping(className), ", lines);\n",
               "  return this;\n", "}");
        }
      } else if (methodName.equals("_r")) {
        puts(0, "Object... lines) {");
        puts(indent,
             "  _p(false, lines);\n",
             "  return this;\n", "}");
      } else {
        puts(0, "String cdata) {");
        puts(indent,
             "  return ", methodName, "()._(cdata)._();\n", "}");
      }
    } else if (params.length == 2) {
      if (methodName.equals("meta")) {
        puts(0, "String name, String content) {");
        puts(indent,
             "  return meta().$name(name).$content(content)._();\n", "}");
      } else if (methodName.equals("meta_http")) {
        puts(0, "String header, String content) {");
        puts(indent,
             "  return meta().$http_equiv(header).$content(content)._();\n",
             "}");
      } else if (methodName.equals("a")) {
        puts(0, "String href, String anchorText) {");
        puts(indent,
             "  return a().$href(href)._(anchorText)._();\n", "}");
      } else if (methodName.equals("bdo")) {
        puts(0, "Dir dir, String cdata) {");
        puts(indent, "  return bdo().$dir(dir)._(cdata)._();\n", "}");
      } else if (methodName.equals("label")) {
        puts(0, "String forId, String cdata) {");
        puts(indent, "  return label().$for(forId)._(cdata)._();\n", "}");
      } else if (methodName.equals("param")) {
        puts(0, "String name, String value) {");
        puts(indent,
             "  return param().$name(name).$value(value)._();\n", "}");
      } else {
        puts(0, "String selector, String cdata) {");
        puts(indent,
             "  return setSelector(", methodName,
             "(), selector)._(cdata)._();\n", "}");
      } 
    } else if (params.length == 3) {
      if (methodName.equals("a")) {
        puts(0, "String selector, String href, String anchorText) {");
        puts(indent,
             "  return setSelector(a(), selector)",
             ".$href(href)._(anchorText)._();\n", "}");
      }
    } else {
      throwUnhandled(className, method);
    }
  }

  static boolean needsEscaping(String eleName) {
    return !eleName.equals("SCRIPT") && !eleName.equals("STYLE");
  }

  static void throwUnhandled(String className, Method method) {
    throw new WebAppException("Unhandled " + className + "#" + method);
  }

  void echo(int indent, Object... args) {
    String prev = null;
    for (Object o : args) {
      String s = String.valueOf(o);
      if (!s.isEmpty() && !s.equals("\n") &&
          (prev == null || prev.endsWith("\n"))) {
        indent(indent);
      }
      prev = s;
      out.print(s);
      bytes += s.length();
    }
  }

  void indent(int indent) {
    for (int i = 0; i < indent; ++i) {
      out.print("  ");
      bytes += 2;
    }
  }

  void puts(int indent, Object... args) {
    echo(indent, args);
    out.println();
    ++bytes;
  }

  boolean isElement(String s) {
    return elementRegex.matcher(s).matches();
  }

  public static void main(String[] args) throws Exception {
    CommandLine cmd = new GnuParser().parse(opts, args);
    if (cmd.hasOption("help")) {
      new HelpFormatter().printHelp("Usage: hbgen [OPTIONS]", opts);
      return;
    }
    // defaults
    Class<?> specClass = HamletSpec.class;
    Class<?> implClass = HamletImpl.class;
    String outputClass = "HamletTmp";
    String outputPackage = implClass.getPackage().getName();
    if (cmd.hasOption("spec-class")) {
      specClass = Class.forName(cmd.getOptionValue("spec-class"));
    }
    if (cmd.hasOption("impl-class")) {
      implClass = Class.forName(cmd.getOptionValue("impl-class"));
    }
    if (cmd.hasOption("output-class")) {
      outputClass = cmd.getOptionValue("output-class");
    }
    if (cmd.hasOption("output-package")) {
      outputPackage = cmd.getOptionValue("output-package");
    }
    new HamletGen().generate(specClass, implClass, outputClass, outputPackage);
  }
}
