// 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());
}
