/*
 * Copyright 2006 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;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

/**
 * Orchestrates the behavior of {@link Booklet}, {@link SplitterJoiner} and
 * other tools to create user documentation and API documentation.
 */
public class DocTool {

  private class ImageCopier extends DefaultHandler {

    private final File htmlDir;

    private ImageCopier(File htmlDir) {
      this.htmlDir = htmlDir;
    }

    public void startElement(String uri, String localName, String qName,
        Attributes attributes) throws SAXException {
      if (qName.equalsIgnoreCase("img")) {
        String imgSrc = attributes.getValue("src");
        if (imgSrc != null) {
          boolean found = false;
          for (int i = 0, n = imagePath.length; i < n; ++i) {
            File dir = imagePath[i];
            File inFile = new File(dir, imgSrc);
            if (inFile.exists()) {
              // Copy it over.
              //
              found = true;
              File outFile = new File(htmlDir, imgSrc);

              if (outFile.exists()) {
                if (outFile.lastModified() > inFile.lastModified()) {
                  // Already up to date.
                  break;
                }
              } else {
                File outFileDir = outFile.getParentFile();
                if (!outFileDir.exists() && !outFileDir.mkdirs()) {
                  err.println("Unable to create image output dir " + outFileDir);
                  break;
                }
              }
              if (!copyFile(inFile, outFile)) {
                err.println("Unable to copy image file " + outFile);
              }
            }
          }
          if (!found) {
            err.println("Unable to find image " + imgSrc);
          }
        }
      }
    }
  }

  private static final Pattern IN_XML_FILENAME = Pattern.compile(
      "(.+)\\.([^\\.]+)\\.xml", Pattern.CASE_INSENSITIVE);

  public static void main(String[] args) {
    DocToolFactory factory = new DocToolFactory();
    String arg;
    String pathSep = System.getProperty("path.separator");
    for (int i = 0, n = args.length; i < n; ++i) {
      if (tryParseFlag(args, i, "-help")) {
        printHelp();
        return;
      } else if (null != (arg = tryParseArg(args, i, "-out"))) {
        ++i;
        factory.setOutDir(arg);
      } else if (null != (arg = tryParseArg(args, i, "-html"))) {
        ++i;
        factory.setGenerateHtml(true);
        factory.setTitle(arg);

        // Slurp every arg not prefixed with "-".
        for (; i + 1 < n && !args[i + 1].startsWith("-"); ++i) {
          factory.addHtmlFileBase(args[i + 1]);
        }
      } else if (null != (arg = tryParseArg(args, i, "-overview"))) {
        ++i;
        factory.setOverviewFile(arg);
      } else if (null != (arg = tryParseArg(args, i, "-sourcepath"))) {
        ++i;
        String[] entries = arg.split("\\" + pathSep);
        for (int entryIndex = 0; entryIndex < entries.length; entryIndex++) {
          factory.addToSourcePath(entries[entryIndex]);
        }
      } else if (null != (arg = tryParseArg(args, i, "-classpath"))) {
        ++i;
        String[] entries = arg.split("\\" + pathSep);
        for (int entryIndex = 0; entryIndex < entries.length; entryIndex++) {
          factory.addToClassPath(entries[entryIndex]);
        }
      } else if (null != (arg = tryParseArg(args, i, "-packages"))) {
        ++i;
        String[] entries = arg.split("\\" + pathSep);
        for (int entryIndex = 0; entryIndex < entries.length; entryIndex++) {
          factory.addToPackages(entries[entryIndex]);
        }
      } else if (null != (arg = tryParseArg(args, i, "-imagepath"))) {
        ++i;
        String[] entries = arg.split("\\" + pathSep);
        for (int entryIndex = 0; entryIndex < entries.length; entryIndex++) {
          factory.addToImagePath(entries[entryIndex]);
        }
      } else {
        if (factory.getFileType() == null) {
          factory.setFileType(args[i]);
        } else {
          factory.setFileBase(args[i]);
        }
      }
    }

    DocTool docTool = factory.create(System.out, System.err);
    if (docTool != null) {
      docTool.process();
    }
  }

