// Copyright 2016 The Bazel Authors. All rights reserved.
//
// 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.devtools.build.android;

import static com.android.resources.ResourceType.DECLARE_STYLEABLE;
import static com.android.resources.ResourceType.ID;
import static com.android.resources.ResourceType.PUBLIC;

import com.android.aapt.Resources.Reference;
import com.android.aapt.Resources.Value;
import com.android.resources.ResourceType;
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.android.AndroidCompiledDataDeserializer.ReferenceResolver;
import com.google.devtools.build.android.FullyQualifiedName.Factory;
import com.google.devtools.build.android.FullyQualifiedName.VirtualType;
import com.google.devtools.build.android.ParsedAndroidData.KeyValueConsumer;
import com.google.devtools.build.android.proto.SerializeFormat;
import com.google.devtools.build.android.proto.SerializeFormat.DataValueXml;
import com.google.devtools.build.android.resources.Visibility;
import com.google.devtools.build.android.xml.ArrayXmlResourceValue;
import com.google.devtools.build.android.xml.AttrXmlResourceValue;
import com.google.devtools.build.android.xml.IdXmlResourceValue;
import com.google.devtools.build.android.xml.MacroXmlResourceValue;
import com.google.devtools.build.android.xml.Namespaces;
import com.google.devtools.build.android.xml.PluralXmlResourceValue;
import com.google.devtools.build.android.xml.PublicXmlResourceValue;
import com.google.devtools.build.android.xml.ResourcesAttribute;
import com.google.devtools.build.android.xml.SimpleXmlResourceValue;
import com.google.devtools.build.android.xml.StyleXmlResourceValue;
import com.google.devtools.build.android.xml.StyleableXmlResourceValue;
import com.google.protobuf.InvalidProtocolBufferException;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Iterator;
import java.util.Objects;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.StartElement;

/**
 * Represents an Android Resource defined in the xml and value folder.
 *
 * <p>Basically, if the resource is defined inside a &lt;resources&gt; tag, this class will handle
 * it. Layouts are treated separately as they don't declare anything besides ids.
 */
public class DataResourceXml implements DataResource {

