/*
 * Copyright 2008 Google Inc.
 *
 * Licensed 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 com.google.gwt.sample.showcase.generator;

import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.sample.showcase.client.ContentWidget;
import com.google.gwt.sample.showcase.client.Showcase;
import com.google.gwt.sample.showcase.client.ShowcaseConstants;
import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseData;
import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseRaw;
import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseSource;
import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseStyle;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * Generate the source code, css styles, and raw source used in the Showcase
 * examples.
 */
public class ShowcaseGenerator extends Generator {
  /**
   * The paths to the CSS style sheets used in Showcase. The paths are relative
   * to the root path of the {@link ClassLoader}. The variable $THEME will be
   * replaced by the current theme. The variable $RTL will be replaced by "_rtl"
   * for RTL locales.
   */
  private static final String[] SRC_CSS = {
      "com/google/gwt/user/theme/$THEME/public/gwt/$THEME/$THEME$RTL.css",
      "com/google/gwt/sample/showcase/client/Showcase.css"};

  /**
   * The class loader used to get resources.
   */
  private ClassLoader classLoader = null;

  /**
   * The generator context.
   */
  private GeneratorContext context = null;

  /**
   * The {@link TreeLogger} used to log messages.
   */
  private TreeLogger logger = null;

  /**
   * The set of raw files that have already been generated. Raw files can be
   * reused by different examples, but we only generate them once.
   */
  private Set<String> rawFiles = new HashSet<String>();

  @Override
  public String generate(
      TreeLogger logger, GeneratorContext context, String typeName)
      throws UnableToCompleteException {
    this.logger = logger;
    this.context = context;
    this.classLoader = Thread.currentThread().getContextClassLoader();

    // Only generate files on the first permutation
    if (!isFirstPass()) {
      return null;
    }

    // Get the Showcase ContentWidget subtypes to examine
    JClassType cwType = null;
    try {
      cwType = context.getTypeOracle().getType(ContentWidget.class.getName());
    } catch (NotFoundException e) {
      logger.log(TreeLogger.ERROR, "Cannot find ContentWidget class", e);
      throw new UnableToCompleteException();
    }
    JClassType[] types = cwType.getSubtypes();

    // Generate the source and raw source files
    for (JClassType type : types) {
      generateRawFiles(type);
      generateSourceFiles(type);
    }

    // Generate the CSS source files
    String[] themes = new String[]{Showcase.THEME};
    for (String theme : themes) {
      String styleDefsLTR = getStyleDefinitions(theme, false);
      String styleDefsRTL = getStyleDefinitions(theme, true);
      String outDirLTR = ShowcaseConstants.DST_SOURCE_STYLE + theme + "/";
      String outDirRTL = ShowcaseConstants.DST_SOURCE_STYLE + theme + "_rtl/";
      for (JClassType type : types) {
        generateStyleFiles(type, styleDefsLTR, outDirLTR);
        generateStyleFiles(type, styleDefsRTL, outDirRTL);
      }
    }

    return null;
  }

  /**
   * Set the full contents of a resource in the public directory.
   *
   * @param partialPath the path to the file relative to the public directory
   * @param contents the file contents
   */
  private void createPublicResource(String partialPath, String contents)
      throws UnableToCompleteException {
    try {
      OutputStream outStream = context.tryCreateResource(logger, partialPath);
      if (outStream == null) {
        String message = "Attempting to generate duplicate public resource: "
            + partialPath
            + ".\nAll generated source files must have unique names.";
        logger.log(TreeLogger.ERROR, message);
        throw new UnableToCompleteException();
      }
      outStream.write(contents.getBytes());
      context.commitResource(logger, outStream);
    } catch (IOException e) {
      logger.log(TreeLogger.ERROR, "Error writing file: " + partialPath, e);
      throw new UnableToCompleteException();
    }
  }