  public static boolean recursiveDelete(File file) {
    if (file.isDirectory()) {
      File[] children = file.listFiles();
      if (children != null) {
        for (int i = 0; i < children.length; i++) {
          if (!recursiveDelete(children[i])) {
            return false;
          }
        }
      }
    }
    if (!file.delete()) {
      System.err.println("Unable to delete " + file.getAbsolutePath());
      return false;
    }
    return true;
  }

  private static void printHelp() {
    String s = "";
    s += "DocTool (filetype filebase)? [docset-creation-options] [html-creation-options]\n";
    s += "    Creates structured javadoc xml output from Java source and/or\n";
    s += "    a table of contents and a set of cross-linked html files.\n";
    s += "    Specifying filebase/filetype produces output file \"filebase.filetype.xml\".\n";
    s += "    Specifying -html produces output files in ${out}/html.\n";
    s += "\n";
    s += "[docset-creation-options] are\n";
    s += "  -out\n";
    s += "    The output directory\n";
    s += "  -overview\n";
    s += "    The overview html file for this doc set\n";
    s += "  -sourcepath path\n";
    s += "    The path to find Java source for this doc set\n";
    s += "  -classpath path\n";
    s += "    The path to find imported classes for this doc set\n";
    s += "  -packages package-names\n";
    s += "    The command-separated list of package names to include in this doc set\n";
    s += "\n";
    s += "[html-creation-options] are\n";
    s += "  -html title filebase+\n";
    s += "    Causes topics in the named filebase(s) to be merged and converted into html\n";
    s += "  -imagepath\n";
    s += "    The semicolon-separated path to find images for html\n";
    System.out.println(s);
  }

  /**
   * Parse a flag with a argument.
   */
  private static String tryParseArg(String[] args, int i, String name) {
    if (i < args.length) {
      if (args[i].equals(name)) {
        if (i + 1 < args.length) {
          String arg = args[i + 1];
          if (arg.startsWith("-")) {
            System.out.println("Warning: arg to " + name
                + " looks more like a flag: " + arg);
          }
          return arg;
        } else {
          throw new IllegalArgumentException("Expecting an argument after "
              + name);
        }
      }
    }
    return null;
  }

  /**
   * Parse just a flag with no subsequent argument.
   */
  private static boolean tryParseFlag(String[] args, int i, String name) {
    if (i < args.length) {
      if (args[i].equals(name)) {
        return true;
      }
    }
    return false;
  }

  private final File[] classPath;

  private final String[] packages;

  private final PrintStream err;

  private final String base;

  private final String fileType;

  private final boolean generateHtml;

  private final String[] htmlFileBases;

  private final File[] imagePath;

  private final PrintStream out;

  private final File outDir;

  private final File overviewFile;

  private final File[] sourcePath;

  private final String title;

  DocTool(PrintStream out, PrintStream err, File outDir, boolean generateHtml,
      String title, String[] htmlFileBases, String fileType, String fileBase,
      File overviewFile, File[] sourcePath, File[] classPath,
      String[] packages, File[] imagePath) {
    this.out = out;
    this.err = err;
    this.outDir = outDir;
    this.generateHtml = generateHtml;
    this.base = fileBase;
    this.fileType = fileType;
    this.overviewFile = overviewFile;
    this.sourcePath = sourcePath;
    this.classPath = classPath;
    this.packages = packages;
    this.imagePath = imagePath;
    this.title = title;
    this.htmlFileBases = (String[]) htmlFileBases.clone();
  }

  public boolean copyFile(File in, File out) {
    FileInputStream fis = null;
    FileOutputStream fos = null;
    try {
      fis = new FileInputStream(in);
      fos = new FileOutputStream(out);
      byte[] buf = new byte[4096];
      int i = 0;
      while ((i = fis.read(buf)) != -1) {
        fos.write(buf, 0, i);
      }
      return true;
    } catch (Exception e) {
      return false;
    } finally {
      close(fis);
      close(fos);
    }
  }

