// 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 markerIndent = ' ' * (i > 10 ? 14 : i);
    return Rejection(
      which: [
        'differs at offset $i:',
        ...indent([
          '${_leading(escapedExpectedDisplay, i)}'
              '${_trailing(escapedExpectedDisplay, i)}',
          '${_leading(escapedActualDisplay, i)}'
              '${_trailing(escapedActualDisplay, i)}',
          '$markerIndent^',
        ]),
      ],
    );
  }
}

/// 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';
