// Copyright 2015 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 com.android.builder.core.VariantType;
import com.android.manifmerger.ManifestMerger2;
import com.android.manifmerger.ManifestMerger2.MergeType;
import com.android.repository.Revision;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.common.options.Converter;
import com.google.devtools.common.options.EnumConverter;
import com.google.devtools.common.options.OptionsParsingException;
import java.io.File;
import java.lang.reflect.ParameterizedType;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Some convenient converters used by android actions. Note: These are specific to android actions.
 */
public final class Converters {
  private static final Converter<String> IDENTITY_CONVERTER = new Converter<String>() {
    @Override public String convert(String input) {
      return input;
    }

    @Override public String getTypeDescription() {
      return "a string";
    }
  };

  /**
   * Converter for {@link UnvalidatedAndroidData}. Relies on
   * {@code UnvalidatedAndroidData#valueOf(String)} to perform conversion and validation.
   */
  public static class UnvalidatedAndroidDataConverter implements Converter<UnvalidatedAndroidData> {

    @Override
    public UnvalidatedAndroidData convert(String input) throws OptionsParsingException {
      try {
        return UnvalidatedAndroidData.valueOf(input);
      } catch (IllegalArgumentException e) {
        throw new OptionsParsingException(
            String.format("invalid UnvalidatedAndroidData: %s", e.getMessage()), e);
      }
    }

    @Override
    public String getTypeDescription() {
      return "unvalidated android data in the format " + UnvalidatedAndroidData.EXPECTED_FORMAT;
    }
  }

  /**
   * Converter for {@link UnvalidatedAndroidDirectories}.
   */
  public static class UnvalidatedAndroidDirectoriesConverter
      implements Converter<UnvalidatedAndroidDirectories> {

    @Override
    public UnvalidatedAndroidDirectories convert(String input) throws OptionsParsingException {
      try {
        return UnvalidatedAndroidDirectories.valueOf(input);
      } catch (IllegalArgumentException e) {
        throw new OptionsParsingException(
            String.format("invalid UnvalidatedAndroidDirectories: %s", e.getMessage()), e);
      }
    }

    @Override
    public String getTypeDescription() {
      return "unvalidated android directories in the format "
          + UnvalidatedAndroidDirectories.EXPECTED_FORMAT;
    }
  }

  /**
   * Converter for a list of {@link DependencyAndroidData}. Relies on
   * {@code DependencyAndroidData#valueOf(String)} to perform conversion and validation.
   */
  public static class DependencyAndroidDataListConverter
      implements Converter<List<DependencyAndroidData>> {

    @Override
    public List<DependencyAndroidData> convert(String input) throws OptionsParsingException {
      if (input.isEmpty()) {
        return ImmutableList.of();
      }
      try {
        ImmutableList.Builder<DependencyAndroidData> builder = ImmutableList.builder();
        for (String item : input.split(",")) {
          builder.add(DependencyAndroidData.valueOf(item));
        }
        return builder.build();
      } catch (IllegalArgumentException e) {
        throw new OptionsParsingException(
            String.format("invalid DependencyAndroidData: %s", e.getMessage()), e);
      }
    }

    @Override
    public String getTypeDescription() {
      return "a list of dependency android data in the format "
          + DependencyAndroidData.EXPECTED_FORMAT + "[,...]";
    }
  }

  /**
   * Converter for a {@link SerializedAndroidData}.
   */
  public static class SerializedAndroidDataConverter implements Converter<SerializedAndroidData> {

    @Override
    public SerializedAndroidData convert(String input) throws OptionsParsingException {
      try {
        return SerializedAndroidData.valueOf(input);
      } catch (IllegalArgumentException e) {
        throw new OptionsParsingException(
            String.format("invalid SerializedAndroidData: %s", e.getMessage()), e);
      }
    }

    @Override
    public String getTypeDescription() {
      return "preparsed android data in the format " + SerializedAndroidData.EXPECTED_FORMAT;
    }
  }

  /**
   * Converter for a list of {@link SerializedAndroidData}.
   */
  public static class SerializedAndroidDataListConverter
      implements Converter<List<SerializedAndroidData>> {

    @Override
    public List<SerializedAndroidData> convert(String input) throws OptionsParsingException {
      if (input.isEmpty()) {
        return ImmutableList.of();
      }
      try {
        ImmutableList.Builder<SerializedAndroidData> builder = ImmutableList.builder();
        for (String entry : input.split("&")) {
          builder.add(SerializedAndroidData.valueOf(entry));
        }
        return builder.build();
      } catch (IllegalArgumentException e) {
        throw new OptionsParsingException(
            String.format("invalid SerializedAndroidData: %s", e.getMessage()), e);
      }
    }

    @Override
    public String getTypeDescription() {
      return "a list of preparsed android data in the format "
          + SerializedAndroidData.EXPECTED_FORMAT + "[&...]";
    }
  }

