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

import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.uibinder.rebind.UiBinderWriter;
import com.google.gwt.uibinder.rebind.XMLElement;
import com.google.gwt.uibinder.rebind.messages.MessageWriter;
import com.google.gwt.uibinder.rebind.messages.MessagesWriter;
import com.google.gwt.user.client.ui.HasHTML;
import com.google.gwt.user.client.ui.HasText;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Used by {@link HTMLPanelParser}. Refines {@link HtmlPlaceholderInterpreter}
 * to allow widgets to appear inside msg elements in an HTMLPanel.
 * <p>
 * HasText and HasHTML get special treatment, where their innerText or innerHTML
 * become part of the {@literal @}Default value of the message being generated.
 * E.g., this markup in an HTMLPanel:
 *
 * <pre>
 * <m:msg>Hello &lt;gwt:HyperLink&gt;click here&lt;/gwt:HyperLink&gt; thank you.</m:msg></pre>
 *
 * becomes a message like this: <pre>
 * {@literal @}Default("Hello {0}click here{1} thank you.")
 * String getMessage1(
 *   {@literal @}Example("&lt;span&gt;") String widget1Begin,
 *   {@literal @}Example("&lt;/span&gt;") String widget1End
 * );</pre>
 *
 * <p>
 * The contents of other widget types are opaque to the message, and are covered
 * by a single placeholder. One implication of this is that the content of an
 * HTMLPanel inside a msg in another HTMLPanel must always be in a separate
 * message.
 */
class WidgetPlaceholderInterpreter extends HtmlPlaceholderInterpreter {
  // Could break this up into three further classes, for HasText, HasHTML
  // and Other, but that seems more trouble than it's worth.

  private int serial = 0;
  private final String ancestorExpression;
  private final String fieldName;
  private final Map<String, XMLElement> idToWidgetElement =
    new HashMap<String, XMLElement>();
  private final Set<String> idIsHasHTML = new HashSet<String>();
  private final Set<String> idIsHasText = new HashSet<String>();

  WidgetPlaceholderInterpreter(String fieldName, UiBinderWriter writer,
      MessageWriter message, String ancestorExpression) {
    super(writer, message, ancestorExpression);
    this.fieldName = fieldName;
    this.ancestorExpression = ancestorExpression;
 }

  @Override
  public String interpretElement(XMLElement elem)
      throws UnableToCompleteException {

    if (!uiWriter.isWidgetElement(elem)) {
      return super.interpretElement(elem);
    }

    JClassType type = uiWriter.findFieldType(elem);
    TypeOracle oracle = uiWriter.getOracle();

    MessagesWriter mw = uiWriter.getMessages();
    String name = mw.consumeMessageAttribute("ph", elem);
    if ("".equals(name)) {
      name = "widget" + (++serial);
    }

    String idHolder = uiWriter.declareDomIdHolder();
    idToWidgetElement.put(idHolder, elem);

    if (oracle.findType(HasHTML.class.getName()).isAssignableFrom(type)) {
      return handleHasHTMLPlaceholder(elem, name, idHolder);
    }

    if (oracle.findType(HasText.class.getName()).isAssignableFrom(type)) {
      return handleHasTextPlaceholder(elem, name, idHolder);
   }

    return handleOpaqueWidgetPlaceholder(name, idHolder);
  }

  /**
   * Called by {@link XMLElement#consumeInnerHtml} after all elements
   * have been handed to {@link #interpretElement}.
   */
  @Override
  public String postProcess(String consumed) throws UnableToCompleteException {
    for (String idHolder : idToWidgetElement.keySet()) {
      XMLElement childElem = idToWidgetElement.get(idHolder);
      String childField = uiWriter.parseElementToField(childElem);

      genSetWidgetTextCall(idHolder, childField);
      uiWriter.addInitStatement("%1$s.addAndReplaceElement(%2$s, %3$s);",
          fieldName, childField, idHolder);
    }
    /*
     * We get used recursively, so this will be called again. Empty the map 
     * or else we'll re-register things.
     */
    idToWidgetElement.clear();
    return super.postProcess(consumed);
  }

  private String genCloseTag(String name) {
    String closePlaceholder = nextClosePlaceholder(name + "End", "</span>");
    return closePlaceholder;
  }

  private String genOpenTag(String name, String idHolder) {
    String openTag = String.format("<span id='%s'>", 
        uiWriter.tokenForStringExpression(idHolder));
    String openPlaceholder = nextOpenPlaceholder(name + "Begin", openTag);
    return openPlaceholder;
  }

  private void genSetWidgetTextCall(String idHolder, String childField) {
    if (idIsHasText.contains(idHolder)) {
      uiWriter.addInitStatement(
          "%s.setText(%s.getElementById(%s).getInnerText());", childField,
          fieldName, idHolder);
    }
    if (idIsHasHTML.contains(idHolder)) {
      uiWriter.addInitStatement(
          "%s.setHTML(%s.getElementById(%s).getInnerHTML());", childField,
          fieldName, idHolder);
    }
  }

  private String handleHasHTMLPlaceholder(XMLElement elem, String name,
      String idHolder) throws UnableToCompleteException {
    idIsHasHTML.add(idHolder);
    String openPlaceholder = genOpenTag(name, idHolder);

    String body =
        elem.consumeInnerHtml(new HtmlPlaceholderInterpreter(uiWriter,
            message, ancestorExpression));
    String bodyToken = tokenator.nextToken(body);

    String closePlaceholder = genCloseTag(name);
    return openPlaceholder + bodyToken + closePlaceholder;
  }

  private String handleHasTextPlaceholder(XMLElement elem, String name,
      String idHolder) throws UnableToCompleteException {
    idIsHasText.add(idHolder);
    String openPlaceholder = genOpenTag(name, idHolder);

    String body =
        elem.consumeInnerText(new TextPlaceholderInterpreter(uiWriter,
            message));
    String bodyToken = tokenator.nextToken(body);

    String closePlaceholder = genCloseTag(name);
    return openPlaceholder + bodyToken + closePlaceholder;
  }

  private String handleOpaqueWidgetPlaceholder(String name, String idHolder) {
    String tag = String.format("<span id='%s'></span>", 
      uiWriter.tokenForStringExpression(idHolder));
    String placeholder = nextPlaceholder(name, "<span></span>", tag);
    return placeholder;
  }
}
