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

import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JField;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameter;
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.core.shared.impl.StringCase;
import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.DataResource;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.resources.client.ImageResource.RepeatStyle;
import com.google.gwt.uibinder.elementparsers.BeanParser;
import com.google.gwt.uibinder.elementparsers.SimpleInterpeter;
import com.google.gwt.uibinder.rebind.messages.MessagesWriter;
import com.google.gwt.uibinder.rebind.model.ImplicitClientBundle;
import com.google.gwt.uibinder.rebind.model.ImplicitCssResource;
import com.google.gwt.uibinder.rebind.model.ImplicitDataResource;
import com.google.gwt.uibinder.rebind.model.ImplicitImageResource;
import com.google.gwt.uibinder.rebind.model.OwnerField;

import java.util.LinkedHashSet;

/**
 * Parses the root UiBinder element, and kicks of the parsing of the rest of the
 * document.
 */
public class UiBinderParser {

  enum Resource {
    DATA {
      @Override
      void create(UiBinderParser parser, XMLElement elem)
          throws UnableToCompleteException {
        parser.createData(elem);
      }
    },
    IMAGE {
      @Override
      void create(UiBinderParser parser, XMLElement elem)
          throws UnableToCompleteException {
        parser.createImage(elem);
      }
    },
    IMPORT {
      @Override
      void create(UiBinderParser parser, XMLElement elem)
          throws UnableToCompleteException {
        parser.createImport(elem);
      }
    },
    STYLE {
      @Override
      void create(UiBinderParser parser, XMLElement elem)
          throws UnableToCompleteException {
        parser.createStyle(elem);
      }
    },
    WITH {
      @Override
      void create(UiBinderParser parser, XMLElement elem)
          throws UnableToCompleteException {
        parser.createResource(elem);
      }
    };

    abstract void create(UiBinderParser parser, XMLElement elem)
        throws UnableToCompleteException;
  }

  private static final String FLIP_RTL_ATTRIBUTE = "flipRtl";
  private static final String FIELD_ATTRIBUTE = "field";
  private static final String REPEAT_STYLE_ATTRIBUTE = "repeatStyle";
  private static final String SOURCE_ATTRIBUTE = "src";
  private static final String TYPE_ATTRIBUTE = "type";
  private static final String GSS_ATTRIBUTE = "gss";
  private static final String DO_NOT_EMBED_ATTRIBUTE = "doNotEmbed";
  private static final String MIME_TYPE_ATTRIBUTE = "mimeType";

  // TODO(rjrjr) Make all the ElementParsers receive their dependencies via
  // constructor like this one does, and make this an ElementParser. I want
  // guice!!!

  private static final String IMPORT_ATTRIBUTE = "import";
  private static final String TAG = "UiBinder";
  private final UiBinderWriter writer;
  private final TypeOracle oracle;
  private final MessagesWriter messagesWriter;
  private final FieldManager fieldManager;
  private final ImplicitClientBundle bundleClass;
  private final JClassType cssResourceType;
  private final JClassType imageResourceType;

  private final JClassType dataResourceType;
  private final String binderUri;
  private final UiBinderContext uiBinderContext;
  private final ResourceOracle resourceOracle;

  public UiBinderParser(UiBinderWriter writer, MessagesWriter messagesWriter,
      FieldManager fieldManager, TypeOracle oracle, ImplicitClientBundle bundleClass,
      String binderUri, UiBinderContext uiBinderContext, ResourceOracle resourceOracle) {
    this.writer = writer;
    this.oracle = oracle;
    this.messagesWriter = messagesWriter;
    this.fieldManager = fieldManager;
    this.bundleClass = bundleClass;
    this.uiBinderContext = uiBinderContext;
    this.cssResourceType = oracle.findType(CssResource.class.getCanonicalName());
    this.imageResourceType = oracle.findType(ImageResource.class.getCanonicalName());
    this.dataResourceType = oracle.findType(DataResource.class.getCanonicalName());
    this.binderUri = binderUri;
    this.resourceOracle = resourceOracle;
  }

