// Copyright (c) 2015, 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.

// @dart = 2.7

library dart2js.test.diagnostic_helper;

import 'dart:collection';

import 'package:compiler/compiler.dart' show CompilerDiagnostics, Diagnostic;
import 'package:compiler/src/diagnostics/messages.dart'
    show Message, MessageKind;
import 'package:expect/expect.dart';

class CollectedMessage {
  final Message message;
  final Uri uri;
  final int begin;
  final int end;
  final String text;
  final Diagnostic kind;

  CollectedMessage(
      this.message, this.uri, this.begin, this.end, this.text, this.kind);

  MessageKind get messageKind => message?.kind;

  @override
  String toString() {
    return '${message != null ? message.kind : ''}'
        ':$uri:$begin:$end:$text:$kind';
  }
}

class DiagnosticCollector implements CompilerDiagnostics {
  List<CollectedMessage> messages = <CollectedMessage>[];

  @override
  void report(covariant Message message, Uri uri, int begin, int end,
      String text, Diagnostic kind) {
    messages.add(new CollectedMessage(message, uri, begin, end, text, kind));
  }

  Iterable<CollectedMessage> filterMessagesByKinds(List<Diagnostic> kinds) {
    return messages
        .where((CollectedMessage message) => kinds.contains(message.kind));
  }

  Iterable<CollectedMessage> get errors {
    return filterMessagesByKinds([Diagnostic.ERROR]);
  }

  Iterable<CollectedMessage> get warnings {
    return filterMessagesByKinds([Diagnostic.WARNING]);
  }

  Iterable<CollectedMessage> get hints {
    return filterMessagesByKinds([Diagnostic.HINT]);
  }

  Iterable<CollectedMessage> get infos {
    return filterMessagesByKinds([Diagnostic.INFO]);
  }

  Iterable<CollectedMessage> get crashes {
    return filterMessagesByKinds([Diagnostic.CRASH]);
  }

  Iterable<CollectedMessage> get verboseInfos {
    return filterMessagesByKinds([Diagnostic.VERBOSE_INFO]);
  }

  /// `true` if non-verbose messages has been collected.
  bool get hasRegularMessages {
    return messages.any((m) => m.kind != Diagnostic.VERBOSE_INFO);
  }

  void clear() {
    messages.clear();
  }

  void checkMessages(List<Expected> expectedMessages) {
    int index = 0;
    Iterable<CollectedMessage> messages = filterMessagesByKinds([
      Diagnostic.ERROR,
      Diagnostic.WARNING,
      Diagnostic.HINT,
      Diagnostic.INFO
    ]);
    for (CollectedMessage message in messages) {
      if (index >= expectedMessages.length) {
        Expect.fail("Unexpected messages:\n "
            "${messages.skip(index).join('\n ')}");
      } else {
        Expected expected = expectedMessages[index];
        Expect.equals(expected.messageKind, message.messageKind,
            "Unexpected message kind in:\n ${messages.join('\n ')}");
        Expect.equals(expected.diagnosticKind, message.kind,
            "Unexpected diagnostic kind in\n ${messages.join('\n ')}");
        index++;
      }
    }
  }
}

class Expected {
  final MessageKind messageKind;
  final Diagnostic diagnosticKind;

  const Expected(this.messageKind, this.diagnosticKind);

  const Expected.error(MessageKind messageKind)
      : this(messageKind, Diagnostic.ERROR);

  const Expected.warning(MessageKind messageKind)
      : this(messageKind, Diagnostic.WARNING);

  const Expected.hint(MessageKind messageKind)
      : this(messageKind, Diagnostic.HINT);

  const Expected.info(MessageKind messageKind)
      : this(messageKind, Diagnostic.INFO);
}

void compareWarningKinds(String text, List expectedWarnings,
    Iterable<CollectedMessage> foundWarnings) {
  compareMessageKinds(text, expectedWarnings, foundWarnings, 'warning');
}

/// [expectedMessages] must be a list of either [MessageKind] or [CheckMessage].
void compareMessageKinds(String text, List expectedMessages,
    Iterable<CollectedMessage> foundMessages, String kind) {
  var fail = (message) => Expect.fail('$text: $message');
  HasNextIterator expectedIterator =
      new HasNextIterator(expectedMessages.iterator);
  HasNextIterator<CollectedMessage> foundIterator =
      new HasNextIterator(foundMessages.iterator);
  while (expectedIterator.hasNext && foundIterator.hasNext) {
    var expected = expectedIterator.next();
    var found = foundIterator.next();
    if (expected is MessageKind) {
      Expect.equals(expected, found.message.kind);
    } else if (expected is CheckMessage) {
      String error = expected(found.message);
      Expect.isNull(error, error);
    } else {
      Expect.fail("Unexpected $kind value: $expected.");
    }
  }
  if (expectedIterator.hasNext) {
    do {
      var expected = expectedIterator.next();
      if (expected is CheckMessage) expected = expected(null);
      print('Expected $kind "${expected}" did not occur');
    } while (expectedIterator.hasNext);
    fail('Too few ${kind}s');
  }
  if (foundIterator.hasNext) {
    do {
      CollectedMessage message = foundIterator.next();
      print('Additional $kind "${message}: ${message.message}"');
    } while (foundIterator.hasNext);
    fail('Too many ${kind}s');
  }
}

/// A function the checks [message]. If the check fails or if [message] is
/// `null`, an error string is returned. Otherwise `null` is returned.
typedef String CheckMessage(Message message);

CheckMessage checkMessage(MessageKind kind, Map arguments) {
  return (Message message) {
    if (message == null) return '$kind';
    if (message.kind != kind) return 'Expected message $kind, found $message.';
    for (var key in arguments.keys) {
      if (!message.arguments.containsKey(key)) {
        return 'Expected argument $key not found in $message.kind.';
      }
      String expectedValue = '${arguments[key]}';
      String foundValue = '${message.arguments[key]}';
      if (expectedValue != foundValue) {
        return 'Expected argument $key with value $expectedValue, '
            'found $foundValue.';
      }
    }
    return null;
  };
}
