// Copyright 2014 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.xcode.plmerge;

import com.dd.plist.BinaryPropertyListWriter;
import com.dd.plist.NSDictionary;
import com.dd.plist.NSObject;
import com.dd.plist.NSString;
import com.dd.plist.PropertyListFormatException;
import com.dd.plist.PropertyListParser;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.Sets;
import com.google.common.io.ByteSource;
import com.google.devtools.build.xcode.plmerge.proto.PlMergeProtos.Control;
import com.google.devtools.build.xcode.util.Equaling;
import com.google.devtools.build.xcode.util.Mapping;
import com.google.devtools.build.xcode.util.Value;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.ParseException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;

/**
 * Utility code for merging project files.
 */
public class PlistMerging extends Value<PlistMerging> {
  private static final String BUNDLE_IDENTIFIER_PLIST_KEY = "CFBundleIdentifier";
  private static final String BUNDLE_IDENTIFIER_DEFAULT = "com.generic.bundleidentifier";
  private static final String BUNDLE_VERSION_PLIST_KEY = "CFBundleVersion";
  private static final String BUNDLE_VERSION_DEFAULT = "1.0.0";
  private static final String BUNDLE_SHORT_VERSION_STRING_PLIST_KEY = "CFBundleShortVersionString";
  private static final String BUNDLE_SHORT_VERSION_STRING_DEFAULT = "1.0";

  /**
   * Exception type thrown when validation of the plist file fails.
   */
  public static class ValidationException extends RuntimeException {
    ValidationException(String message) {
      super(message);
    }
  }

  private final NSDictionary merged;

  /**
   * Wraps a {@code NSDictionary} as a PlistMerging.
   */
  public PlistMerging(NSDictionary merged) {
    super(merged);
    this.merged = merged;
  }

  /**
   * Merges several plist files into a single {@code NSDictionary}. Each file should be a plist (of
   * one of these formats: ASCII, Binary, or XML) that contains an NSDictionary.
   */
  @VisibleForTesting
  static NSDictionary merge(Collection<? extends Path> sourceFilePaths) throws IOException {
    NSDictionary result = new NSDictionary();
    for (Path sourceFilePath : sourceFilePaths) {
      result.putAll(readPlistFile(sourceFilePath));
    }
    return result;
  }

  public static NSDictionary readPlistFile(final Path sourceFilePath) throws IOException {
    ByteSource rawBytes = new Utf8BomSkippingByteSource(sourceFilePath);

    try {
      try (InputStream in = rawBytes.openStream()) {
        return (NSDictionary) PropertyListParser.parse(in);
      } catch (PropertyListFormatException | ParseException e) {
        // If we failed to parse, the plist may implicitly be a map. To handle this, wrap the plist
        // with {}.
        // TODO(bazel-team): Do this in a cleaner way.
        ByteSource concatenated = ByteSource.concat(
            ByteSource.wrap(new byte[] {'{'}),
            rawBytes,
            ByteSource.wrap(new byte[] {'}'}));
        try (InputStream in = concatenated.openStream()) {
          return (NSDictionary) PropertyListParser.parse(in);
        }
      }
    } catch (PropertyListFormatException | ParseException | ParserConfigurationException
        | SAXException e) {
      throw new IOException(e);
    }
  }

  /**
   * Writes the results of a merge operation to a binary plist file.
   * @param plistPath the path of the plist to write in binary format
   */
  public PlistMerging writePlist(Path plistPath) throws IOException {
    try (OutputStream out = Files.newOutputStream(plistPath)) {
      BinaryPropertyListWriter.write(out, merged);
    }
    return this;
  }

  /**
   * Writes the results of a merge operation to an XML plist file.
   * @param plistPath the path of the plist to write in XML format
   */
  public PlistMerging writeXmlPlist(Path plistPath) throws IOException {
    try (OutputStream out = Files.newOutputStream(plistPath)) {
      PropertyListParser.saveAsXML(merged, out);
    }
    return this;
  }

