/*
 * Copyright 2009 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.attributeparsers;

import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.uibinder.rebind.FieldManager;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Deals with field references, e.g. the bits in braces here: <code>&lt;div
 * class="{style.enabled} fancy {style.impressive}" /></code>, by converting
 * them to java expressions (with the help of a
 * {@link FieldReferenceConverter.Delegate}).
 * <p>
 * A field reference is one or more segments separated by dots. The first
 * segment is considered to be a reference to a ui field, and succeeding
 * segments are method calls. So, <code>"{able.baker.charlie}"</code> becomes
 * <code>"able.baker().charlie()"</code>.
 * <p>
 * A field reference starts with '{' and is followed immediately by a character
 * that can legally start a java identifier&mdash;that is a letter, $, or
 * underscore. Braces not followed by such a character are left in place.
 * <p>
 * For convenience when dealing with generated CssResources, field segments with
 * dashes are converted to camel case. That is, {able.baker-charlie} is the same
 * as {able.bakerCharlie}
 * <p>
 * Opening braces may be escape by doubling them. That is, "{{foo}" will
 * converted to "{foo}", with no field reference detected.
 */
public class FieldReferenceConverter {
  /**
   * May be thrown by the {@link FieldReferenceConverter.Delegate} for badly
   * formatted input.
   */
  @SuppressWarnings("serial")
  public static class IllegalFieldReferenceException extends RuntimeException {
  }

  /**
   * Responsible for the bits around and between the field references. May throw
   * IllegalFieldReferenceException as it sees fit.
   */
  interface Delegate {
    /**
     * Returns the type any parsed field references are expected to return.
     */
    JType getType();

    /**
     * Called for fragment around and between field references.
     * <p>
     * Note that it will be called with empty strings if these surrounding bits
     * are empty. E.g., "{style.enabled} fancy {style.impressive}" would call
     * this method three times, with "", " fancy ", and "".
     * <p>
     * A string with no field references is treated as a single fragment, and
     * causes a single call to this method.
     */
    String handleFragment(String fragment)
        throws IllegalFieldReferenceException;

    /**
     * Called for each expanded field reference, to allow it to be stitched
     * together with surrounding fragments.
     */
    String handleReference(String reference)
        throws IllegalFieldReferenceException;
  }

  /**
   * Used by {@link #hasFieldReferences}. Passthrough implementation that notes
   * when handleReference has been called.
   */
  private static final class Telltale implements
      FieldReferenceConverter.Delegate {
    boolean hasComputed = false;

    public JType getType() {
      return null;
    }

    public String handleFragment(String fragment) {
      return fragment;
    }

    public String handleReference(String reference) {
      hasComputed = true;
      return reference;
    }

    public boolean hasComputed() {
      return hasComputed;
    }
  }

  private static final Pattern BRACES = Pattern.compile("[{]([^}]*)[}]");
  private static final Pattern LEGAL_FIRST_CHAR = Pattern.compile("^[$_a-zA-Z].*");

  /**
   * Returns true if the given string holds one or more field references.
   */
  public static boolean hasFieldReferences(String string) {
    Telltale telltale = new Telltale();
    new FieldReferenceConverter(null).convert(string, telltale);
    return telltale.hasComputed();
  }

  private final CssNameConverter cssConverter = new CssNameConverter();
  private final FieldManager fieldManager;

  /**
   * @param fieldManager to register parsed references with. May be null
   */
  FieldReferenceConverter(FieldManager fieldManager) {
    this.fieldManager = fieldManager;
  }

  /**
   * @throws IllegalFieldReferenceException if the delegate does
   */
  public String convert(String in, Delegate delegate) {
    StringBuilder b = new StringBuilder();
    int nextFindStart = 0;
    int lastMatchEnd = 0;

    Matcher m = BRACES.matcher(in);
    while (m.find(nextFindStart)) {
      String fieldReference = m.group(1);
      if (!legalFirstCharacter(fieldReference)) {
        nextFindStart = m.start() + 2;
        continue;
      }

      String precedingFragment = in.substring(lastMatchEnd, m.start());
      precedingFragment = handleFragment(precedingFragment, delegate);
      b.append(precedingFragment);

      if (fieldManager != null) {
        fieldManager.registerFieldReference(fieldReference, delegate.getType());
      }
      fieldReference = expandDots(fieldReference);
      b.append(delegate.handleReference(fieldReference));
      nextFindStart = lastMatchEnd = m.end();
    }

    b.append(handleFragment(in.substring(lastMatchEnd), delegate));
    return b.toString();
  }

  private String expandDots(String value) {
    StringBuilder b = new StringBuilder();
    String[] segments = value.split("[.]");

    for (String segment : segments) {
      segment = cssConverter.convertName(segment);
      if (b.length() == 0) {
        b.append(segment); // field name
      } else {
        b.append(".").append(segment).append("()");
      }
    }
    return b.toString();
  }

  private String handleFragment(String fragment, Delegate delegate) {
    fragment = fragment.replace("{{", "{");
    return delegate.handleFragment(fragment);
  }

  private boolean legalFirstCharacter(String fieldReference) {
    return LEGAL_FIRST_CHAR.matcher(fieldReference).matches();
  }
}
