// Copyright (c) 2014, the Dart 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.

import 'package:analyzer/src/generated/interner.dart';
import 'package:analyzer/src/generated/java_core.dart';

export 'package:analyzer/exception/exception.dart';

/**
 * A predicate is a one-argument function that returns a boolean value.
 */
typedef bool Predicate<E>(E argument);

class FileNameUtilities {
  static String getExtension(String fileName) {
    if (fileName == null) {
      return "";
    }
    int index = fileName.lastIndexOf('.');
    if (index >= 0) {
      return fileName.substring(index + 1);
    }
    return "";
  }
}

class StringUtilities {
  static const String EMPTY = '';
  static const List<String> EMPTY_ARRAY = <String>[];

  static Interner INTERNER = NullInterner();

  /**
   * Compute line starts for the given [content].
   * Lines end with `\r`, `\n` or `\r\n`.
   */
  static List<int> computeLineStarts(String content) {
    List<int> lineStarts = <int>[0];
    int length = content.length;
    int unit;
    for (int index = 0; index < length; index++) {
      unit = content.codeUnitAt(index);
      // Special-case \r\n.
      if (unit == 0x0D /* \r */) {
        // Peek ahead to detect a following \n.
        if ((index + 1 < length) && content.codeUnitAt(index + 1) == 0x0A) {
          // Line start will get registered at next index at the \n.
        } else {
          lineStarts.add(index + 1);
        }
      }
      // \n
      if (unit == 0x0A) {
        lineStarts.add(index + 1);
      }
    }
    return lineStarts;
  }

  static endsWith3(String str, int c1, int c2, int c3) {
    var length = str.length;
    return length >= 3 &&
        str.codeUnitAt(length - 3) == c1 &&
        str.codeUnitAt(length - 2) == c2 &&
        str.codeUnitAt(length - 1) == c3;
  }

  static endsWithChar(String str, int c) {
    int length = str.length;
    return length > 0 && str.codeUnitAt(length - 1) == c;
  }

  static int indexOf1(String str, int start, int c) {
    int index = start;
    int last = str.length;
    while (index < last) {
      if (str.codeUnitAt(index) == c) {
        return index;
      }
      index++;
    }
    return -1;
  }

  static int indexOf2(String str, int start, int c1, int c2) {
    int index = start;
    int last = str.length - 1;
    while (index < last) {
      if (str.codeUnitAt(index) == c1 && str.codeUnitAt(index + 1) == c2) {
        return index;
      }
      index++;
    }
    return -1;
  }

  static int indexOf4(
      String string, int start, int c1, int c2, int c3, int c4) {
    int index = start;
    int last = string.length - 3;
    while (index < last) {
      if (string.codeUnitAt(index) == c1 &&
          string.codeUnitAt(index + 1) == c2 &&
          string.codeUnitAt(index + 2) == c3 &&
          string.codeUnitAt(index + 3) == c4) {
        return index;
      }
      index++;
    }
    return -1;
  }

  static int indexOf5(
      String str, int start, int c1, int c2, int c3, int c4, int c5) {
    int index = start;
    int last = str.length - 4;
    while (index < last) {
      if (str.codeUnitAt(index) == c1 &&
          str.codeUnitAt(index + 1) == c2 &&
          str.codeUnitAt(index + 2) == c3 &&
          str.codeUnitAt(index + 3) == c4 &&
          str.codeUnitAt(index + 4) == c5) {
        return index;
      }
      index++;
    }
    return -1;
  }

  /**
   * Return the index of the first not letter/digit character in the [string]
   * that is at or after the [startIndex]. Return the length of the [string] if
   * all characters to the end are letters/digits.
   */
  static int indexOfFirstNotLetterDigit(String string, int startIndex) {
    int index = startIndex;
    int last = string.length;
    while (index < last) {
      int c = string.codeUnitAt(index);
      if (!Character.isLetterOrDigit(c)) {
        return index;
      }
      index++;
    }
    return last;
  }