  /**
   * Parses xml resources from a Path to the provided overwritable and combining collections.
   *
   * <p>This method is a bit tricky in the service of performance -- creating several collections
   * and merging them was more expensive than writing to mutable collections directly.
   *
   * @param xmlInputFactory Used to create an XMLEventReader from the supplied resource path.
   * @param path The path to the xml resource to be parsed.
   * @param fqnFactory Used to create {@link FullyQualifiedName}s from the resource names.
   * @param overwritingConsumer A consumer for overwritable {@link DataResourceXml}s.
   * @param combiningConsumer A consumer for combining {@link DataResourceXml}s.
   * @throws XMLStreamException Thrown with the resource format is invalid.
   * @throws FactoryConfigurationError Thrown with the {@link XMLInputFactory} is misconfigured.
   * @throws IOException Thrown when there is an error reading a file.
   */
  public static void parse(
      XMLInputFactory xmlInputFactory,
      Path path,
      Factory fqnFactory,
      KeyValueConsumer<DataKey, DataResource> overwritingConsumer,
      KeyValueConsumer<DataKey, DataResource> combiningConsumer)
      throws XMLStreamException, FactoryConfigurationError, IOException {
    XMLEventReader eventReader =
        xmlInputFactory.createXMLEventReader(
            new BufferedInputStream(Files.newInputStream(path)), StandardCharsets.UTF_8.toString());
    try {
      // TODO(corysmith): Make the xml parsing more readable.
      for (StartElement resources = XmlResourceValues.moveToResources(eventReader);
          resources != null;
          resources = XmlResourceValues.moveToResources(eventReader)) {
        // Record attributes on the <resources> tag.
        Iterator<Attribute> attributes = XmlResourceValues.iterateAttributesFrom(resources);
        while (attributes.hasNext()) {
          Attribute attribute = attributes.next();
          Namespaces namespaces = Namespaces.from(attribute.getName());
          String attributeName =
              attribute.getName().getNamespaceURI().isEmpty()
                  ? attribute.getName().getLocalPart()
                  // This is intentionally putting the "package" in the wrong place!
                  // TODO: FullyQualifiedName.Factory#create has a overload which accepts "package".
                  : attribute.getName().getPrefix() + ":" + attribute.getName().getLocalPart();
          FullyQualifiedName fqn =
              fqnFactory.create(VirtualType.RESOURCES_ATTRIBUTE, attribute.getName().toString());
          ResourcesAttribute resourceAttribute =
              ResourcesAttribute.of(fqn, attributeName, attribute.getValue());
          DataResourceXml resource =
              DataResourceXml.createWithNamespaces(path, resourceAttribute, namespaces);
          if (resourceAttribute.isCombining()) {
            combiningConsumer.accept(fqn, resource);
          } else {
            overwritingConsumer.accept(fqn, resource);
          }
        }
        // Process resource declarations.
        for (StartElement start = XmlResourceValues.findNextStart(eventReader);
            start != null;
            start = XmlResourceValues.findNextStart(eventReader)) {
          Namespaces.Collector namespacesCollector = Namespaces.collector();
          if (XmlResourceValues.isEatComment(start) || XmlResourceValues.isSkip(start)) {
            continue;
          }
          ResourceType resourceType = getResourceType(start);
          if (resourceType == null) {
            // Note: parsing <macro> resources is currently not possible but this should not be a
            // problem since Bazel for the most part does not need to parse resource XML files.
            throw new XMLStreamException(
                path + " contains an unrecognized resource type: " + start, start.getLocation());
          }
          if (resourceType == DECLARE_STYLEABLE) {
            // Styleables are special, as they produce multiple overwrite and combining values,
            // so we let the value handle the assignments.
            XmlResourceValues.parseDeclareStyleable(
                fqnFactory, path, overwritingConsumer, combiningConsumer, eventReader, start);
          } else {
            // Of simple resources, only IDs and Public are combining.
            KeyValueConsumer<DataKey, DataResource> consumer =
                (resourceType == ID || resourceType == PUBLIC)
                    ? combiningConsumer
                    : overwritingConsumer;
            String elementName = XmlResourceValues.getElementName(start);
            if (elementName == null) {
              throw new XMLStreamException(
                  String.format("resource name is required for %s", resourceType),
                  start.getLocation());
            }
            FullyQualifiedName key = fqnFactory.create(resourceType, elementName);
            XmlResourceValue xmlResourceValue =
                parseXmlElements(resourceType, eventReader, start, namespacesCollector);
            consumer.accept(
                key,
                DataResourceXml.createWithNamespaces(
                    path, xmlResourceValue, namespacesCollector.toNamespaces()));
          }
        }
      }
    } catch (XMLStreamException e) {
      throw new XMLStreamException(path + ": " + e.getMessage(), e.getLocation(), e);
    } catch (RuntimeException e) {
      throw new RuntimeException("Error parsing " + path, e);
    }
  }

  @SuppressWarnings("deprecation")
  // TODO(corysmith): Update proto to use get<>Map
  public static DataValue from(SerializeFormat.DataValue protoValue, DataSource source)
      throws InvalidProtocolBufferException {
    DataValueXml xmlValue = protoValue.getXmlValue();
    return createWithNamespaces(
        source, valueFromProto(xmlValue), Namespaces.from(xmlValue.getNamespaceMap()));
  }

  public static DataResourceXml from(
      Value protoValue,
      Visibility visibility,
      DataSource source,
      ResourceType resourceType,
      ReferenceResolver packageResolver)
      throws InvalidProtocolBufferException {
    DataResourceXml dataResourceXml =
        createWithNamespaces(
            source,
            valueFromProto(protoValue, visibility, resourceType, packageResolver),
            Namespaces.empty());
    return dataResourceXml;
  }

  private static XmlResourceValue valueFromProto(SerializeFormat.DataValueXml proto)
      throws InvalidProtocolBufferException {
    Preconditions.checkArgument(proto.hasType());
    switch (proto.getType()) {
      case ARRAY:
        return ArrayXmlResourceValue.from(proto);
      case SIMPLE:
        return SimpleXmlResourceValue.from(proto);
      case ATTR:
        return AttrXmlResourceValue.from(proto);
      case ID:
        return IdXmlResourceValue.of();
      case PLURAL:
        return PluralXmlResourceValue.from(proto);
      case PUBLIC:
        return PublicXmlResourceValue.from(proto);
      case STYLE:
        return StyleXmlResourceValue.from(proto);
      case STYLEABLE:
        return StyleableXmlResourceValue.from(proto);
      case RESOURCES_ATTRIBUTE:
        return ResourcesAttribute.from(proto);
      case MACRO:
        return MacroXmlResourceValue.from(proto);
      default:
        throw new IllegalArgumentException();
    }
  }

