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

import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JEnumType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.uibinder.rebind.UiBinderWriter;
import com.google.gwt.uibinder.rebind.XMLElement;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.SplitLayoutPanel;

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

/**
 * Parses {@link DockLayoutPanel} widgets.
 * 
 * TODO(jgw): The code that explicitly excludes SplitLayoutPanel in a fairly
 * awkward way could be greatly simplified if we hoisted the "dock-ness" into an
 * interface implemented by both DockLayoutPanel and SplitLayoutPanel, and moved
 * most of this code into a parser for that specific interface. This parser
 * would then be reduced to a simple special case for the ctor param.
 */
public class DockLayoutPanelParser implements ElementParser {

  private static class CenterChild {
    final String widgetName;
    final XMLElement child;

    public CenterChild(XMLElement child, String widgetName) {
      this.widgetName = widgetName;
      this.child = child;
    }
  }

  private static final Map<String, String> DOCK_NAMES = new HashMap<String, String>();

  static {
    DOCK_NAMES.put("north", "addNorth");
    DOCK_NAMES.put("south", "addSouth");
    DOCK_NAMES.put("east", "addEast");
    DOCK_NAMES.put("west", "addWest");
    DOCK_NAMES.put("center", "add");
  }

  public void parse(XMLElement elem, String fieldName, JClassType type,
      UiBinderWriter writer) throws UnableToCompleteException {
    // Generate instantiation (requires a 'unit' ctor param).
    // (Don't generate a ctor for the SplitLayoutPanel, it has its own parser).
    if (type != getSplitLayoutPanelType(writer)) {
      JEnumType unitEnumType = writer.getOracle().findType(
          Unit.class.getCanonicalName()).isEnum();
      String unit = elem.consumeAttributeWithDefault("unit",
          String.format("%s.%s", unitEnumType.getQualifiedSourceName(), "PX"),
          unitEnumType);
      writer.setFieldInitializerAsConstructor(fieldName,
          writer.getOracle().findType(DockLayoutPanel.class.getName()), unit);
    }

    CenterChild center = null;

    // Parse children.
    for (XMLElement child : elem.consumeChildElements()) {
      // Make sure the element is one of the fixed set of valid directions.
      if (!isValidChildElement(elem, child)) {
        writer.die(elem,
            "Child must be one of "
                + "<%2$s:north>, <%2$s:south>, <%2$s:east>, <%2$s:west> or <%2$s:center>, "
                + "but found %3$s", elem.getPrefix(), child);
      }

      // Consume the single widget element.
      XMLElement widget = child.consumeSingleChildElement();
      if (!writer.isWidgetElement(widget)) {
        writer.die(elem, "%s must contain a widget, but found %s", child,
            widget);
      }
      String widgetName = writer.parseElementToField(widget);

      if (child.getLocalName().equals("center")) {
        if (center != null) {
          writer.die(elem, "Only one <%s:center> is allowed", elem.getPrefix());
        }
        center = new CenterChild(child, widgetName);
      } else {
        String size = child.consumeRequiredDoubleAttribute("size");
        writer.addStatement("%s.%s(%s, %s);", fieldName, addMethodName(child),
            widgetName, size);
      }
    }

    if (center != null) {
      writer.addStatement("%s.%s(%s);", fieldName, addMethodName(center.child),
          center.widgetName);
    }
  }

  private String addMethodName(XMLElement elem) {
    return DOCK_NAMES.get(elem.getLocalName());
  }

  private JClassType getSplitLayoutPanelType(UiBinderWriter writer) {
    try {
      return writer.getOracle().getType(SplitLayoutPanel.class.getName());
    } catch (NotFoundException e) {
      throw new RuntimeException("Unexpected exception", e);
    }
  }

  private boolean isValidChildElement(XMLElement parent, XMLElement child) {
    if (!parent.getNamespaceUri().equals(child.getNamespaceUri())) {
      return false;
    }
    if (!DOCK_NAMES.containsKey(child.getLocalName())) {
      return false;
    }
    // Made it through the gauntlet.
    return true;
  }
}