  /**
   * Parses the root UiBinder element, and kicks off the parsing of the rest of
   * the document.
   */
  public FieldWriter parse(XMLElement elem) throws UnableToCompleteException {
    if (!writer.isBinderElement(elem)) {
      writer.die(elem, "Bad prefix on <%s:%s>? The root element must be in "
          + "xml namespace \"%s\" (usually with prefix \"ui:\"), "
          + "but this has prefix \"%s\"", elem.getPrefix(),
          elem.getLocalName(), binderUri, elem.getPrefix());
    }

    if (!TAG.equals(elem.getLocalName())) {
      writer.die(elem, "Root element must be %s:%s", elem.getPrefix(), TAG);
    }

    findResources(elem);
    messagesWriter.findMessagesConfig(elem);
    XMLElement uiRoot = elem.consumeSingleChildElement();
    return writer.parseElementToField(uiRoot);
  }

  private JClassType consumeCssResourceType(XMLElement elem)
      throws UnableToCompleteException {
    String typeName = elem.consumeRawAttribute(TYPE_ATTRIBUTE, null);
    if (typeName == null) {
      return cssResourceType;
    }

    return findCssResourceType(elem, typeName);
  }

  private JClassType consumeTypeAttribute(XMLElement elem)
      throws UnableToCompleteException {
    if (!elem.hasAttribute(TYPE_ATTRIBUTE)) {
      return null;
    }
    String resourceTypeName = elem.consumeRawAttribute(TYPE_ATTRIBUTE);

    JClassType resourceType = oracle.findType(resourceTypeName);
    if (resourceType == null) {
      writer.die(elem, "No such type %s", resourceTypeName);
    }

    return resourceType;
  }

  /**
   * Interprets <ui:data> elements.
   */
  private void createData(XMLElement elem) throws UnableToCompleteException {
    String name = elem.consumeRequiredRawAttribute(FIELD_ATTRIBUTE);
    String source = elem.consumeRequiredRawAttribute(SOURCE_ATTRIBUTE);
    // doNotEmbed is optional on DataResource
    Boolean doNotEmbed = elem.consumeBooleanConstantAttribute(DO_NOT_EMBED_ATTRIBUTE);
    // mimeType is optional on DataResource
    String mimeType = elem.consumeRawAttribute(MIME_TYPE_ATTRIBUTE);
    ImplicitDataResource dataMethod = bundleClass.createDataResource(
        name, source, mimeType, doNotEmbed);
    FieldWriter field = fieldManager.registerField(dataResourceType,
        dataMethod.getName());
    field.setInitializer(String.format("%s.%s()",
        fieldManager.convertFieldToGetter(bundleClass.getFieldName()),
        dataMethod.getName()));
  }

  /**
   * Interprets <ui:image> elements.
   */
  private void createImage(XMLElement elem) throws UnableToCompleteException {
    String name = elem.consumeRequiredRawAttribute(FIELD_ATTRIBUTE);
    // @source is optional on ImageResource
    String source = elem.consumeRawAttribute(SOURCE_ATTRIBUTE, null);

    Boolean flipRtl = elem.consumeBooleanConstantAttribute(FLIP_RTL_ATTRIBUTE);

    RepeatStyle repeatStyle = null;
    if (elem.hasAttribute(REPEAT_STYLE_ATTRIBUTE)) {
      String value = elem.consumeRawAttribute(REPEAT_STYLE_ATTRIBUTE);
      try {
        repeatStyle = RepeatStyle.valueOf(value);
      } catch (IllegalArgumentException e) {
        writer.die(elem, "Bad repeatStyle value %s", value);
      }
    }

    ImplicitImageResource imageMethod = bundleClass.createImageResource(name,
        source, flipRtl, repeatStyle);

    FieldWriter field = fieldManager.registerField(imageResourceType,
        imageMethod.getName());
    field.setInitializer(String.format("%s.%s()",
        fieldManager.convertFieldToGetter(bundleClass.getFieldName()),
        imageMethod.getName()));
  }

