// 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 Predicate<E> = bool Function(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 bool 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 bool 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 bool startsWith2(String str, int start, int c1, int c2) {
    return str.length - start >= 2 &&
        str.codeUnitAt(start) == c1 &&
        str.codeUnitAt(start + 1) == c2;
  }

  static bool 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 bool 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 bool 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 bool 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 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 const int __nextId = 0;

  final String id;

  UUID(this.id);

  @override
  String toString() => id;

  static UUID randomUUID() => UUID((__nextId).toString());
}