  private void close(InputStream is) {
    if (is != null) {
      try {
        is.close();
      } catch (IOException e) {
        e.printStackTrace(err);
      }
    }
  }

  private void close(OutputStream os) {
    if (os != null) {
      try {
        os.close();
      } catch (IOException e) {
        e.printStackTrace(err);
      }
    }
  }

  private boolean copyImages(File htmlDir, File mergedTopicsFile) {
    FileReader fileReader = null;
    Throwable caught = null;
    try {
      fileReader = new FileReader(mergedTopicsFile);
      SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
      InputSource inputSource = new InputSource(fileReader);
      XMLReader xmlReader = parser.getXMLReader();
      xmlReader.setContentHandler(new ImageCopier(htmlDir));
      xmlReader.parse(inputSource);
      return true;
    } catch (SAXException e) {
      caught = e;
      Exception inner = e.getException();
      if (inner != null) {
        caught = inner;
      }
    } catch (ParserConfigurationException e) {
      caught = e;
    } catch (IOException e) {
      caught = e;
    } finally {
      try {
        if (fileReader != null) {
          fileReader.close();
        }
      } catch (IOException e) {
        e.printStackTrace(err);
      }
    }
    caught.printStackTrace(err);
    return false;
  }

  private Set findSourcePackages() {
    Set results = new HashSet();
    for (int i = 0, n = sourcePath.length; i < n; ++i) {
      File srcDir = sourcePath[i];
      findSourcePackages(results, srcDir, "");
    }
    return results;
  }

  private void findSourcePackages(Set results, File dir, String parentPackage) {
    File[] children = dir.listFiles();
    if (children != null) {
      for (int i = 0, n = children.length; i < n; ++i) {
        File child = children[i];
        String childName = parentPackage
            + (parentPackage.length() > 0 ? "." : "") + child.getName();
        if (child.isDirectory()) {
          // Recurse
          findSourcePackages(results, child, childName);
        } else if (child.getName().endsWith(".java")) {
          // Only include this dir as a result if there's at least one java file
          results.add(parentPackage);
        }
      }
    }
  }

  private String flattenPath(File[] entries) {
    String pathSep = System.getProperty("path.separator");
    String path = "";
    for (int i = 0, n = entries.length; i < n; ++i) {
      File entry = entries[i];
      if (i > 0) {
        path += pathSep;
      }
      path += entry.getAbsolutePath();
    }
    return path;
  }

  private void freshenIf(File file) {
    if (!file.isFile()) {
      return;
    }

    String name = file.getName();
    Matcher matcher = IN_XML_FILENAME.matcher(name);
    if (matcher.matches()) {
      String suffix = "." + matcher.group(2) + ".xml";
      File topicFile = tryReplaceSuffix(file, suffix, ".topics.xml");
      if (topicFile != null) {
        if (file.lastModified() > topicFile.lastModified()) {
          String xsltFileName = matcher.group(2) + "-" + "topics.xslt";
          String xslt = getFileFromClassPath(xsltFileName); // yucky slow
          out.println(file + " -> " + topicFile);
          transform(xslt, file, topicFile, null);
        }
      }
    }
  }

