// Copyright (c) 2022, 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 'dart:math' as math;

import '../../context.dart';

import 'core.dart';

extension StringChecks on Subject<String> {
  /// Expects that the value contains [pattern] according to [String.contains];
  void contains(Pattern pattern) {
    context.expect(() => prefixFirst('contains ', literal(pattern)), (actual) {
      if (actual.contains(pattern)) return null;
      return Rejection(
        which: prefixFirst('Does not contain ', literal(pattern)),
      );
    });
  }

  Subject<int> get length => has((m) => m.length, 'length');

  void isEmpty() {
    context.expect(() => const ['is empty'], (actual) {
      if (actual.isEmpty) return null;
      return Rejection(which: ['is not empty']);
    });
  }

  void isNotEmpty() {
    context.expect(() => const ['is not empty'], (actual) {
      if (actual.isNotEmpty) return null;
      return Rejection(which: ['is empty']);
    });
  }

  void startsWith(Pattern other) {
    context.expect(() => prefixFirst('starts with ', literal(other)), (actual) {
      if (actual.startsWith(other)) return null;
      return Rejection(
        which: prefixFirst('does not start with ', literal(other)),
      );
    });
  }

  void endsWith(String other) {
    context.expect(() => prefixFirst('ends with ', literal(other)), (actual) {
      if (actual.endsWith(other)) return null;
      return Rejection(
        which: prefixFirst('does not end with ', literal(other)),
      );
    });
  }

  /// Expects that the string matches the pattern [expected].
  ///
  /// Fails if [expected] returns an empty result from calling `allMatches` with
  /// the value.
  ///
  /// ```
  /// check(actual).matchesPattern('abc');
  /// check(actual).matchesPattern(RegExp(r'\d'));
  /// ```
  void matchesPattern(Pattern expected) {
    context.expect(() => prefixFirst('matches ', literal(expected)), (actual) {
      if (expected.allMatches(actual).isNotEmpty) return null;
      return Rejection(
        which: prefixFirst('does not match ', literal(expected)),
      );
    });
  }

  /// Expects that the `String` contains each of the sub strings in expected
  /// in the given order, with any content between them.
  ///
  /// For example, the following will succeed:
  ///
  ///     check('abcdefg').containsInOrder(['a','e']);
  void containsInOrder(Iterable<String> expected) {
    context.expect(
      () => prefixFirst('contains, in order: ', literal(expected)),
      (actual) {
        var fromIndex = 0;
        for (var s in expected) {
          var index = actual.indexOf(s, fromIndex);
          if (index < 0) {
            return Rejection(
              which: [
                ...prefixFirst(
                  'does not have a match for the substring ',
                  literal(s),
                ),
                if (fromIndex != 0)
                  'following the other matches up to character $fromIndex',
              ],
            );
          }
          fromIndex = index + s.length;
        }
        return null;
      },
    );
  }

  /// Expects that the `String` contains exactly the same code units as
  /// [expected].
  void equals(String expected) {
    context.expect(
      () => prefixFirst('equals ', literal(expected)),
      (actual) => _findDifference(actual, expected),
    );
  }

  /// Expects that the `String` contains the same characters as [expected] if
  /// both were lower case.
  void equalsIgnoringCase(String expected) {
    context.expect(
      () => prefixFirst('equals ignoring case ', literal(expected)),
      (actual) => _findDifference(
        actual.toLowerCase(),
        expected.toLowerCase(),
        actual,
        expected,
      ),
    );
  }

  /// Expects that the `String` contains the same content as [expected],
  /// ignoring differences in whitsepace.
  ///
  /// All runs of whitespace characters are collapsed to a single space, and
  /// leading and traiilng whitespace are removed before comparison.
  ///
  /// For example the following will succeed:
  ///
  ///     check(' hello   world ').equalsIgnoringWhitespace('hello world');
  ///
  /// While the following will fail:
  ///
  ///     check('helloworld').equalsIgnoringWhitespace('hello world');
  ///     check('he llo world').equalsIgnoringWhitespace('hello world');
  void equalsIgnoringWhitespace(String expected) {
    context.expect(
      () => prefixFirst('equals ignoring whitespace ', literal(expected)),
      (actual) {
        final collapsedActual = _collapseWhitespace(actual);
        final collapsedExpected = _collapseWhitespace(expected);
        return _findDifference(
          collapsedActual,
          collapsedExpected,
          collapsedActual,
          collapsedExpected,
        );
      },
    );
  }
}

Rejection? _findDifference(
  String actual,
  String expected, [
  String? actualDisplay,
  String? expectedDisplay,
]) {
  if (actual == expected) return null;
  final escapedActual = escape(actual);
  final escapedExpected = escape(expected);
  final escapedActualDisplay = actualDisplay != null
      ? escape(actualDisplay)
      : escapedActual;
  final escapedExpectedDisplay = expectedDisplay != null
      ? escape(expectedDisplay)
      : escapedExpected;
  final minLength = math.min(escapedActual.length, escapedExpected.length);
  var i = 0;
  for (; i < minLength; i++) {
    if (escapedActual.codeUnitAt(i) != escapedExpected.codeUnitAt(i)) {
      break;
    }
  }
  if (i == minLength) {
    if (escapedExpected.length < escapedActual.length) {
      if (expected.isEmpty) {
        return Rejection(which: ['is not the empty string']);
      }
      return Rejection(
        which: [
          'is too long with unexpected trailing characters:',
          _trailing(escapedActualDisplay, i),
        ],
      );
    } else {
      if (actual.isEmpty) {
        return Rejection(
          actual: ['an empty string'],
          which: [
            'is missing all expected characters:',
            _trailing(escapedExpectedDisplay, 0),
          ],
        );
      }
      return Rejection(
        which: [
          'is too short with missing trailing characters:',
          _trailing(escapedExpectedDisplay, i),
        ],
      );
    }
  } else {
    final indentation = ' ' * (i > 10 ? 14 : i);
    return Rejection(
      which: [
        'differs at offset $i:',
        '${_leading(escapedExpectedDisplay, i)}'
            '${_trailing(escapedExpectedDisplay, i)}',
        '${_leading(escapedActualDisplay, i)}'
            '${_trailing(escapedActualDisplay, i)}',
        '$indentation^',
      ],
    );
  }
}

/// The truncated beginning of [s] up to the [end] character.
String _leading(String s, int end) =>
    (end > 10) ? '... ${s.substring(end - 10, end)}' : s.substring(0, end);

/// The truncated remainder of [s] starting at the [start] character.
String _trailing(String s, int start) => (start + 10 > s.length)
    ? s.substring(start)
    : '${s.substring(start, start + 10)} ...';

/// Utility function to collapse whitespace runs to single spaces
/// and strip leading/trailing whitespace.
String _collapseWhitespace(String string) {
  var result = StringBuffer();
  var skipSpace = true;
  for (var i = 0; i < string.length; i++) {
    var character = string[i];
    if (_isWhitespace(character)) {
      if (!skipSpace) {
        result.write(' ');
        skipSpace = true;
      }
    } else {
      result.write(character);
      skipSpace = false;
    }
  }
  return result.toString().trim();
}

bool _isWhitespace(String ch) =>
    ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
