/*
 * 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.i18n.tools;

import com.google.gwt.i18n.client.Constants;
import com.google.gwt.i18n.client.ConstantsWithLookup;
import com.google.gwt.i18n.client.Localizable;
import com.google.gwt.i18n.client.Messages;
import com.google.gwt.i18n.rebind.AbstractLocalizableInterfaceCreator;
import com.google.gwt.i18n.rebind.ConstantsInterfaceCreator;
import com.google.gwt.i18n.rebind.LocalizableGenerator;
import com.google.gwt.i18n.rebind.MessagesInterfaceCreator;
import com.google.gwt.util.tools.ArgHandlerExtra;
import com.google.gwt.util.tools.ArgHandlerString;
import com.google.gwt.util.tools.ToolBase;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;

/**
 * Common public access point for localization support methods.
 */
public class I18NSync extends ToolBase {

  private class classNameArgHandler extends ArgHandlerExtra {

    @Override
    public boolean addExtraArg(String str) {
      if (classNameArg != null) {
        System.err.println("Too many arguments.");
        return false;
      }
      // We wish to use the same sets of checks for validity whether the user
      // calls the static method to create localizable fields or uses the
      // command line, as the java call must throw IOException, here we must
      // catch it and convert it to a System.err message.
      try {
        File resourceFile = urlToResourceFile(str);
        checkValidResourceInputFile(resourceFile);
        classNameArg = str;
      } catch (IOException e) {
        System.err.println("Error: " + e.getMessage());
        return false;
      }
      return true;
    }

    @Override
    public String getPurpose() {
      return "Identifies the Constants/Messages class to be created.  For example com.google.sample.i18n.client.Colors";
    }

    @Override
    public String[] getTagArgs() {
      String[] interfaceArg = {"name of the Constants/Messages interface to create"};
      return interfaceArg;
    }

    @Override
    public boolean isRequired() {
      return true;
    }
  }

  private class outDirHandler extends ArgHandlerString {
    @Override
    public String getPurpose() {
      return "Java source directory, defaults to the resource's class path.";
    }

    @Override
    public String getTag() {
      return "-out";
    }

    @Override
    public String[] getTagArgs() {
      String[] resourceArgs = {"fileName"};
      return resourceArgs;
    }

    @Override
    public boolean isRequired() {
      return false;
    }

    @Override
    public boolean setString(String str) {

      // We wish to use the same sets of checks for validity whether the user
      // calls the static method to create localizable classes or uses the
      // command line, as the java call must throw IOException, here we must
      // catch it and convert it to a System.err message.
      outDirArg = new File(str);
      try {
        checkValidSourceDir(outDirArg);
      } catch (IOException e) {
        System.err.println("Error: " + e.getMessage());
        return false;
      }
      return true;
    }
  }

  /**
   * Created Key.
   */
  public static final String ID = "@" + LocalizableGenerator.GWT_KEY + " ";

  /**
   * Creates a <code>Constants</code> interface from a class name. The
   * resource file needed to create the class must be on your class path.
   *
   * @param className the name of the Constants class to be created
   * @param outDir source dir root
   * @throws IOException
   */
  public static void createConstantsInterfaceFromClassName(String className,
      File outDir) throws IOException {
    createConstantsInterfaceFromClassName(className, outDir, Constants.class);
  }

  /**
   * Creates a <code>ConstantsWithLookup</code> interface from a class name.
   * The resource file needed to create the class must be on your class path.
   *
   * @param className the name of the Constants class to be created
   * @throws IOException
   */
  public static void createConstantsWithLookupInterfaceFromClassName(
      String className) throws IOException {
    createConstantsInterfaceFromClassName(className, null,
        ConstantsWithLookup.class);
  }

  /**
   * Creates a <code>ConstantsWithLookup</code> interface from a class name.
   * The resource file needed to create the class must be on your class path.
   *
   * @param className the name of the Constants class to be created
   * @param sourceDir source dir root
   * @throws IOException
   */
  public static void createConstantsWithLookupInterfaceFromClassName(
      String className, File sourceDir) throws IOException {
    createConstantsInterfaceFromClassName(className, sourceDir,
        ConstantsWithLookup.class);
  }

  /**
   * Creates one of a Messages, ConstantsWithLookup, or Constants subclass.
   *
   * @param className Name of the subclass to be created
   * @param sourceDir source directory root
   * @param interfaceType What kind of base class to use
   * @throws IOException
   */
  public static void createInterfaceFromClassName(String className,
      File sourceDir, Class<? extends Localizable> interfaceType)
      throws IOException {
    if (interfaceType == Messages.class) {
      createMessagesInterfaceFromClassName(className, sourceDir);
    } else {
      if (!Constants.class.isAssignableFrom(interfaceType)) {
        throw new RuntimeException(
            "Internal Error: Unable to create i18n class derived from " +
            interfaceType.getName());
      }
      createConstantsInterfaceFromClassName(className, sourceDir,
          interfaceType.asSubclass(Constants.class));
    }
  }

  /**
   * Creates a <code>Messages</code> interface from a class name. The resource
   * file needed to create the class must be on your class path.
   *
   * @param className the name of the Constants class to be created
   * @throws IOException
   */
  public static void createMessagesInterfaceFromClassName(String className)
      throws IOException {
    createMessagesInterfaceFromClassName(className, null);
  }