  static String intern(String string) => INTERNER.intern(string);
  static bool isEmpty(String s) {
    return s == null || s.isEmpty;
  }

  static bool isTagName(String s) {
    if (s == null || s.isEmpty) {
      return false;
    }
    int sz = s.length;
    for (int i = 0; i < sz; i++) {
      int c = s.codeUnitAt(i);
      if (!Character.isLetter(c)) {
        if (i == 0) {
          return false;
        }
        if (!Character.isDigit(c) && c != 0x2D) {
          return false;
        }
      }
    }
    return true;
  }

  /**
   * Produce a string containing all of the names in the given array, surrounded by single quotes,
   * and separated by commas. The list must contain at least two elements.
   *
   * @param names the names to be printed
   * @return the result of printing the names
   */
  static String printListOfQuotedNames(List<String> names) {
    if (names == null) {
      throw ArgumentError("The list must not be null");
    }
    int count = names.length;
    if (count < 2) {
      throw ArgumentError("The list must contain at least two names");
    }
    StringBuffer buffer = StringBuffer();
    buffer.write("'");
    buffer.write(names[0]);
    buffer.write("'");
    for (int i = 1; i < count - 1; i++) {
      buffer.write(", '");
      buffer.write(names[i]);
      buffer.write("'");
    }
    buffer.write(" and '");
    buffer.write(names[count - 1]);
    buffer.write("'");
    return buffer.toString();
  }

  static startsWith2(String str, int start, int c1, int c2) {
    return str.length - start >= 2 &&
        str.codeUnitAt(start) == c1 &&
        str.codeUnitAt(start + 1) == c2;
  }

  static startsWith3(String str, int start, int c1, int c2, int c3) {
    return str.length - start >= 3 &&
        str.codeUnitAt(start) == c1 &&
        str.codeUnitAt(start + 1) == c2 &&
        str.codeUnitAt(start + 2) == c3;
  }

  static startsWith4(String str, int start, int c1, int c2, int c3, int c4) {
    return str.length - start >= 4 &&
        str.codeUnitAt(start) == c1 &&
        str.codeUnitAt(start + 1) == c2 &&
        str.codeUnitAt(start + 2) == c3 &&
        str.codeUnitAt(start + 3) == c4;
  }

  static startsWith5(
      String str, int start, int c1, int c2, int c3, int c4, int c5) {
    return str.length - start >= 5 &&
        str.codeUnitAt(start) == c1 &&
        str.codeUnitAt(start + 1) == c2 &&
        str.codeUnitAt(start + 2) == c3 &&
        str.codeUnitAt(start + 3) == c4 &&
        str.codeUnitAt(start + 4) == c5;
  }

  static startsWith6(
      String str, int start, int c1, int c2, int c3, int c4, int c5, int c6) {
    return str.length - start >= 6 &&
        str.codeUnitAt(start) == c1 &&
        str.codeUnitAt(start + 1) == c2 &&
        str.codeUnitAt(start + 2) == c3 &&
        str.codeUnitAt(start + 3) == c4 &&
        str.codeUnitAt(start + 4) == c5 &&
        str.codeUnitAt(start + 5) == c6;
  }

  static startsWithChar(String str, int c) {
    return str.isNotEmpty && str.codeUnitAt(0) == c;
  }

  static String substringBefore(String str, String separator) {
    if (str == null || str.isEmpty) {
      return str;
    }
    if (separator == null) {
      return str;
    }
    int pos = str.indexOf(separator);
    if (pos < 0) {
      return str;
    }
    return str.substring(0, pos);
  }

  static String substringBeforeChar(String str, int c) {
    if (isEmpty(str)) {
      return str;
    }
    int pos = indexOf1(str, 0, c);
    if (pos < 0) {
      return str;
    }
    return str.substring(0, pos);
  }
}

class UUID {
  static int __nextId = 0;
  final String id;
  UUID(this.id);
  String toString() => id;
  static UUID randomUUID() => UUID((__nextId).toString());
}