  /**
   * Process <code>&lt;ui:import field="com.example.Blah.CONSTANT"></code>.
   */
  private void createImport(XMLElement elem) throws UnableToCompleteException {
    String rawFieldName = elem.consumeRequiredRawAttribute(FIELD_ATTRIBUTE);
    if (elem.getAttributeCount() > 0) {
      writer.die(elem, "Should only find attribute \"%s\"", FIELD_ATTRIBUTE);
    }

    int idx = rawFieldName.lastIndexOf('.');
    if (idx < 1) {
      writer.die(elem, "Attribute %s does not look like a static import "
          + "reference", FIELD_ATTRIBUTE);
    }
    String enclosingName = rawFieldName.substring(0, idx);
    String constantName = rawFieldName.substring(idx + 1);

    JClassType enclosingType = oracle.findType(enclosingName);
    if (enclosingType == null) {
      writer.die(elem, "Unable to locate type %s", enclosingName);
    }

    if ("*".equals(constantName)) {
      for (JField field : enclosingType.getFields()) {
        if (!field.isStatic()) {
          continue;
        } else if (field.isPublic()) {
          // OK
        } else if (field.isProtected() || field.isPrivate()) {
          continue;
        } else if (!enclosingType.getPackage().equals(
            writer.getOwnerClass().getOwnerType().getPackage())) {
          // package-protected in another package
          continue;
        }
        createSingleImport(elem, enclosingType, enclosingName + "."
            + field.getName(), field.getName());
      }
    } else {
      createSingleImport(elem, enclosingType, rawFieldName, constantName);
    }
  }

  /**
   * Interprets <ui:with> elements.
   */
  private void createResource(XMLElement elem) throws UnableToCompleteException {
    String resourceName = elem.consumeRequiredRawAttribute(FIELD_ATTRIBUTE);

    JClassType resourceType = consumeTypeAttribute(elem);

    if (elem.getAttributeCount() > 0) {
      writer.die(elem, "Should only find attributes \"%s\" and \"%s\".", FIELD_ATTRIBUTE,
          TYPE_ATTRIBUTE);
    }

    /* Is it a parameter passed to a render method? */

    if (writer.isRenderer()) {
      JClassType matchingResourceType = findRenderParameterType(resourceName);
      if (matchingResourceType != null) {
        createResourceUiRenderer(elem, resourceName, resourceType, matchingResourceType);
        return;
      }
    }

    /* Perhaps it is provided via @UiField */

    if (writer.getOwnerClass() == null) {
      writer.die("No owner provided for %s", writer.getBaseClass().getQualifiedSourceName());
    }

    if (writer.getOwnerClass().getUiField(resourceName) != null) {
      // If the resourceType is present, is it the same as the one in the base class?
      OwnerField ownerField = writer.getOwnerClass().getUiField(resourceName);

      // If the resourceType was given, it must match the one declared with @UiField
      if (resourceType != null && !resourceType.getErasedType()
          .equals(ownerField.getType().getRawType().getErasedType())) {
        writer.die(elem, "Type must match %s.", ownerField);
      }

      if (ownerField.isProvided()) {
        createResourceUiField(resourceName, ownerField);
        return;
      } else {
        // Let's keep trying, but we know the type at least.
        resourceType = ownerField.getType().getRawType().getErasedType();
      }
    }

    /* Nope. If we know the type, maybe a @UiFactory will make it */

    if (resourceType != null && writer.getOwnerClass().getUiFactoryMethod(resourceType) != null) {
      createResourceUiFactory(elem, resourceName, resourceType);
      return;
    }

    /*
     * If neither of the above, the FieldWriter's default GWT.create call will
     * do just fine.
     */
    if (resourceType != null) {
      fieldManager.registerField(FieldWriterType.IMPORTED, resourceType, resourceName);
    } else {
      writer.die(elem, "Could not infer type for field %s.", resourceName);
    }

    // process ui:attributes child for property setting
    boolean attributesChildFound = false;
    // Use consumeChildElements(Interpreter) so no assertEmpty check is performed
    for (XMLElement child : elem.consumeChildElements(new SimpleInterpeter<Boolean>(true))) {
      if (attributesChildFound) {
        writer.die(child, "<ui:with> can only contain a single <ui:attributes> child Element.");
      }
      attributesChildFound = true;

      if (!elem.getNamespaceUri().equals(child.getNamespaceUri()) || !"attributes".equals(child.getLocalName())) {
        writer.die(child, "Found unknown child element.");
      }

      new BeanParser(uiBinderContext).parse(child, resourceName, resourceType, writer);
    }
  }