  private boolean genHtml() {
    // Make sure the html directory exists.
    //
    File htmlDir = new File(outDir, "html");
    if (!htmlDir.exists() && !htmlDir.mkdirs()) {
      err.println("Cannot create html output directory "
          + htmlDir.getAbsolutePath());
      return false;
    }

    // Merge all *.topics.xml into one topics.xml file.
    //
    File mergedTopicsFile = new File(outDir, "topics.xml");
    if (!mergeTopics(mergedTopicsFile)) {
      return false;
    }

    // Parse it all to find the images and copy them over.
    //
    copyImages(htmlDir, mergedTopicsFile);

    // Transform to merged topics into merged htmls.
    //
    File mergedHtmlsFile = new File(htmlDir, "topics.htmls");
    long lastModifiedHtmls = mergedHtmlsFile.lastModified();
    long lastModifiedTopics = mergedTopicsFile.lastModified();
    if (!mergedHtmlsFile.exists() || lastModifiedHtmls < lastModifiedTopics) {
      String xsltHtmls = getFileFromClassPath("topics-htmls.xslt");

      Map params = new HashMap();
      params.put("title", title);

      transform(xsltHtmls, mergedTopicsFile, mergedHtmlsFile, params);

      // Split the merged htmls into many html files.
      //
      if (!splitHtmls(mergedHtmlsFile)) {
        return false;
      }

      // Create a table of contents.
      //
      File tocFile = new File(htmlDir, "contents.html");
      String xsltToc = getFileFromClassPath("topics-toc.xslt");
      transform(xsltToc, mergedTopicsFile, tocFile, params);

      // Copy the CSS file over.
      //
      String css = getFileFromClassPath("doc.css");
      try {
        FileWriter cssWriter = new FileWriter(new File(htmlDir, "doc.css"));
        cssWriter.write(css);
        cssWriter.close();
      } catch (IOException e) {
        e.printStackTrace(err);
      }
    } else {
      out.println("Skipping html creation since nothing seems to have changed since "
          + mergedHtmlsFile.getAbsolutePath());
    }

    return true;
  }