  private static XmlResourceValue valueFromProto(
      Value proto,
      Visibility visibility,
      ResourceType resourceType,
      ReferenceResolver packageResolver)
      throws InvalidProtocolBufferException {
    switch (resourceType) {
      case STYLE:
        return StyleXmlResourceValue.from(proto, visibility);
      case ARRAY:
        return ArrayXmlResourceValue.from(proto, visibility);
      case PLURALS:
        return PluralXmlResourceValue.from(proto, visibility);
      case ATTR:
        return AttrXmlResourceValue.from(proto, visibility);
      case STYLEABLE:
        return StyleableXmlResourceValue.from(proto, visibility, packageResolver);
      case ID:
        return IdXmlResourceValue.from(proto, visibility);
      case DIMEN:
      case LAYOUT:
      case STRING:
      case BOOL:
      case COLOR:
      case FRACTION:
      case INTEGER:
      case DRAWABLE:
      case ANIM:
      case ANIMATOR:
      case DECLARE_STYLEABLE:
      case INTERPOLATOR:
      case MENU:
      case MIPMAP:
      case NAVIGATION:
      case RAW:
      case TRANSITION:
      case FONT:
      case XML:
        return SimpleXmlResourceValue.from(proto, visibility, resourceType);
      default:
        // TODO(b/193025750): The current version of the layoutlib prebuilt used by Bazel does not
        // contain the macro type. This work around allows using macro resource types internally
        // until the layoutlib preuilt is updated or the dependency on it is removed.
        if ("macro".equals(resourceType.getName())) {
          return MacroXmlResourceValue.from(proto, visibility);
        }
        throw new IllegalArgumentException("Unhandled type " + resourceType + " from " + proto);
    }
  }

  public static DataResourceXml fromPublic(DataSource source, ResourceType resourceType, int id) {
    DataResourceXml dataResourceXml =
        createWithNamespaces(
            source, PublicXmlResourceValue.from(resourceType, id), Namespaces.empty());
    return dataResourceXml;
  }

  private static XmlResourceValue parseXmlElements(
      ResourceType resourceType,
      XMLEventReader eventReader,
      StartElement start,
      Namespaces.Collector namespacesCollector)
      throws XMLStreamException {
    // Handle ids first, as they are a special kind of item.
    if (resourceType == ID) {
      return XmlResourceValues.parseId(eventReader, start, namespacesCollector);
    }
    // Handle item stubs.
    if (XmlResourceValues.isItem(start)) {
      return XmlResourceValues.parseSimple(eventReader, resourceType, start, namespacesCollector);
    }
    switch (resourceType) {
      case STYLE:
        return XmlResourceValues.parseStyle(eventReader, start);
      case ARRAY:
        return ArrayXmlResourceValue.parseArray(eventReader, start, namespacesCollector);
      case PLURALS:
        return XmlResourceValues.parsePlurals(eventReader, start, namespacesCollector);
      case ATTR:
        return XmlResourceValues.parseAttr(eventReader, start);
      case PUBLIC:
        return XmlResourceValues.parsePublic(eventReader, start, namespacesCollector);
      case LAYOUT:
      case DIMEN:
      case STRING:
      case BOOL:
      case COLOR:
      case FRACTION:
      case INTEGER:
      case DRAWABLE:
      case ANIM:
      case ANIMATOR:
      case DECLARE_STYLEABLE:
      case INTERPOLATOR:
      case MENU:
      case MIPMAP:
      case RAW:
      case STYLEABLE:
      case TRANSITION:
      case XML:
        return XmlResourceValues.parseSimple(eventReader, resourceType, start, namespacesCollector);
      default:
        throw new XMLStreamException(
            String.format("Unhandled resourceType %s", resourceType), start.getLocation());
    }
  }

  private static ResourceType getResourceType(StartElement start) {
    if (XmlResourceValues.isItem(start)) {
      return ResourceType.getEnum(XmlResourceValues.getElementType(start));
    }
    return ResourceType.getEnum(start.getName().getLocalPart());
  }

  private final DataSource source;
  private final XmlResourceValue xml;
  private final Namespaces namespaces;

