/*
 * Copyright 2010 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.doctool.custom;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * Used by trunk/doc/build.xml to generate the packages.properties file.
 */
public class FindPackages {

  /**
   * A list of regular expressions to exclude. For readability, a '.' character
   * will be interpreted literally (i.e., it will be transformed into '\.'
   * before being compiled). Add rules here as needed.
   */
  private static final String[] EXCLUSIONS = {
      "^com.example.", "^com.google.gwt.dev(.|$)", "^com.google.gwt.emul.",
      "^com.google.gwt.examples(.|$)", "^com.google.gwt.i18n.server(.|$)",
      "^com.google.gwt.i18n.tools", "^com.google.gwt.lang",
      "^com.google.gwt.junit(.|$)", "^com.google.gwt.resources.css(.|$)",
      "^com.google.gwt.resources.rg(.|$)",
      "^com.google.gwt.rpc.client.ast(.|$)", "^com.google.gwt.soyc(.|$)",
      "^com.google.gwt.validation(.|$)",
      "^com.google.gwt.user.\\w+.rpc.core.",
      "^javax.", "^junit.", "^org.",
      ".impl(.|$)", ".rebind(.|$)"
  };

  /**
   * A list of emulated packages in the java.* namespace, to be emitted as
   * the JAVA_PKGS property.  Add packages here as needed.
   */
  private static final String[] JAVA_PKGS = {
    "java.lang", "java.lang.annotation", "java.math", "java.io", "java.sql", "java.util", "java.util.logging"};

  /**
   * User packages to include, regardless of exclusions.  Add packages here
   * as needed.
   */
  private static final String[] PACKAGE_WHITELIST = {
      "com.google.gwt.i18n.rebind.format", "com.google.gwt.i18n.rebind.keygen",
      "com.google.gwt.junit.client"};

  /**
   * Source directories under the root directory to traverse.  Add directories
   * here as needed.
   */
  private static final String[] SOURCE_DIRS = {
      "user/src", "user/javadoc", "user/super", "dev/core/src",
      "dev/core/super"};

  /**
   * Individual user classes to include, even if the rest of their packages
   * is not included.  Add classes here as needed.
   */
  private static final String[] USER_CLASSES = {
      "user/src/com/google/gwt/junit/tools/GWTTestSuite.java",
      "user/src/com/google/gwt/i18n/rebind/LocaleUtils.java",
      "user/src/com/google/gwt/i18n/server/GwtLocaleFactoryImpl.java",
      "user/src/com/google/gwt/i18n/server/GwtLocaleImpl.java"};

  private static Pattern exclusions;
  static {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < EXCLUSIONS.length; i++) {
      String ex = EXCLUSIONS[i];
      ex = ex.replace(".", "\\.");
      if (i < EXCLUSIONS.length - 1) {
        sb.append(ex + "|");
      } else {
        sb.append(ex);
      }
    }
    exclusions = Pattern.compile(sb.toString());
  }

  public static void main(String[] args) {
    if (args.length < 1) {
      System.err.println("usage: java com.google.doctool.custom.FindPackages <root dir>");
      System.exit(1);
    }

    try {
      File rootDir = new File(args[0]);
      // Output to <root>/doc/packages.properties
      File build = new File(rootDir, "build");
      File buildOut = new File(build, "out");
      File outFile = new File(buildOut, "packages.properties");
      PrintStream out = new PrintStream(new FileOutputStream(outFile), false, "UTF-8");

      out.println("# THIS FILE IS AUTOMATICALLY GENERATED BY");
      out.println("# com.google.doctool.custom.FindPackages");
      out.println("#");
      out.println("# This file contains all of the user javadoc packages");
      out.println("#");
      out.println("# JRE emulation packages");
      out.println("JAVA_PKGS=\\");
      for (int i = 0; i < JAVA_PKGS.length; i++) {
        if (i < JAVA_PKGS.length - 1) {
          out.println(JAVA_PKGS[i] + ";\\");
        } else {
          out.println(JAVA_PKGS[i]);
        }
      }
      out.println("# The last package should not have a trailing semicolon");
      out.println("");
      out.println("# Individual classes to include when we don't want to include an entire package");
      out.println("USER_CLASSES=\\");

      // Output a package-info.java once for each package
      Set<String> classPaths = new HashSet<String>();
      for (int i = 0; i < USER_CLASSES.length; i++) {
        String className = USER_CLASSES[i];
        String classPath = className.substring(0, className.lastIndexOf('/'));
        if (!classPaths.contains(classPath)) {
          classPaths.add(classPath);
          out.println("${gwt.root}/" + classPath + "/package-info.java" + ":\\");
        }
        if (i < USER_CLASSES.length - 1) {
          out.println("${gwt.root}/" + className + ":\\");
        } else {
          out.println("${gwt.root}/" + className);
        }
      }
      out.println("");
      out.println("# Packages to include");
      out.println("USER_PKGS=\\");

      Set<String> packages = new HashSet<String>();
      for (String dir : SOURCE_DIRS) {
        File f = new File(rootDir, dir);
        findPackages(f, null, packages);
      }
      for (String s : PACKAGE_WHITELIST) {
        packages.add(s);
      }

      ArrayList<String> packageList = new ArrayList<String>(packages);
      Collections.sort(packageList);

      for (int i = 0; i < packages.size(); i++) {
        if (i < packages.size() - 1) {
          out.println(packageList.get(i) + ";\\");
        } else {
          out.println(packageList.get(i));
        }
      }
      out.println("# The last package should not have a trailing semicolon");
      out.close();
    } catch (IOException e) {
      System.err.println("Got I/O Exception: " + e);
      System.exit(2);
    }
  }

  /**
   * Recursively find java packages under the given directory.
   *
   * @param dir the root directory
   * @param packageName the package name so far
   * @param packages the set of packages to output to
   */
  private static void findPackages(File dir, String packageName,
      Set<String> packages) {
    File[] files = dir.listFiles();
    if (files == null) {
      return;
    }
    boolean hasJava = false;
    for (File f : files) {
      String name = f.getName();
      if (f.isDirectory()) {
        String subPackage = packageName == null ? name : packageName + "."
            + name;
        findPackages(f, subPackage, packages);
      } else {
        // If there is a java file in the directory, include the package
        // for further processing.
        if (!hasJava && name.endsWith(".java")) {
          hasJava = true;
        }
      }
    }

    // Clean up translatable/ and super/ paths
    // Emit the package name if not excluded
    if (hasJava && packageName != null) {
      int index;
      if ((index = packageName.indexOf(".translatable.")) != -1) {
        packageName = packageName.substring(index + 14);
      }
      if ((index = packageName.indexOf(".super.")) != -1) {
        packageName = packageName.substring(index + 7);
      }
      if (!exclusions.matcher(packageName).find()) {
        packages.add(packageName);
      }
    }
  }
}