  /**
   * Writes a PkgInfo file based on certain keys in the merged plist.
   * @param pkgInfoPath the path of the PkgInfo file to write. In many iOS apps, this file just
   *     contains the raw string {@code APPL????}.
   */
  public PlistMerging writePkgInfo(Path pkgInfoPath) throws IOException {
    String pkgInfo =
        Mapping.of(merged, "CFBundlePackageType").or(NSObject.wrap("APPL")).toString()
        + Mapping.of(merged, "CFBundleSignature").or(NSObject.wrap("????")).toString();
    Files.write(pkgInfoPath, pkgInfo.getBytes(StandardCharsets.UTF_8));
    return this;
  }

  /**
   * Generates a Plistmerging combining values from sourceFiles and immutableSourceFiles, and
   * modifying them based on substitutions and keysToRemoveIfEmptyString.
   */
  public static PlistMerging from(
      Control control,
      KeysToRemoveIfEmptyString keysToRemoveIfEmptyString)
      throws IOException {

    FileSystem fileSystem = FileSystems.getDefault();

    ImmutableList.Builder<Path> sourceFilePathsBuilder = new Builder<>();
    for (String pathString : control.getSourceFileList()) {
      sourceFilePathsBuilder.add(fileSystem.getPath(pathString));
    }
    ImmutableList.Builder<Path> immutableSourceFilePathsBuilder = new Builder<>();
    for (String pathString : control.getImmutableSourceFileList()) {
      immutableSourceFilePathsBuilder.add(fileSystem.getPath(pathString));
    }

    return from(
        sourceFilePathsBuilder.build(),
        immutableSourceFilePathsBuilder.build(),
        control.getVariableSubstitutionMap(),
        keysToRemoveIfEmptyString,
        Strings.emptyToNull(control.getExecutableName()));
  }

  /**
   * Generates a Plistmerging combining values from sourceFiles and immutableSourceFiles, and
   * modifying them based on subsitutions and keysToRemoveIfEmptyString.
   */
  public static PlistMerging from(
      List<Path> sourceFiles,
      List<Path> immutableSourceFiles,
      Map<String, String> substitutions,
      KeysToRemoveIfEmptyString keysToRemoveIfEmptyString,
      String executableName)
      throws IOException {
    NSDictionary merged = PlistMerging.merge(sourceFiles);
    NSDictionary immutableEntries = PlistMerging.merge(immutableSourceFiles);
    Set<String> conflictingEntries = Sets.intersection(immutableEntries.keySet(), merged.keySet());

    Preconditions.checkArgument(
        conflictingEntries.isEmpty(),
        "The following plist entries may not be overridden, but are present in more than one "
            + "of the input lists: %s",
        conflictingEntries);
    merged.putAll(immutableEntries);

    for (Map.Entry<String, NSObject> entry : merged.entrySet()) {
      if (entry.getValue().toJavaObject() instanceof String) {
        String newValue = substituteEnvironmentVariable(
            substitutions, (String) entry.getValue().toJavaObject());
        merged.put(entry.getKey(), newValue);
      }
    }

    for (String key : keysToRemoveIfEmptyString) {
      if (Equaling.of(Mapping.of(merged, key), Optional.<NSObject>of(new NSString("")))) {
        merged.remove(key);
      }
    }

    // Info.plist files must contain a valid CFBundleVersion and a valid CFBundleShortVersionString,
    // or it will be rejected by Apple.
    // A valid Bundle Version is 18 characters or less, and only contains [0-9.]
    // We know we have an info.plist file as opposed to a strings file if the immutableEntries
    // have any values set.
    // TODO(bazel-team): warn user if we replace their values.
    if (!immutableEntries.isEmpty()) {
      Pattern versionPattern = Pattern.compile("[^0-9.]");
      if (!merged.containsKey(BUNDLE_VERSION_PLIST_KEY)) {
        merged.put(BUNDLE_VERSION_PLIST_KEY, BUNDLE_VERSION_DEFAULT);
      } else {
        NSObject nsVersion = merged.get(BUNDLE_VERSION_PLIST_KEY);
        String version = (String) nsVersion.toJavaObject();
        if (version.length() > 18 || versionPattern.matcher(version).find()) {
          merged.put(BUNDLE_VERSION_PLIST_KEY, BUNDLE_VERSION_DEFAULT);
        }
      }
      if (!merged.containsKey(BUNDLE_SHORT_VERSION_STRING_PLIST_KEY)) {
        merged.put(BUNDLE_SHORT_VERSION_STRING_PLIST_KEY, BUNDLE_SHORT_VERSION_STRING_DEFAULT);
      } else {
        NSObject nsVersion = merged.get(BUNDLE_SHORT_VERSION_STRING_PLIST_KEY);
        String version = (String) nsVersion.toJavaObject();
        if (version.length() > 18 || versionPattern.matcher(version).find()) {
          merged.put(BUNDLE_SHORT_VERSION_STRING_PLIST_KEY, BUNDLE_SHORT_VERSION_STRING_DEFAULT);
        }
      }
    }
    
    PlistMerging result = new PlistMerging(merged);

    if (executableName != null) {
      result.setExecutableName(executableName);
    }

    return result;
  }