  /**
   * Converter for a list of {@link DependencySymbolFileProvider}. Relies on
   * {@code DependencySymbolFileProvider#valueOf(String)} to perform conversion and validation.
   */
  public static class DependencySymbolFileProviderListConverter
      implements Converter<List<DependencySymbolFileProvider>> {

    @Override
    public List<DependencySymbolFileProvider> convert(String input) throws OptionsParsingException {
      if (input.isEmpty()) {
        return ImmutableList.<DependencySymbolFileProvider>of();
      }
      try {
        ImmutableList.Builder<DependencySymbolFileProvider> builder = ImmutableList.builder();
        for (String item : input.split(",")) {
          builder.add(DependencySymbolFileProvider.valueOf(item));
        }
        return builder.build();
      } catch (IllegalArgumentException e) {
        throw new OptionsParsingException(
            String.format("invalid DependencyAndroidData: %s", e.getMessage()), e);
      }
    }

    @Override
    public String getTypeDescription() {
      return String.format("a list of dependency android data in the format: %s[%s]",
          DependencySymbolFileProvider.commandlineFormat("1"),
          DependencySymbolFileProvider.commandlineFormat("2"));
    }
  }

  /**
   * Converter for {@link Revision}. Relies on {@code Revision#parseRevision(String)} to
   * perform conversion and validation.
   */
  public static class RevisionConverter implements Converter<Revision> {

    @Override
    public Revision convert(String input) throws OptionsParsingException {
      try {
        return Revision.parseRevision(input);
      } catch (NumberFormatException e) {
        throw new OptionsParsingException(e.getMessage());
      }
    }

    @Override
    public String getTypeDescription() {
      return "a revision number";
    }
  }

  /** Validating converter for Paths. A Path is considered valid if it resolves to a file. */
  public static class PathConverter implements Converter<Path> {

    private final boolean mustExist;

    public PathConverter() {
      this.mustExist = false;
    }

    protected PathConverter(boolean mustExist) {
      this.mustExist = mustExist;
    }

    @Override
    public Path convert(String input) throws OptionsParsingException {
      try {
        Path path = FileSystems.getDefault().getPath(input);
        if (mustExist && !Files.exists(path)) {
          throw new OptionsParsingException(
              String.format("%s is not a valid path: it does not exist.", input));
        }
        return path;
      } catch (InvalidPathException e) {
        throw new OptionsParsingException(
            String.format("%s is not a valid path: %s.", input, e.getMessage()), e);
      }
    }

    @Override
    public String getTypeDescription() {
      return "a valid filesystem path";
    }
  }

  /**
   * Validating converter for Paths. A Path is considered valid if it resolves to a file and exists.
   */
  public static class ExistingPathConverter extends PathConverter {
    public ExistingPathConverter() {
      super(true);
    }
  }

  /** Converter for {@link VariantType}. */
  public static class VariantTypeConverter extends EnumConverter<VariantType> {
    public VariantTypeConverter() {
      super(VariantType.class, "variant type");
    }
  }

  /** Converter for {@link ManifestMerger2}.{@link MergeType}. */
  public static class MergeTypeConverter
      extends EnumConverter<MergeType> {
    public MergeTypeConverter() {
      super(MergeType.class, "merge type");
    }
  }

  /**
   * Validating converter for a list of Paths.
   * A Path is considered valid if it resolves to a file.
   */
  public static class PathListConverter implements Converter<List<Path>> {

    private final PathConverter baseConverter;

    public PathListConverter() {
      this(false);
    }

    protected PathListConverter(boolean mustExist) {
      baseConverter = new PathConverter(mustExist);
    }

    @Override
    public List<Path> convert(String input) throws OptionsParsingException {
      List<Path> list = new ArrayList<>();
      for (String piece : input.split(File.pathSeparator)) {
        if (!piece.isEmpty()) {
          list.add(baseConverter.convert(piece));
        }
      }
      return Collections.unmodifiableList(list);
    }

    @Override
    public String getTypeDescription() {
      return "a colon-separated list of paths";
    }
  }

  /**
   * Validating converter for a list of Paths. The list is considered valid if all Paths resolve to
   * a file that exists.
   */
  public static class ExistingPathListConverter extends PathListConverter {
    public ExistingPathListConverter() {
      super(true);
    }
  }