  private void createResourceUiFactory(XMLElement elem, String resourceName, JClassType resourceType)
      throws UnableToCompleteException {
    FieldWriter fieldWriter;
    JMethod factoryMethod = writer.getOwnerClass().getUiFactoryMethod(resourceType);
    JClassType methodReturnType = factoryMethod.getReturnType().getErasedType()
        .isClassOrInterface();
    if (!resourceType.getErasedType().equals(methodReturnType)) {
      writer.die(elem, "Type must match %s.", methodReturnType);
    }

    String initializer;
    if (writer.getDesignTime().isDesignTime()) {
      String typeName = factoryMethod.getReturnType().getQualifiedSourceName();
      initializer = writer.getDesignTime().getProvidedFactory(typeName,
          factoryMethod.getName(), "");
    } else {
      initializer = String.format("owner.%s()", factoryMethod.getName());
    }
    fieldWriter = fieldManager.registerField(
        FieldWriterType.IMPORTED, resourceType, resourceName);
    fieldWriter.setInitializer(initializer);
  }

  private void createResourceUiField(String resourceName, OwnerField ownerField)
      throws UnableToCompleteException {
    FieldWriter fieldWriter;
    String initializer;

    if (writer.getDesignTime().isDesignTime()) {
      String typeName = ownerField.getType().getRawType().getQualifiedSourceName();
      initializer = writer.getDesignTime().getProvidedField(typeName, ownerField.getName());
    } else {
      initializer = "owner." + ownerField.getName();
    }
    fieldWriter = fieldManager.registerField(
        FieldWriterType.IMPORTED,
        ownerField.getType().getRawType().getErasedType(),
        resourceName);
    fieldWriter.setInitializer(initializer);
  }

  private void createResourceUiRenderer(XMLElement elem, String resourceName,
      JClassType resourceType, JClassType matchingResourceType) throws UnableToCompleteException {
    FieldWriter fieldWriter;
    if (resourceType != null
        && !resourceType.getErasedType().isAssignableFrom(matchingResourceType.getErasedType())) {
      writer.die(elem, "Type must match the type of parameter %s in %s#render method.",
          resourceName,
          writer.getBaseClass().getQualifiedSourceName());
    }

    fieldWriter = fieldManager.registerField(
        FieldWriterType.IMPORTED, matchingResourceType.getErasedType(), resourceName);
    // Sets initialization as a NOOP. These fields are set from
    // parameters passed to UiRenderer#render(), instead.
    fieldWriter.setInitializer(resourceName);
  }