  /**
   * Creates a <code>Messages</code> interface from a class name. The resource
   * file needed to create the class must be on your class path.
   *
   * @param className the name of the Constants class to be created
   * @param sourceDir source directory root
   * @throws IOException
   */
  public static void createMessagesInterfaceFromClassName(String className,
      File sourceDir) throws IOException {
    File resource = urlToResourceFile(className);
    File source;
    if (sourceDir == null) {
      source = synthesizeSourceFile(resource);
    } else {
      checkValidSourceDir(sourceDir);
      String sourcePath = className.replace('.', File.separatorChar);
      sourcePath = sourceDir.getCanonicalFile() + File.separator + sourcePath
          + ".java";
      source = new File(sourcePath);
    }
    // Need both source path and class name for this check
    checkValidJavaSourceOutputFile(source);
    checkValidResourceInputFile(resource);

    int classDiv = className.lastIndexOf(".");
    String packageName = className.substring(0, classDiv);
    String name = className.substring(classDiv + 1);
    AbstractLocalizableInterfaceCreator creator = new MessagesInterfaceCreator(
        name, packageName, resource, source);
    creator.generate();
  }

  /**
   * Creates Messages and Constants java source files.
   *
   * @param args arguments for generation
   */
  public static void main(String[] args) {
    I18NSync creator = new I18NSync();
    if (creator.processArgs(args)) {
      if (creator.run()) {
        return;
      }
    }
    System.exit(1);
  }

  static void checkValidJavaSourceOutputFile(File targetSource)
      throws IOException {

    if (targetSource.isDirectory()) {
      throw new IOException("Output file'" + targetSource
          + "' exists and is a directory; cannot overwrite");
    }
    if (targetSource.getParentFile().isDirectory() == false) {
      throw new IOException("The target source's directory '"
          + targetSource.getParent() + "' must be an existing directory");
    }
  }

  static void checkValidResourceInputFile(File resource) throws IOException {
    if (!resource.getPath().endsWith(".properties")) {
      throw new IOException("Properties files " + resource
          + " should end with '.properties'");
    }
    if (!resource.exists() || !resource.isFile()) {
      throw new IOException("Properties file not found: " + resource);
    }
  }

  private static void checkValidSourceDir(File outDir) throws IOException {
    if (outDir.isDirectory() == false) {
      throw new IOException(outDir
          + " must be an existing directory. Current path is "
          + new File(".").getCanonicalPath());
    }
  }

  private static void createConstantsInterfaceFromClassName(String className,
      File sourceDir, Class<? extends Constants> interfaceClass)
      throws IOException {
    File resource = urlToResourceFile(className);
    File source;
    if (sourceDir == null) {
      source = synthesizeSourceFile(resource);
    } else {
      checkValidSourceDir(sourceDir);
      String sourcePath = className.replace('.', File.separatorChar);
      sourcePath = sourceDir.getCanonicalFile() + File.separator + sourcePath
          + ".java";
      source = new File(sourcePath);
    }
    // Need both source path and class name for this check
    checkValidJavaSourceOutputFile(source);
    checkValidResourceInputFile(resource);

    int classDiv = className.lastIndexOf(".");
    String packageName = className.substring(0, classDiv);
    String name = className.substring(classDiv + 1);
    AbstractLocalizableInterfaceCreator creator = new ConstantsInterfaceCreator(
        name, packageName, resource, source, interfaceClass);
    creator.generate();
  }

  private static File synthesizeSourceFile(File resource) {
    String javaPath = resource.getName();
    javaPath = javaPath.substring(0, javaPath.lastIndexOf("."));
    javaPath = resource.getParentFile().getPath() + File.separator + javaPath
        + ".java";
    File targetClassFile = new File(javaPath);
    return targetClassFile;
  }

  private static File urlToResourceFile(String className)
      throws IOException {
    if (className.endsWith(".java") || className.endsWith(".properties")
        || className.endsWith(".class")
        || className.indexOf(File.separator) > 0) {
      throw new IllegalArgumentException(
          "class '"
              + className
              + "'should not contain an extension. \"com.google.gwt.SomeClass\" is an example of a correctly formed class string");
    }
    String resourcePath = className.replace('.', '/') + ".properties";
    ClassLoader cl = Thread.currentThread().getContextClassLoader();
    if (cl == null) {
      cl = ClassLoader.getSystemClassLoader();
    }
    URL r = cl.getResource(resourcePath);
    if (r == null) {
      throw new FileNotFoundException("Could not find the resource '"
          + resourcePath + " matching '" + className
          + "' did you remember to add it to your classpath?");
    }
    File resourceFile = new File(URLDecoder.decode(r.getPath(), "utf-8"));
    return resourceFile;
  }

  private ArgHandlerValueChooser chooser;
  private String classNameArg;
  private File outDirArg;

  private I18NSync() {
    registerHandler(new classNameArgHandler());
    registerHandler(new outDirHandler());
    chooser = new ArgHandlerValueChooser();
    registerHandler(chooser.getConstantsWithLookupArgHandler());
    registerHandler(chooser.getMessagesArgHandler());
  }

  /**
   * Creates the interface.
   *
   * @return whether the interface was created
   */
  protected boolean run() {
    try {
      createInterfaceFromClassName(classNameArg, outDirArg,
          chooser.getArgValue());
      return true;
    } catch (Throwable e) {
      System.err.println(e.getMessage());
      return false;
    }
  }
}
