// 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.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 ImmutableList.Builder<>();
    for (String pathString : control.getSourceFileList()) {
      sourceFilePathsBuilder.add(fileSystem.getPath(pathString));
    }
    ImmutableList.Builder<Path> immutableSourceFilePathsBuilder = new ImmutableList.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;
    }
  }
}
