/*
 * 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.client.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);
      }
    }
  }
}
