// Copyright (c) 2017, 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_plugin/src/utilities/charcodes.dart';

/// Returns a list of the words from which the given camel case [string] is
/// composed.
///
/// 'getCamelWords' => ['get', 'Camel', 'Words']
/// 'getHTMLText' => ['get', 'HTML', 'Text']
List<String> getCamelWords(String? string) {
  if (string == null || string.isEmpty) {
    return const <String>[];
  }
  var parts = <String>[];
  var wasLowerCase = false;
  var wasUpperCase = false;
  var wordStart = 0;
  for (var i = 0; i < string.length; i++) {
    var c = string.codeUnitAt(i);
    var newLowerCase = isLowerCase(c);
    var newUpperCase = isUpperCase(c);
    // myWord
    // | ^
    if (wasLowerCase && newUpperCase) {
      parts.add(string.substring(wordStart, i));
      wordStart = i;
    }
    // myHTMLText
    //   |   ^
    if (wasUpperCase &&
        newUpperCase &&
        i + 1 < string.length &&
        isLowerCase(string.codeUnitAt(i + 1))) {
      parts.add(string.substring(wordStart, i));
      wordStart = i;
    }
    wasLowerCase = newLowerCase;
    wasUpperCase = newUpperCase;
  }
  parts.add(string.substring(wordStart));
  return parts;
}

/// Return `true` if the given [string] is either `null` or empty.
bool isEmpty(String? string) => string == null || string.isEmpty;

/// Return `true` if the given [character] is a lowercase ASCII character.
bool isLowerCase(int character) => character >= $a && character <= $z;

/// Return `true` if the given [character] is an uppercase ASCII character.
bool isUpperCase(int character) => character >= $A && character <= $Z;

/// If the given [string] starts with the text to [remove], then return the
/// portion of the string after the text to remove. Otherwise, return the
/// original string unmodified.
String? removeStart(String? string, String? remove) {
  if (string == null || string.isEmpty) {
    return string;
  }
  if (remove == null || remove.isEmpty) {
    return string;
  }
  if (string.startsWith(remove)) {
    return string.substring(remove.length);
  }
  return string;
}