  /**
   * Generate the raw files used by a {@link ContentWidget}.
   *
   * @param type the {@link ContentWidget} subclass
   */
  private void generateRawFiles(JClassType type)
      throws UnableToCompleteException {
    // Look for annotation
    if (!type.isAnnotationPresent(ShowcaseRaw.class)) {
      return;
    }

    // Get the package info
    String pkgName = type.getPackage().getName();
    String pkgPath = pkgName.replace('.', '/') + "/";

    // Generate each raw source file
    String[] filenames = type.getAnnotation(ShowcaseRaw.class).value();
    for (String filename : filenames) {
      // Check if the file has already been generated.
      String path = pkgName + filename;
      if (rawFiles.contains(path)) {
        continue;
      }
      rawFiles.add(path);

      // Get the file contents
      String fileContents = getResourceContents(pkgPath + filename);

      // Make the source pretty
      fileContents = fileContents.replace("<", "&lt;");
      fileContents = fileContents.replace(">", "&gt;");
      fileContents = fileContents.replace("* \n   */\n", "*/\n");
      fileContents = "<pre>" + fileContents + "</pre>";

      // Save the raw source in the public directory
      String dstPath = ShowcaseConstants.DST_SOURCE_RAW + filename + ".html";
      createPublicResource(dstPath, fileContents);
    }
  }

  /**
   * Generate the formatted source code for a {@link ContentWidget}.
   *
   * @param type the {@link ContentWidget} subclass
   */
  private void generateSourceFiles(JClassType type)
      throws UnableToCompleteException {
    // Get the file contents
    String filename = type.getQualifiedSourceName().replace('.', '/') + ".java";
    String fileContents = getResourceContents(filename);

    // Get each data code block
    String formattedSource = "";
    String dataTag = "@" + ShowcaseData.class.getSimpleName();
    String sourceTag = "@" + ShowcaseSource.class.getSimpleName();
    int dataTagIndex = fileContents.indexOf(dataTag);
    int srcTagIndex = fileContents.indexOf(sourceTag);
    while (dataTagIndex >= 0 || srcTagIndex >= 0) {
      if (dataTagIndex >= 0
          && (dataTagIndex < srcTagIndex || srcTagIndex < 0)) {
        // Get the boundaries of a DATA tag
        int beginIndex = fileContents.lastIndexOf("  /*", dataTagIndex);
        int beginTagIndex = fileContents.lastIndexOf("\n", dataTagIndex) + 1;
        int endTagIndex = fileContents.indexOf("\n", dataTagIndex) + 1;
        int endIndex = fileContents.indexOf(";", beginIndex) + 1;

        // Add to the formatted source
        String srcData = fileContents.substring(beginIndex, beginTagIndex)
            + fileContents.substring(endTagIndex, endIndex);
        formattedSource += srcData + "\n\n";

        // Get next tag
        dataTagIndex = fileContents.indexOf(dataTag, endIndex + 1);
      } else {
        // Get the boundaries of a SRC tag
        int beginIndex = fileContents.lastIndexOf("/*", srcTagIndex) - 2;
        int beginTagIndex = fileContents.lastIndexOf("\n", srcTagIndex) + 1;
        int endTagIndex = fileContents.indexOf("\n", srcTagIndex) + 1;
        int endIndex = fileContents.indexOf("\n  }", beginIndex) + 4;

        // Add to the formatted source
        String srcCode = fileContents.substring(beginIndex, beginTagIndex)
            + fileContents.substring(endTagIndex, endIndex);
        formattedSource += srcCode + "\n\n";

        // Get the next tag
        srcTagIndex = fileContents.indexOf(sourceTag, endIndex + 1);
      }
    }

    // Make the source pretty
    formattedSource = formattedSource.replace("<", "&lt;");
    formattedSource = formattedSource.replace(">", "&gt;");
    formattedSource = formattedSource.replace("* \n   */\n", "*/\n");
    formattedSource = "<pre>" + formattedSource + "</pre>";

    // Save the source code to a file
    String dstPath = ShowcaseConstants.DST_SOURCE_EXAMPLE
        + type.getSimpleSourceName() + ".html";
    createPublicResource(dstPath, formattedSource);
  }

