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

import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.shared.GwtLocale;
import com.google.gwt.regexp.shared.MatchResult;
import com.google.gwt.regexp.shared.RegExp;

import java.util.Map;

import javax.validation.MessageInterpolator;

/**
 * Base GWT {@link MessageInterpolator}.
 */
abstract class BaseMessageInterpolator implements MessageInterpolator {

  // local version because guava is not included.
  private static interface Function<F, T> {
    T apply(F from);
  }

  /**
   * Regular expression used to do message interpolation.
   */
  private static final RegExp MESSAGE_PARAMETER_PATTERN = RegExp.compile(
      "(\\{[^\\}]+?\\})", "g");

  // Visible for testing
  static Function<String, String> createAnnotationReplacer(
      final Map<String, Object> map) {
    return new Function<String, String>() {

      @Override
      public String apply(String from) {
        Object object = map.get(from);
        return object == null ? null : object.toString();
      }
    };
  }

  private static Function<String, String> createReplacer(
      final ValidationMessageResolver messageResolver) {
    return new Function<String, String>() {
      @Override
      public String apply(String from) {
        Object object = messageResolver.get(from);
        return object == null ? null : object.toString();
      }
    };
  }

  /**
   * Replaces keys using the Default Validation Provider properties.
   */
  private final Function<String, String> providerReplacer =
      createReplacer((ValidationMessageResolver)
          GWT.create(ProviderValidationMessageResolver.class));

  /**
   * Replaces keys using the Validation User custom properties.
   */
  private final Function<String, String> userReplacer;

  protected BaseMessageInterpolator(
      UserValidationMessagesResolver userValidationMessagesResolver) {
    userReplacer = createReplacer(userValidationMessagesResolver);
  }

  @Override
  public final String interpolate(String messageTemplate, Context context) {
    return gwtInterpolate(messageTemplate, context, null);
  }

  protected final String gwtInterpolate(String message, Context context,
      GwtLocale locale) {
    // see Section 4.3.1.1
    String resolvedMessage = message;
    String step1message;

    // TODO(nchalko) Add a safety to make sure this does not loop forever.
    do {
      do {
        step1message = resolvedMessage;

        // Step 1 Replace message parameters using custom user messages
        // repeat
        resolvedMessage = replaceParameters(resolvedMessage, userReplacer);
      } while (!step1message.equals(resolvedMessage));

      // Step2 Replace message parameter using the default provider messages.
      resolvedMessage = replaceParameters(resolvedMessage, providerReplacer);

      // Step 3 repeat from step 1 if step 2 made changes.
    } while (!step1message.equals(resolvedMessage));

    // step 4 resolve annotation attributes
    resolvedMessage = replaceParameters(
        resolvedMessage,
        createAnnotationReplacer(context.getConstraintDescriptor().getAttributes()));

    // Remove escapes (4.3.1)
    resolvedMessage = resolvedMessage.replace("\\{", "{");
    resolvedMessage = resolvedMessage.replace("\\}", "}");
    resolvedMessage = resolvedMessage.replace("\\\\", "\\");
    return resolvedMessage;
  }

  protected final String replaceParameters(String message,
      Function<String, String> replacer) {
    StringBuffer sb = new StringBuffer();
    int index = 0;

    MatchResult matcher;
    while ((matcher = MESSAGE_PARAMETER_PATTERN.exec(message)) != null) {
      String matched = matcher.getGroup(0);
      sb.append(message.substring(index, matcher.getIndex()));
      Object value = replacer.apply(removeCurlyBrace(matched));
      sb.append(value == null ? matched : value);
      index = MESSAGE_PARAMETER_PATTERN.getLastIndex();
    }
    if (index < message.length()) {
      sb.append(message.substring(index));
    }
    return sb.toString();
  }

  private String removeCurlyBrace(String parameter) {
    return parameter.substring(1, parameter.length() - 1);
  }
}
