/*
 * 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.gwt.uibinder.elementparsers;

import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.i18n.client.CurrencyData;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.uibinder.rebind.UiBinderWriter;
import com.google.gwt.uibinder.rebind.XMLElement;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * Parses {@link com.google.gwt.user.client.ui.DateLabel} widgets.
 */
public class NumberLabelParser implements ElementParser {

  static final String AT_MOST_ONE_SPECIFIED_FORMAT = "May have only one of format, predefinedFormat and customFormat.";
  static final String AT_MOST_ONE_SPECIFIED_CURRENCY = "May have only one of currencyData and customCode.";
  static final String NO_CURRENCY_WITH_FORMAT = "May not specify both a NumberFormat and a currency code.";
  static final String NO_CURRENCY_WITHOUT_SPECIFIED_FORMAT = "May not specify a currency code if no format is given.";
  static final String NO_CURRENCY_WITH_PREDEFINED_FORMAT = "May not specify a currency code with a predefined format (except the CURRENCY format)";
  static final String UNKNOWN_PREDEFINED_FORMAT = "Unknown predefined format: %s";

  private static final Map<String, String> predefinedFormats;

  static {
    String prefix = NumberFormat.class.getCanonicalName();
    Map<String, String> formats = new HashMap<String, String>(4);
    formats.put("DECIMAL", prefix + ".getDecimalFormat()");
    formats.put("PERCENT", prefix + ".getPercentFormat()");
    formats.put("SCIENTIFIC", prefix + ".getScientificFormat()");
    // CURRENCY is special-cased in consumeFormat.
    predefinedFormats = Collections.unmodifiableMap(formats);
  }

  public void parse(XMLElement elem, String fieldName, JClassType type,
      UiBinderWriter writer) throws UnableToCompleteException {
    if (hasNumberFormatConstructor(writer.getOracle(), type)) {
      String format = consumeFormat(elem, writer);

      if (format != null) {
        writer.setFieldInitializerAsConstructor(fieldName, type, format);
      }
    }
  }

  private String consumeCurrency(XMLElement elem, UiBinderWriter writer)
      throws UnableToCompleteException {
    String currencyData = elem.consumeAttribute("currencyData",
        writer.getOracle().findType(CurrencyData.class.getCanonicalName()));
    String currencyCode = elem.consumeStringAttribute("currencyCode");

    if (currencyData != null && currencyCode != null) {
      writer.die(elem, AT_MOST_ONE_SPECIFIED_CURRENCY);
    }
    return currencyData != null ? currencyData : currencyCode;
  }

  private String consumeFormat(XMLElement elem, UiBinderWriter writer)
      throws UnableToCompleteException {
    String format = elem.consumeAttribute("format",
        writer.getOracle().findType(DateTimeFormat.class.getCanonicalName()));
    String predefinedFormat = elem.consumeRawAttribute("predefinedFormat");
    String customFormat = elem.consumeStringAttribute("customFormat");

    if (format != null) {
      if (predefinedFormat != null || customFormat != null) {
        writer.die(elem, AT_MOST_ONE_SPECIFIED_FORMAT);
      }
      if (hasCurrency(elem)) {
        writer.die(elem, NO_CURRENCY_WITH_FORMAT);
      }
      return format;
    }
    if (predefinedFormat != null) {
      if (customFormat != null) {
        writer.die(elem, AT_MOST_ONE_SPECIFIED_FORMAT);
      }
      if ("CURRENCY".equals(predefinedFormat)) {
        String currency = consumeCurrency(elem, writer);
        return NumberFormat.class.getCanonicalName() + ".getCurrencyFormat("
            + (currency != null ? currency : "") + ")";
      }
      if (hasCurrency(elem)) {
        writer.die(elem, NO_CURRENCY_WITH_PREDEFINED_FORMAT);
      }
      String f = predefinedFormats.get(predefinedFormat);
      if (f == null) {
        writer.die(elem, UNKNOWN_PREDEFINED_FORMAT, predefinedFormat);
      }
      return f;
    }
    if (customFormat != null) {
      String currency = consumeCurrency(elem, writer);
      return NumberFormat.class.getCanonicalName() + ".getFormat(" + customFormat
          + (currency != null ? ", " + currency : "") + ")";
    }
    if (hasCurrency(elem)) {
      writer.die(elem, NO_CURRENCY_WITHOUT_SPECIFIED_FORMAT);
    }
    return null;
  }

  private boolean hasCurrency(XMLElement elem) {
    return elem.hasAttribute("currencyData")
        || elem.hasAttribute("currencyCode");
  }

  private boolean hasNumberFormatConstructor(TypeOracle typeOracle,
      JClassType type) {
    JType numberFormatType = typeOracle.findType(NumberFormat.class.getName());
    return type.findConstructor(new JType[] {numberFormatType}) != null;
  }
}