  private void createSingleImport(XMLElement elem, JClassType enclosingType,
      String rawFieldName, String constantName)
      throws UnableToCompleteException {
    JField field = enclosingType.findField(constantName);
    if (field == null) {
      writer.die(elem, "Unable to locate a field named %s in %s", constantName,
          enclosingType.getQualifiedSourceName());
    } else if (!field.isStatic()) {
      writer.die(elem, "Field %s in type %s is not static", constantName,
          enclosingType.getQualifiedSourceName());
    }

    JType importType = field.getType();
    JClassType fieldType;
    if (importType instanceof JPrimitiveType) {
      fieldType = oracle.findType(((JPrimitiveType) importType).getQualifiedBoxedSourceName());
    } else {
      fieldType = (JClassType) importType;
    }

    FieldWriter fieldWriter = fieldManager.registerField(fieldType,
        constantName);
    fieldWriter.setInitializer(rawFieldName);
  }

  private void createStyle(XMLElement elem) throws UnableToCompleteException {
    String body = elem.consumeUnescapedInnerText();
    String[] source = elem.consumeRawArrayAttribute(SOURCE_ATTRIBUTE);

    if (0 == body.length() && 0 == source.length) {
      writer.die(elem, "Must have either a src attribute or body text");
    }

    String name = elem.consumeRawAttribute(FIELD_ATTRIBUTE, "style");
    JClassType publicType = consumeCssResourceType(elem);

    String[] importTypeNames = elem.consumeRawArrayAttribute(IMPORT_ATTRIBUTE);
    LinkedHashSet<JClassType> importTypes = new LinkedHashSet<JClassType>();
    for (String type : importTypeNames) {
      importTypes.add(findCssResourceType(elem, type));
    }

    Boolean gss = elem.consumeBooleanConstantAttribute(GSS_ATTRIBUTE);

    ImplicitCssResource cssMethod = bundleClass.createCssResource(name, source,
        publicType, body, importTypes, gss, resourceOracle);

    FieldWriter field = fieldManager.registerFieldForGeneratedCssResource(cssMethod);
    field.setInitializer(String.format("%s.%s()",
        fieldManager.convertFieldToGetter(bundleClass.getFieldName()),
        cssMethod.getName()));
  }

  private JClassType findCssResourceType(XMLElement elem, String typeName)
      throws UnableToCompleteException {
    JClassType publicType = oracle.findType(typeName);
    if (publicType == null) {
      writer.die(elem, "No such type %s", typeName);
    }

    if (!publicType.isAssignableTo(cssResourceType)) {
      writer.die(elem, "Type %s does not extend %s",
          publicType.getQualifiedSourceName(),
          cssResourceType.getQualifiedSourceName());
    }
    return publicType;
  }

  private JClassType findRenderParameterType(String resourceName) throws UnableToCompleteException {
    JMethod renderMethod = null;
    JClassType baseClass = writer.getBaseClass();
    for (JMethod method : baseClass.getInheritableMethods()) {
      if (method.getName().equals("render")) {
        if (renderMethod == null) {
          renderMethod = method;
        } else {
          writer.die("%s declares more than one method named render",
              baseClass.getQualifiedSourceName());
        }
      }
    }
    if (renderMethod == null) {
      return null;
    }
    JClassType matchingResourceType = null;
    for (JParameter jParameter : renderMethod.getParameters()) {
      if (jParameter.getName().equals(resourceName)) {
        matchingResourceType = jParameter.getType().isClassOrInterface();
        break;
      }
    }
    return matchingResourceType;
  }

  private void findResources(XMLElement binderElement)
      throws UnableToCompleteException {
    binderElement.consumeChildElements(new XMLElement.Interpreter<Boolean>() {
      @Override
      public Boolean interpretElement(XMLElement elem)
          throws UnableToCompleteException {

        if (writer.isBinderElement(elem)) {
          try {
            Resource.valueOf(StringCase.toUpper(elem.getLocalName())).create(
                UiBinderParser.this, elem);
          } catch (IllegalArgumentException e) {
            writer.die(elem,
                "Unknown tag %s, or is not appropriate as a top level element",
                elem.getLocalName());
          }
          return true;
        }
        return false; // leave it be
      }
    });
  }
}
