/*
 * 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.ArgHandler;
import com.google.gwt.util.tools.ArgHandlerExtra;
import com.google.gwt.util.tools.ArgHandlerFlag;
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;
    }
  }
}

/**
 * This class holds the '-createConstantsWithLookup' and '-createMessages'
 * ArgHandler classes.  It is shared by both I18NSync and I18NCreator classes.
 *        
 * To use this class, call the getConstantsWithLookupArgHandler()
 * and getMessagesArgHandler() methods and add the returned ArgHandler 
 * instances to a ToolBase registerHandler() method.  When parsing the arguments
 * is complete, you can retrieve the selected type by calling getArgValue().
 */
class ArgHandlerValueChooser {

  private  Class<? extends Localizable> argValue = Constants.class;
  private ArgHandler cwlArgHandler;
  private ArgHandler messagesArgHandler;

  /**
   * Returns one on "Messages.class", "ConstantsWithLookup.class", or
   * "Constants.class" depending on which argument handlers fired.
   *
   * @return A class literal, returns "Constants.class" by default.
   */
  Class<? extends Localizable> getArgValue() {
    return argValue;
  }

  /**
   * Retrieve the argument handler for -createConstantsWithLookup.
   * 
   * @return a flag argument handler
   */
   ArgHandler getConstantsWithLookupArgHandler() {
    if (cwlArgHandler == null) {
      cwlArgHandler = new ArgHandlerFlag() {

        @Override
        public String getPurpose() {
          return "Create scripts for a ConstantsWithLookup interface "
              + "rather than a Constants one";
        }

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

        @Override
        public boolean setFlag() {
          if (argValue == Messages.class) {
            System.err.println("-createMessages cannot be used with -createConstantsWithLookup");
            return false;
          }
          argValue = ConstantsWithLookup.class;
          return true;
        }
      };
    }
    return cwlArgHandler;
  }

  /**
   * Retrieves the -createMessages argument handler.
   * 
   * @return a flag argument handler
   */
  ArgHandler getMessagesArgHandler() {
    if (messagesArgHandler == null) {
      messagesArgHandler = new ArgHandlerFlag() {

        @Override
        public String getPurpose() {
          return "Create scripts for a Messages interface "
              + "rather than a Constants one";
        }

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

        @Override
        public boolean setFlag() {
          if (argValue == ConstantsWithLookup.class) {
            System.err.println("-createMessages cannot be used with -createConstantsWithLookup");
            return false;
          }
          argValue = Messages.class;
          return true;
        }
      };
    }
    return messagesArgHandler;
  }
}