// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils;

import com.android.tools.r8.errors.Unreachable;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StringUtils {
  public static char[] EMPTY_CHAR_ARRAY = {};
  public static final String[] EMPTY_ARRAY = {};
  public static final String LINE_SEPARATOR = System.getProperty("line.separator");
  public static final char BOM = '\uFEFF';

  public enum BraceType {
    PARENS,
    SQUARE,
    TUBORG,
    NONE;

    public String left() {
      switch (this) {
        case PARENS: return "(";
        case SQUARE: return "[";
        case TUBORG: return "{";
        case NONE: return "";
        default: throw new Unreachable("Invalid brace type: " + this);
      }
    }

    public String right() {
      switch (this) {
        case PARENS: return ")";
        case SQUARE: return "]";
        case TUBORG: return "}";
        case NONE: return "";
        default: throw new Unreachable("Invalid brace type: " + this);
      }
    }
  }

  public static String toASCIIString(String s) {
    StringBuilder builder = new StringBuilder();
    for (char ch : s.toCharArray()) {
      if (0x1f < ch && ch < 0x7f) {  // 0 - 0x1f and 0x7f are control characters.
        builder.append(ch);
      } else {
        builder.append("\\u").append(StringUtils.hexString(ch, 4, false));
      }
    }
    return builder.toString();
  }

  // Utilities for splitting (and avoiding errorprone String.split).

  /**
   * Iterate over the substrings of a string split by a single char separator.
   *
   * <p>No special treatment of whitespace. No occurrence of the separator will appear in any
   * split-off substring. Given N occurrences of the separator, the resulting callback will be
   * called N+1 times.
   */
  public static void splitForEach(String string, char separator, Consumer<String> fn) {
    int length = string.length();
    int start = 0;
    for (int i = 0; i < length; i++) {
      char c = string.charAt(i);
      if (c == separator) {
        fn.accept(string.substring(start, i));
        start = i + 1;
      }
    }
    fn.accept(string.substring(start));
  }

  /**
   * Split a string by a single char separator.
   *
   * <p>No special treatment of whitespace. No occurrence of the separator will appear in any
   * split-off substring. Given N occurrences of the separator, the resulting split list will have
   * size N+1.
   */
  public static List<String> split(String string, char separator) {
    List<String> result = new ArrayList<>();
    splitForEach(string, separator, result::add);
    return result;
  }

  /**
   * Split a string by a single char separator with the requirement on the split size.
   *
   * <p>No special treatment of whitespace. No occurrence of the separator will appear in any
   * split-off substring. Given N occurrences of the separator, the resulting split list will have
   * size N+1.
   *
   * <p>Thus for a valid split with size=N, the result will be an array of length N if and only if
   * the input string has exactly N-1 occurrences of the separator. In any other case the return
   * value is null.
   */
  public static String[] splitKnownSize(String string, char separator, int size) {
    assert size > 1;
    String[] result = new String[size];
    IntBox box = new IntBox(0);
    splitForEach(
        string,
        separator,
        part -> {
          int i = box.getAndIncrement();
          if (i < size) {
            result[i] = part;
          }
        });
    return size == box.get() ? result : null;
  }

  public static boolean appendNonEmpty(
      StringBuilder builder, String pre, Object item, String post) {
    if (item == null) {
      return false;
    }
    String text = item.toString();
    if (!text.isEmpty()) {
      if (pre != null) {
        builder.append(pre);
      }
      builder.append(text);
      if (post != null) {
        builder.append(post);
      }
      return true;
    }
    return false;
  }

  public static StringBuilder appendIndent(StringBuilder builder, String subject, int indent) {
    for (int i = 0; i < indent; i++) {
      builder.append(" ");
    }
    builder.append(subject);
    return builder;
  }

  public static StringBuilder appendLeftPadded(StringBuilder builder, String subject, int width) {
    for (int i = subject.length(); i < width; i++) {
      builder.append(" ");
    }
    builder.append(subject);
    return builder;
  }

  public static StringBuilder appendRightPadded(StringBuilder builder, String subject, int width) {
    builder.append(subject);
    for (int i = subject.length(); i < width; i++) {
      builder.append(" ");
    }
    return builder;
  }

  public static <T> StringBuilder append(StringBuilder builder, Collection<T> collection) {
    return append(builder, collection, ", ", BraceType.PARENS);
  }

  public static <T> StringBuilder append(
      StringBuilder builder, Iterable<T> collection, String seperator, BraceType brace) {
    builder.append(brace.left());
    boolean first = true;
    for (T element : collection) {
      if (first) {
        first = false;
      } else {
        builder.append(seperator);
      }
      builder.append(element);
    }
    builder.append(brace.right());
    return builder;
  }

  public static StringBuilder appendLines(StringBuilder builder, String... lines) {
    for (String line : lines) {
      builder.append(line).append(LINE_SEPARATOR);
    }
    return builder;
  }

  public static String join(String separator, String... strings) {
    return join(separator, Arrays.asList(strings));
  }

  public static <T> String join(String separator, Iterable<T> iterable) {
    return join(separator, iterable, BraceType.NONE);
  }

  public static <T> String join(String separator, Iterable<T> iterable, Function<T, String> fn) {
    return join(separator, iterable, fn, BraceType.NONE);
  }

  public static <T> String join(String separator, Stream<T> stream, Function<T, String> fn) {
    return join(separator, stream.collect(Collectors.toList()), fn, BraceType.NONE);
  }

  public static <T> String join(
      String separator, T[] elements, Function<T, String> fn, BraceType brace) {
    return join(separator, Arrays.asList(elements), fn, brace);
  }

  public static <T> String join(String separator, Iterable<T> iterable, BraceType brace) {
    return join(separator, iterable, Object::toString, brace);
  }

  public static <T> String join(
      String separator, Iterable<T> iterable, Function<T, String> fn, BraceType brace) {
    StringBuilder builder = new StringBuilder();
    append(builder, IterableUtils.transform(iterable, fn), separator, brace);
    return builder.toString();
  }

  public static String lines(List<String> lines) {
    return lines(lines, LINE_SEPARATOR);
  }

  private static String lines(List<String> lines, String lineSeperator) {
    StringBuilder builder = new StringBuilder();
    for (String line : lines) {
      builder.append(line).append(lineSeperator);
    }
    return builder.toString();
  }

  public static String lines(String... lines) {
    return lines(Arrays.asList(lines));
  }

  public static String unixLines(String... lines) {
    return lines(Arrays.asList(lines), "\n");
  }

  public static String withNativeLineSeparator(String s) {
    s = s.replace("\r\n", "\n");
    if (LINE_SEPARATOR.equals("\r\n")) {
      return s.replace("\n", "\r\n");
    } else {
      assert LINE_SEPARATOR.equals("\n");
      return s;
    }
  }

  public static String joinLines(String... lines) {
    return join(LINE_SEPARATOR, lines);
  }

  public static <T> String joinLines(Collection<T> collection) {
    return join(LINE_SEPARATOR, collection, BraceType.NONE);
  }


  public static List<String> splitLines(String content) {
    return splitLines(content, false);
  }

  public static List<String> splitLines(String content, boolean includeTrailingEmptyLine) {
    int length = content.length();
    List<String> lines = new ArrayList<>();
    int start = 0;
    for (int i = 0; i < length; i++) {
      char c = content.charAt(i);
      int end = i;
      if (c == '\r' && i + 1 < length && content.charAt(i + 1) == '\n') {
        ++i;
      } else if (c != '\n') {
        continue;
      }
      lines.add(content.substring(start, end));
      start = i + 1;
    }
    if (start < length) {
      String line = content.substring(start);
      if (includeTrailingEmptyLine || !line.isEmpty()) {
        lines.add(line);
      }
    }
    return lines;
  }

  public static String zeroPrefix(int i, int width) {
    return zeroPrefixString(Integer.toString(i), width);
  }

  private static String zeroPrefixString(String s, int width) {
    String prefix = "0000000000000000";
    assert(width <= prefix.length());
    int prefixLength = width - s.length();
    if (prefixLength > 0) {
      StringBuilder builder = new StringBuilder();
      builder.append(prefix, 0, prefixLength);
      builder.append(s);
      return builder.toString();
    } else {
      return s;
    }
  }

  public static String hexString(int value, int width) {
    return hexString(value, width, true);
  }

  public static String hexString(int value, int width, boolean zeroXPrefix) {
    assert(0 <= width && width <= 8);
    String prefix = zeroXPrefix ? "0x" : "";
    String hex = Integer.toHexString(value);
    if (value >= 0) {
      return prefix + zeroPrefixString(hex, width);
    } else {
      // Negative ints are always formatted as 8 characters.
      assert(hex.length() == 8);
      return prefix + hex;
    }
  }

  public static String hexString(long value, int width) {
    return hexString(value, width, true);
  }

  public static String hexString(long value, int width, boolean zeroXPrefix) {
    assert(0 <= width && width <= 16);
    String prefix = zeroXPrefix ? "0x" : "";
    String hex = Long.toHexString(value);
    if (value >= 0) {
      return prefix + zeroPrefixString(hex, width);
    } else {
      // Negative longs are always formatted as 16 characters.
      assert(hex.length() == 16);
      return prefix + hex;
    }
  }

  public static String computeMD5Hash(String name) {
    byte[] digest = null;
    try {
      MessageDigest m = MessageDigest.getInstance("MD5");
      m.reset();
      m.update(name.getBytes());
      digest = m.digest();
    } catch (NoSuchAlgorithmException e) {
      throw new RuntimeException(e);
    }
    return Arrays.toString(digest);
  }


  public static String times(String string, int count) {
    StringBuilder builder = new StringBuilder();
    while (--count >= 0) {
      builder.append(string);
    }
    return builder.toString();
  }

  public static boolean isBOM(int codePoint) {
    return codePoint == BOM;
  }

  public static boolean isFalsy(String string) {
    return string.equals("0") || string.toLowerCase().equals("false");
  }

  public static boolean isTruthy(String string) {
    return string.equals("1") || string.toLowerCase().equals("true");
  }

  public static boolean isWhitespace(int codePoint) {
    return Character.isWhitespace(codePoint) || isBOM(codePoint);
  }

  public static String stripLeadingBOM(String s) {
    if (s.length() > 0 && s.charAt(0) == StringUtils.BOM) {
      return s.substring(1);
    } else {
      return s;
    }
  }

  public static String trim(String s) {
    int beginIndex = 0;
    int endIndex = s.length();
    while (beginIndex < endIndex && isWhitespace(s.charAt(beginIndex))) {
      beginIndex++;
    }
    while (endIndex - 1 > beginIndex && isWhitespace(s.charAt(endIndex - 1))) {
      endIndex--;
    }
    if (beginIndex > 0 || endIndex < s.length()) {
      return s.substring(beginIndex, endIndex);
    } else {
      return s;
    }
  }

  /** Returns true if {@param s} only contains the characters [0-9]. */
  public static boolean onlyContainsDigits(String s) {
    for (int i = 0; i < s.length(); i++) {
      char c = s.charAt(i);
      if (!Character.isDigit(c)) {
        return false;
      }
    }
    return true;
  }

  public static char lastChar(String s) {
    return charFromEnd(s, 0);
  }

  public static char charFromEnd(String s, int charsFromEnd) {
    assert s.length() > charsFromEnd;
    return s.charAt(s.length() - (charsFromEnd + 1));
  }

  public static int firstNonWhitespaceCharacter(String string) {
    for (int i = 0; i < string.length(); i++) {
      if (!isWhitespace(string.charAt(i))) {
        return i;
      }
    }
    return string.length();
  }

  public static String replaceAll(String subject, Map<String, String> map) {
    for (Entry<String, String> entry : map.entrySet()) {
      subject = replaceAll(subject, entry.getKey(), entry.getValue());
    }
    return subject;
  }

  public static String replaceAll(String subject, String target, String replacement) {
    return subject.replaceAll(Pattern.quote(target), Matcher.quoteReplacement(replacement));
  }

  public static String quote(String string) {
    return "\"" + string + "\"";
  }

  public static String stacktraceAsString(Throwable throwable) {
    StringWriter sw = new StringWriter();
    throwable.printStackTrace(new PrintWriter(sw));
    return sw.toString();
  }

  public static String capitalize(String stringToCapitalize) {
    if (stringToCapitalize == null || stringToCapitalize.isEmpty()) {
      return stringToCapitalize;
    }
    return stringToCapitalize.substring(0, 1).toUpperCase() + stringToCapitalize.substring(1);
  }

  public static int indexOf(String s, char ch1, char ch2) {
    int i1 = s.indexOf(ch1);
    int i2 = s.indexOf(ch2);
    if (i1 == -1) return i2;
    if (i2 == -1) return i1;
    return Math.min(i1, i2);
  }
}
