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

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(elem, 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);
    }
    return super.postProcess(consumed);
  }

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

  private String genOpenTag(String name, String idHolder) {
    String openTag = String.format("<span id='\" + %s + \"'>", idHolder);
    String openPlaceholder =
        nextPlaceholder(name + "Begin", "<span>", 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(XMLElement elem, String name,
      String idHolder) throws UnableToCompleteException {
    String tag = String.format("<span id='\" + %s + \"'></span>", idHolder);
    String placeholder = nextPlaceholder(name, "<span></span>", tag);
    return placeholder;
  }
}
