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

import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.i18n.shared.CustomDateTimeFormat;
import com.google.gwt.i18n.shared.CustomDateTimeFormat.Pattern;
import com.google.gwt.i18n.shared.DateTimeFormat;
import com.google.gwt.i18n.shared.GwtLocale;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;

import java.io.PrintWriter;

/**
 * Generator used to generate an implementation of a {@link CustomDateTimeFormat} interface,
 * computing the best matching localized format patterns at compile time.
 */
public class CustomDateTimeFormatGenerator extends Generator {

  /**
   * Generate an implementation for the given type.
   *
   * @param logger error logger
   * @param context generator context
   * @param typeName target type name
   * @return generated class name
   * @throws UnableToCompleteException
   */
  @SuppressWarnings("deprecation")
  @Override
  public final String generate(TreeLogger logger, final GeneratorContext context,
      String typeName) throws UnableToCompleteException {
    TypeOracle typeOracle = context.getTypeOracle();
    // Get the current locale and interface type.
    PropertyOracle propertyOracle = context.getPropertyOracle();
    LocaleUtils localeUtils = LocaleUtils.getInstance(logger, propertyOracle,
        context);

    JClassType targetClass;
    try {
      targetClass = typeOracle.getType(typeName);
    } catch (NotFoundException e) {
      logger.log(TreeLogger.ERROR, "No such type " + typeName, e);
      throw new UnableToCompleteException();
    }
    JClassType cdtfClass;
    try {
      cdtfClass = typeOracle.getType(CustomDateTimeFormat.class.getName());
    } catch (NotFoundException e) {
      logger.log(TreeLogger.ERROR, "No such type "
          + CustomDateTimeFormat.class.getName(), e);
      throw new UnableToCompleteException();
    }
    if (!cdtfClass.isAssignableFrom(targetClass)) {
      logger.log(TreeLogger.ERROR, typeName + " is not assignable to "
          + CustomDateTimeFormat.class.getName());
      throw new UnableToCompleteException();
    }
    JClassType oldDateTimeFormat;
    try {
      oldDateTimeFormat = typeOracle.getType(
          com.google.gwt.i18n.client.DateTimeFormat.class.getName());
    } catch (NotFoundException e) {
      logger.log(TreeLogger.ERROR, "No client DateTimeFormat type?", e);
      throw new UnableToCompleteException();
    }
    JClassType dateTimeFormat;
    try {
      dateTimeFormat = typeOracle.getType(DateTimeFormat.class.getName());
    } catch (NotFoundException e) {
      logger.log(TreeLogger.ERROR, "No DateTimeFormat type?", e);
      throw new UnableToCompleteException();
    }
    // TODO(jat): runtime locales support
    GwtLocale gwtLocale = localeUtils.getCompileLocale();
    DateTimePatternGenerator dtpg = getDateTimePatternGenerator(gwtLocale);
    String packageName = targetClass.getPackage().getName();
    String className = targetClass.getName().replace('.', '_') + "_"
        + gwtLocale.getAsString();
    PrintWriter pw = context.tryCreate(logger, packageName, className);
    if (pw != null) {
      ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(
          packageName, className);
      factory.addImplementedInterface(targetClass.getQualifiedSourceName());
      factory.addImport("com.google.gwt.i18n.client.DateTimeFormat");
      SourceWriter writer = factory.createSourceWriter(context, pw);
      writer.indent();
      for (JMethod method : targetClass.getMethods()) {
        JType returnType = method.getReturnType();
        if (returnType != dateTimeFormat && returnType != oldDateTimeFormat) {
          logger.log(TreeLogger.ERROR, typeName + "." + method.getName()
              + " must return DateTimeFormat");
          throw new UnableToCompleteException();
        }
        String pattern;
        Pattern annotation = method.getAnnotation(Pattern.class);
        if (annotation == null) {
          com.google.gwt.i18n.client.CustomDateTimeFormat.Pattern oldAnnotation
              = method.getAnnotation(com.google.gwt.i18n.client.CustomDateTimeFormat.Pattern.class);
          if (oldAnnotation == null) {
            logger.log(TreeLogger.ERROR, typeName + "." + method.getName()
                + " must have an @Pattern annotation");
            throw new UnableToCompleteException();
          }
          pattern = oldAnnotation.value();
        } else {
          pattern = annotation.value();
        }
        pattern = dtpg.getBestPattern(pattern);
        writer.println();
        String retTypeName = method.getReturnType().getQualifiedSourceName();
        writer.println("public " + retTypeName + " " + method.getName() + "() {");
        writer.println("  return " + retTypeName + ".getFormat(\"" + pattern
            + "\");");
        writer.println("}");
      }
      writer.commit(logger);
    }
    return packageName + "." + className;
  }

  protected DateTimePatternGenerator getDateTimePatternGenerator(GwtLocale gwtLocale) {
    return new DateTimePatternGenerator(gwtLocale);
  }
}