  private DataResourceXml(DataSource source, XmlResourceValue xmlValue, Namespaces namespaces) {
    this.source = source;
    this.xml = xmlValue;
    this.namespaces = namespaces;
  }

  public static DataResourceXml createWithNoNamespace(Path sourcePath, XmlResourceValue xml) {
    return createWithNamespaces(sourcePath, xml, ImmutableMap.<String, String>of());
  }

  public static DataResourceXml createWithNoNamespace(DataSource source, XmlResourceValue xml) {
    return new DataResourceXml(source, xml, Namespaces.empty());
  }

  public static DataResourceXml createWithNamespaces(
      Path sourcePath, XmlResourceValue xml, ImmutableMap<String, String> prefixToUri) {
    return createWithNamespaces(sourcePath, xml, Namespaces.from(prefixToUri));
  }

  public static DataResourceXml createWithNamespaces(
      DataSource source, XmlResourceValue xml, Namespaces namespaces) {
    return new DataResourceXml(source, xml, namespaces);
  }

  public static DataResourceXml createWithNamespaces(
      Path sourcePath, XmlResourceValue xml, Namespaces namespaces) {
    return createWithNamespaces(DataSource.of(DependencyInfo.UNKNOWN, sourcePath), xml, namespaces);
  }

  @Override
  public DataSource source() {
    return source;
  }

  @Override
  public int hashCode() {
    return Objects.hash(source, xml, namespaces);
  }

  @Override
  public boolean equals(Object obj) {
    if (!(obj instanceof DataResourceXml)) {
      return false;
    }
    DataResourceXml other = (DataResourceXml) obj;
    return Objects.equals(source, other.source)
        && Objects.equals(xml, other.xml)
        && Objects.equals(namespaces, other.namespaces);
  }

  @Override
  public String toString() {
    return MoreObjects.toStringHelper(getClass())
        .add("source", source)
        .add("xml", xml)
        .add("namespaces", namespaces)
        .toString();
  }

  @Override
  public void writeResource(FullyQualifiedName key, AndroidDataWritingVisitor mergedDataWriter) {
    mergedDataWriter.defineNamespacesFor(key, namespaces);
    xml.write(key, source, mergedDataWriter);
  }

  @Override
  public void writeResourceToClass(FullyQualifiedName key, AndroidResourceSymbolSink sink) {
    xml.writeResourceToClass(source().getDependencyInfo(), key, sink);
  }

  @Override
  public int serializeTo(DataSourceTable sourceTable, OutputStream outStream)
      throws IOException {
    return xml.serializeTo(sourceTable.getSourceId(source), namespaces, outStream);
  }

  // TODO(corysmith): Clean up all the casting. The type structure is unclean.
  @Override
  public DataResource combineWith(DataResource resource) {
    if (!(resource instanceof DataResourceXml)) {
      throw new IllegalArgumentException(resource + " is not combinable with " + this);
    }
    DataResourceXml xmlResource = (DataResourceXml) resource;
    return createWithNamespaces(
        source.combine(xmlResource.source),
        xml.combineWith(xmlResource.xml),
        namespaces.union(xmlResource.namespaces));
  }

  @Override
  public DataResource overwrite(DataResource resource) {
    if (equals(resource)) {
      return this;
    }
    return createWithNamespaces(source.overwrite(resource.source()), xml, namespaces);
  }

  @Override
  public DataValue update(DataSource source) {
    return createWithNamespaces(source, xml, namespaces);
  }

  @Override
  public String asConflictString() {
    return xml.asConflictStringWith(source);
  }

  @Override
  public boolean valueEquals(DataValue value) {
    if (!(value instanceof DataResourceXml)) {
      return false;
    }
    DataResourceXml other = (DataResourceXml) value;
    return Objects.equals(xml, other.xml);
  }

  @Override
  public int compareMergePriorityTo(DataValue value) {
    Preconditions.checkNotNull(value);
    if (!(value instanceof DataResourceXml)) {
      // This is an ambiguous conflict; return 0 meaning neither has priority.
      return 0;
    }
    DataResourceXml other = (DataResourceXml) value;
    return xml.compareMergePriorityTo(other.xml);
  }

  @Override
  public Visibility getVisibility() {
    return xml.getVisibility();
  }

  @Override
  public ImmutableList<Reference> getReferencedResources() {
    return xml.getReferencedResources();
  }
}