  private String getFileFromClassPath(String filename) {
    InputStream in = null;
    try {
      in = getClass().getClassLoader().getResourceAsStream(filename);
      try {
        if (in == null) {
          err.println("Cannot find file: " + filename);
          System.exit(-1); // yuck
        }
        StringWriter sw = new StringWriter();
        int ch;
        while ((ch = in.read()) != -1) {
          sw.write(ch);
        }
        return sw.toString();
      } finally {
        if (in != null) {
          in.close();
        }
      }
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  private boolean mergeTopics(File mergedTopicsFile) {
    try {
      List args = new ArrayList();
      args.add("join"); // what to do
      args.add("topics"); // the outer element is <topics>
      args.add(mergedTopicsFile.getAbsolutePath());

      // For each of the htmlFileBases, try to find a file having that name to
      // merge into the big topics doc.
      //
      boolean foundAny = false;
      for (int i = 0, n = htmlFileBases.length; i < n; ++i) {
        String filebase = htmlFileBases[i];
        File fileToMerge = new File(outDir, filebase + ".topics.xml");
        if (fileToMerge.exists()) {
          foundAny = true;
          args.add(fileToMerge.getAbsolutePath());
        } else {
          err.println("Unable to find " + fileToMerge.getName());
        }
      }

      if (foundAny) {
        String[] argArray = (String[]) args.toArray(new String[0]);
        traceCommand("SplitterJoiner", argArray);
        SplitterJoiner.main(argArray);
      } else {
        err.println("No topics found");
        return false;
      }
    } catch (IOException e) {
      e.printStackTrace(err);
      return false;
    }
    return true;
  }

  /**
   * Runs the help process.
   */
  private boolean process() {
    if (fileType != null) {
      // Produce XML from JavaDoc.
      //
      String fileName = base + "." + fileType + ".xml";
      if (!runBooklet(new File(outDir, fileName))) {
        return false;
      }
    }

    // Process existing files to get them into topics format.
    // Done afterwards for convenience when debugging your doc.
    //
    transformExistingIntoTopicXml();

    if (generateHtml) {
      // Merge into HTML.
      if (!genHtml()) {
        return false;
      }
    }

    return true;
  }

  private boolean runBooklet(File bkoutFile) {
    // Write out the list of packages that can be found on the source path.
    out.println("Creating " + bkoutFile.getAbsolutePath());
    Set srcPackages = findSourcePackages();
    if (srcPackages.isEmpty()) {
      err.println("No input files found");
      return false;
    }

    List args = new ArrayList();

    // For now, harded-coded, but could be passed through
    args.add("-source");
    args.add("1.4");

    // The doclet
    args.add("-doclet");
    args.add(Booklet.class.getName());

    // Class path
    args.add("-classpath");
    args.add(flattenPath(classPath));

    // Source path
    args.add("-sourcepath");
    args.add(flattenPath(sourcePath));

    // Overview file
    if (overviewFile != null) {
      args.add("-overview");
      args.add(overviewFile.getAbsolutePath());
    }

    // Output file
    args.add("-bkout");
    args.add(bkoutFile.getAbsolutePath());

    if (packages != null) {
      // Specify the packages to actually emit doc for
      StringBuffer bkdocpkg = new StringBuffer();
      for (int i = 0; i < packages.length; i++) {
        String pkg = packages[i];
        bkdocpkg.append(pkg);
        bkdocpkg.append(";");
      }
      args.add("-bkdocpkg");
      args.add(bkdocpkg.toString());
    }

    args.add("-breakiterator");

    // Specify the set of input packages (needed by JavaDoc)
    args.addAll(srcPackages);

    String[] argArray = (String[]) args.toArray(new String[0]);
    traceCommand("Booklet", argArray);
    Booklet.main(argArray);

    return bkoutFile.exists();
  }

  private boolean splitHtmls(File mergedHtmlsFile) {
    try {
      List args = new ArrayList();
      args.add("split"); // what to do
      args.add(mergedHtmlsFile.getAbsolutePath());
      String[] argArray = (String[]) args.toArray(new String[0]);
      traceCommand("SplitterJoiner", argArray);
      SplitterJoiner.main(argArray);
    } catch (IOException e) {
      e.printStackTrace(err);
      return false;
    }
    return true;
  }

  private void traceCommand(String cmd, String[] args) {
    out.print(cmd);
    for (int i = 0, n = args.length; i < n; ++i) {
      String arg = args[i];
      out.print(" ");
      out.print(arg);
    }
    out.println();
  }

  private void transform(String xslt, File inFile, File outFile, Map params) {
    Throwable caught = null;
    try {
      TransformerFactory transformerFactory = TransformerFactory.newInstance();
      StreamSource xsltSource = new StreamSource(new StringReader(xslt));
      Transformer transformer = transformerFactory.newTransformer(xsltSource);
      transformer.setOutputProperty(
          javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes");
      transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT,
          "yes");
      transformer.setOutputProperty(
          "{http://xml.apache.org/xslt}indent-amount", "4");

      if (params != null) {
        for (Iterator iter = params.entrySet().iterator(); iter.hasNext();) {
          Map.Entry entry = (Map.Entry) iter.next();
          transformer.setParameter((String) entry.getKey(), entry.getValue());
        }
      }

      FileOutputStream fos = new FileOutputStream(outFile);
      StreamResult result = new StreamResult(fos);
      StreamSource xmlSource = new StreamSource(new FileReader(inFile));
      transformer.transform(xmlSource, result);
      fos.close();
      return;
    } catch (TransformerConfigurationException e) {
      caught = e;
    } catch (TransformerException e) {
      caught = e;
    } catch (IOException e) {
      caught = e;
    }
    throw new RuntimeException("Unable to complete the xslt tranform", caught);
  }

  private void transformExistingIntoTopicXml() {
    File[] children = outDir.listFiles();
    if (children != null) {
      for (int i = 0, n = children.length; i < n; ++i) {
        File file = children[i];
        freshenIf(file);
      }
    }
  }

  private File tryReplaceSuffix(File file, String oldSuffix, String newSuffix) {
    String name = file.getName();
    if (name.endsWith(oldSuffix)) {
      String baseName = name.substring(0, name.length() - oldSuffix.length());
      return new File(file.getParent(), baseName + newSuffix);
    } else {
      return null;
    }
  }
}
