// 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.

library dart2js.test.diagnostic_helper;

import 'dart:collection';

import 'package:compiler/compiler_new.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;

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

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

  void call(Uri uri, int begin, int end, String message, Diagnostic kind) {
    throw '';
    report(null, uri, begin, end, message, kind);
  }

  @override
  void report(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]);
  }

  /// `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;
  };
}