  /**
   * Generate the styles used by a {@link ContentWidget}.
   *
   * @param type the {@link ContentWidget} subclass
   * @param styleDefs the concatenated style definitions
   * @param outDir the output directory
   */
  private void generateStyleFiles(
      JClassType type, String styleDefs, String outDir)
      throws UnableToCompleteException {
    // Look for annotation
    if (!type.isAnnotationPresent(ShowcaseStyle.class)) {
      return;
    }

    // Generate a style file for each theme/RTL mode pair
    String[] prefixes = type.getAnnotation(ShowcaseStyle.class).value();
    Map<String, String> matched = new LinkedHashMap<String, String>();
    for (String prefix : prefixes) {
      // Get the start location of the style code in the source file
      boolean foundStyle = false;
      int start = styleDefs.indexOf("\n" + prefix);
      while (start >= 0) {
        // Get the cssContents string name pattern
        int end = styleDefs.indexOf("{", start);
        String matchedName = styleDefs.substring(start, end).trim();

        // Get the style code
        end = styleDefs.indexOf("}", start) + 1;
        String styleDef = "<pre>" + styleDefs.substring(start, end) + "</pre>";
        matched.put(matchedName, styleDef);

        // Goto the next match
        foundStyle = true;
        start = styleDefs.indexOf("\n" + prefix, end);
      }

      // No style exists
      if (!foundStyle) {
        matched.put(prefix, "<pre>" + prefix + " {\n}</pre>");
      }
    }

    // Combine all of the styles into one formatted string
    String formattedStyle = "";
    for (String styleDef : matched.values()) {
      formattedStyle += styleDef;
    }

    // Save the raw source in the public directory
    String dstPath = outDir + type.getSimpleSourceName() + ".html";
    createPublicResource(dstPath, formattedStyle);
  }

  /**
   * Get the full contents of a resource.
   *
   * @param path the path to the resource
   * @return the contents of the resource
   */
  private String getResourceContents(String path)
      throws UnableToCompleteException {
    InputStream in = classLoader.getResourceAsStream(path);
    if (in == null) {
      logger.log(TreeLogger.ERROR, "Resource not found: " + path);
      throw new UnableToCompleteException();
    }

    StringBuffer fileContentsBuf = new StringBuffer();
    BufferedReader br = null;
    try {
      br = new BufferedReader(new InputStreamReader(in));
      String temp;
      while ((temp = br.readLine()) != null) {
        fileContentsBuf.append(temp).append('\n');
      }
    } catch (IOException e) {
      logger.log(TreeLogger.ERROR, "Cannot read resource", e);
      throw new UnableToCompleteException();
    } finally {
      if (br != null) {
        try {
          br.close();
        } catch (IOException e) {
        }
      }
    }

    // Return the file contents as a string
    return fileContentsBuf.toString();
  }

  /**
   * Load the contents of all CSS files used in the Showcase for a given
   * theme/RTL mode, concatenated into one string.
   *
   * @param theme the style theme
   * @param isRTL true if RTL mode
   * @return the concatenated styles
   */
  private String getStyleDefinitions(String theme, boolean isRTL)
      throws UnableToCompleteException {
    String cssContents = "";
    for (String path : SRC_CSS) {
      path = path.replace("$THEME", theme);
      if (isRTL) {
        path = path.replace("$RTL", "_rtl");
      } else {
        path = path.replace("$RTL", "");
      }
      cssContents += getResourceContents(path) + "\n\n";
    }
    return cssContents;
  }

  /**
   * Ensure that we only generate files once by creating a placeholder file,
   * then looking for it on subsequent generates.
   *
   * @return true if this is the first pass, false if not
   */
  private boolean isFirstPass() {
    String placeholder = ShowcaseConstants.DST_SOURCE + "generated";
    try {
      OutputStream outStream = context.tryCreateResource(logger, placeholder);
      if (outStream == null) {
        return false;
      } else {
        context.commitResource(logger, outStream);
      }
    } catch (UnableToCompleteException e) {
      logger.log(TreeLogger.ERROR, "Unable to generate", e);
      return false;
    }
    return true;
  }
}