  private static String substituteEnvironmentVariable(
      Map<String, String> substitutions, String string) {
    // The substitution is *not* performed recursively.
    for (Map.Entry<String, String> variable : substitutions.entrySet()) {
      String key = variable.getKey();
      String value = variable.getValue();
      string = string
          .replace("${" + key + "}", value)
          .replace("$(" + key + ")", value);
      key = key + ":rfc1034identifier";
      value = convertToRFC1034(value);
      string = string
          .replace("${" + key + "}", value)
          .replace("$(" + key + ")", value);
    }

    return string;
  }

  // Force RFC1034 compliance by changing any "bad" character to a '-'
  // This is essentially equivalent to what Xcode does.
  private static String convertToRFC1034(String value) {
    return value.replaceAll("[^-0-9A-Za-z.]", "-");
  }

  @VisibleForTesting
  NSDictionary asDictionary() {
    return merged;
  }

  /**
   * Sets the given executable name on this merged plist in the {@code CFBundleExecutable}
   * attribute.
   *
   * @param executableName name of the bundle executable
   * @return this plist merging
   * @throws ValidationException if the plist already contains an incompatible
   *    {@code CFBundleExecutable} entry
   */
  public PlistMerging setExecutableName(String executableName) {
    NSString bundleExecutable = (NSString) merged.get("CFBundleExecutable");

    if (bundleExecutable == null) {
      merged.put("CFBundleExecutable", executableName);
    } else if (!executableName.equals(bundleExecutable.getContent())) {
      throw new ValidationException(String.format(
          "Blaze generated the executable %s but the Plist CFBundleExecutable is %s",
          executableName, bundleExecutable));
    }

    return this;
  }
  
  /**
   * Sets the given identifier on this merged plist in the {@code CFBundleIdentifier}
   * attribute.
   *
   * @param primaryIdentifier used to set the bundle identifier or override the existing one from
   *     plist file, can be null
   * @param fallbackIdentifier used to set the bundle identifier if it is not set by plist file or
   *     primary identifier, can be null
   * @return this plist merging
   */
  public PlistMerging setBundleIdentifier(String primaryIdentifier, String fallbackIdentifier) {
    NSString bundleIdentifier = (NSString) merged.get(BUNDLE_IDENTIFIER_PLIST_KEY);

    if (primaryIdentifier != null) {
      merged.put(BUNDLE_IDENTIFIER_PLIST_KEY, convertToRFC1034(primaryIdentifier));
    } else if (bundleIdentifier == null) {
      if (fallbackIdentifier != null) {
        merged.put(BUNDLE_IDENTIFIER_PLIST_KEY, convertToRFC1034(fallbackIdentifier));
      } else {
        // TODO(bazel-team): We shouldn't be generating an info.plist in this case.
        merged.put(BUNDLE_IDENTIFIER_PLIST_KEY, BUNDLE_IDENTIFIER_DEFAULT);
      }
    }

    return this;
  }

  private static class Utf8BomSkippingByteSource extends ByteSource {

    private static final byte[] UTF8_BOM =
        new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF };

    private final Path path;

    public Utf8BomSkippingByteSource(Path path) {
      this.path = path;
    }

    @Override
    public InputStream openStream() throws IOException {
      InputStream stream = new BufferedInputStream(Files.newInputStream(path));
      stream.mark(UTF8_BOM.length);
      byte[] buffer = new byte[UTF8_BOM.length];
      int read = stream.read(buffer);
      stream.reset();

      if (UTF8_BOM.length == read && Arrays.equals(buffer, UTF8_BOM)) {
        stream.skip(UTF8_BOM.length);
      }

      return stream;
    }
  }
}