  // Commas that are not escaped by a backslash.
  private static final String UNESCAPED_COMMA_REGEX = "(?<!\\\\)\\,";
  // Colons that are not escaped by a backslash.
  private static final String UNESCAPED_COLON_REGEX = "(?<!\\\\)\\:";

  private static String unescapeInput(String input) {
    return input.replace("\\:", ":").replace("\\,", ",");
  }

  /**
   * A converter for dictionary arguments of the format key:value[,key:value]*. The keys and values
   * may contain colons and commas as long as they are escaped with a backslash.
   */
  private abstract static class DictionaryConverter<K, V> implements Converter<Map<K, V>> {
    private final Converter<K> keyConverter;
    private final Converter<V> valueConverter;

    public DictionaryConverter(Converter<K> keyConverter, Converter<V> valueConverter) {
      this.keyConverter = keyConverter;
      this.valueConverter = valueConverter;
    }

    @Override
    public Map<K, V> convert(String input) throws OptionsParsingException {
      if (input.isEmpty()) {
        return ImmutableMap.of();
      }
      Map<K, V> map = new LinkedHashMap<>();
      // Only split on comma and colon that are not escaped with a backslash
      for (String entry : input.split(UNESCAPED_COMMA_REGEX)) {
        String[] entryFields = entry.split(UNESCAPED_COLON_REGEX, -1);
        if (entryFields.length < 2) {
          throw new OptionsParsingException(String.format(
              "Dictionary entry [%s] does not contain both a key and a value.",
              entry));
        } else if (entryFields.length > 2) {
          throw new OptionsParsingException(String.format(
              "Dictionary entry [%s] contains too many fields.",
              entry));
        }
        // Unescape any comma or colon that is not a key or value separator.
        String keyString = unescapeInput(entryFields[0]);
        K key = keyConverter.convert(keyString);
        if (map.containsKey(key)) {
          throw new OptionsParsingException(String.format(
              "Dictionary already contains the key [%s].",
              keyString));
        }
        // Unescape any comma or colon that is not a key or value separator.
        String valueString = unescapeInput(entryFields[1]);
        V value = valueConverter.convert(valueString);
        map.put(key, value);
      }
      return ImmutableMap.copyOf(map);
    }

    @Override
    public String getTypeDescription() {
      // Retrieve types of dictionary through reflection to avoid overriding this method in each
      // subclass or passing types to this superclass.
      return String.format(
          "a comma-separated list of colon-separated key value pairs of the types %s and %s",
          ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0],
          ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1]);
    }
  }

  /**
   * A converter for dictionary arguments of the format key:value[,key:value]*. The keys and values
   * may contain colons and commas as long as they are escaped with a backslash. The key and value
   * types are both String.
   */
  public static class StringDictionaryConverter extends DictionaryConverter<String, String> {
    public StringDictionaryConverter() {
      super(IDENTITY_CONVERTER, IDENTITY_CONVERTER);
    }
    // The way {@link OptionsData} checks for generic types requires convert to have literal type
    // parameters and not argument type parameters.
    @Override public Map<String, String> convert(String input) throws OptionsParsingException {
      return super.convert(input);
    }
  }

  /**
   * A converter for dictionary arguments of the format key:value[,key:value]*. The keys and values
   * may contain colons and commas as long as they are escaped with a backslash. The key type is
   * Path and the value type is String.
   */
  public static class PathStringDictionaryConverter extends DictionaryConverter<Path, String> {
    public PathStringDictionaryConverter() {
      super(new PathConverter(), IDENTITY_CONVERTER);
    }
    // The way {@link OptionsData} checks for generic types requires convert to have literal type
    // parameters and not argument type parameters.
    @Override public Map<Path, String> convert(String input) throws OptionsParsingException {
      return super.convert(input);
    }
  }

  /**
   * A converter for dictionary arguments of the format key:value[,key:value]*. The keys and values
   * may contain colons and commas as long as they are escaped with a backslash. The key type is
   * Path and the value type is String.
   */
  public static class ExistingPathStringDictionaryConverter
      extends DictionaryConverter<Path, String> {
    public ExistingPathStringDictionaryConverter() {
      super(new ExistingPathConverter(), IDENTITY_CONVERTER);
    }
    // The way {@link OptionsData} checks for generic types requires convert to have literal type
    // parameters and not argument type parameters.
    @Override public Map<Path, String> convert(String input) throws OptionsParsingException {
      return super.convert(input);
    }
  }
}
