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

library _fe_analyzer_shared.messages.codes;

import 'dart:convert' show JsonEncoder, json;

import 'diagnostic_message.dart' show DiagnosticMessage;

import '../scanner/token.dart' show Token;

import 'severity.dart' show Severity;

import '../util/relativize.dart' as util show isWindows, relativizeUri;

part 'codes_generated.dart';

const int noLength = 1;

class Code<T> {
  final String name;

  /// The unique positive integer associated with this code,
  /// or `-1` if none. This index is used when translating
  /// this error to its corresponding Analyzer error.
  final int index;

  final List<String>? analyzerCodes;

  final Severity severity;

  const Code(this.name,
      {this.index: -1, this.analyzerCodes, this.severity: Severity.error});

  String toString() => name;
}

class Message {
  final Code<dynamic> code;

  final String message;

  final String? tip;

  final Map<String, dynamic> arguments;

  const Message(this.code,
      {required this.message, this.tip, this.arguments = const {}});

  LocatedMessage withLocation(Uri uri, int charOffset, int length) {
    return new LocatedMessage(uri, charOffset, length, this);
  }

  LocatedMessage withoutLocation() {
    return new LocatedMessage(null, -1, noLength, this);
  }

  String toString() {
    return "Message[$code, $message, $tip, $arguments]";
  }
}

class MessageCode extends Code<Null> implements Message {
  final String message;

  final String? tip;

  const MessageCode(String name,
      {int index: -1,
      List<String>? analyzerCodes,
      Severity severity: Severity.error,
      required this.message,
      this.tip})
      : super(name,
            index: index, analyzerCodes: analyzerCodes, severity: severity);

  Map<String, dynamic> get arguments => const <String, dynamic>{};

  Code<dynamic> get code => this;

  @override
  LocatedMessage withLocation(Uri uri, int charOffset, int length) {
    return new LocatedMessage(uri, charOffset, length, this);
  }

  LocatedMessage withoutLocation() {
    return new LocatedMessage(null, -1, noLength, this);
  }
}

class Template<T> {
  final String messageTemplate;

  final String? tipTemplate;

  final T withArguments;

  const Template(
      {required this.messageTemplate,
      this.tipTemplate,
      required this.withArguments});
}

class LocatedMessage implements Comparable<LocatedMessage> {
  final Uri? uri;

  final int charOffset;

  final int length;

  final Message messageObject;

  const LocatedMessage(
      this.uri, this.charOffset, this.length, this.messageObject);

  Code<dynamic> get code => messageObject.code;

  String get message => messageObject.message;

  String? get tip => messageObject.tip;

  Map<String, dynamic> get arguments => messageObject.arguments;

  @override
  int compareTo(LocatedMessage other) {
    int result = "${uri}".compareTo("${other.uri}");
    if (result != 0) return result;
    result = charOffset.compareTo(other.charOffset);
    if (result != 0) return result;
    return message.compareTo(message);
  }

  FormattedMessage withFormatting(PlainAndColorizedString formatted, int line,
      int column, Severity severity, List<FormattedMessage>? relatedInformation,
      {List<Uri>? involvedFiles}) {
    return new FormattedMessage(this, formatted.plain, formatted.colorized,
        line, column, severity, relatedInformation,
        involvedFiles: involvedFiles);
  }

  @override
  int get hashCode =>
      13 * uri.hashCode +
      17 * charOffset.hashCode +
      19 * length.hashCode +
      23 * messageObject.hashCode;

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;
    return other is LocatedMessage &&
        uri == other.uri &&
        charOffset == other.charOffset &&
        length == other.length &&
        messageObject == other.messageObject;
  }

  @override
  String toString() =>
      'LocatedMessage(uri=$uri,charOffset=$charOffset,length=$length,'
      'messageObject=$messageObject)';
}

class PlainAndColorizedString {
  final String plain;
  final String colorized;

  @override
  String toString() {
    assert(false, "Called PlainAndColorizedString.toString: $plain");
    return 'PlainAndColorizedString:$plain';
  }

  const PlainAndColorizedString(this.plain, this.colorized);

  const PlainAndColorizedString.plainOnly(this.plain) : this.colorized = plain;
}

class FormattedMessage implements DiagnosticMessage {
  final LocatedMessage locatedMessage;

  final String formattedPlain;

  final String formattedColorized;

  final int line;

  final int column;

  @override
  final Severity severity;

  final List<FormattedMessage>? relatedInformation;

  final List<Uri>? involvedFiles;

  const FormattedMessage(
      this.locatedMessage,
      this.formattedPlain,
      this.formattedColorized,
      this.line,
      this.column,
      this.severity,
      this.relatedInformation,
      {this.involvedFiles});

  Code<dynamic> get code => locatedMessage.code;

  String get codeName => code.name;

  String get message => locatedMessage.message;

  String? get tip => locatedMessage.tip;

  Map<String, dynamic> get arguments => locatedMessage.arguments;

  Uri? get uri => locatedMessage.uri;

  int get charOffset => locatedMessage.charOffset;

  int get length => locatedMessage.length;

  @override
  Iterable<String> get ansiFormatted sync* {
    yield formattedColorized;
    if (relatedInformation != null) {
      for (FormattedMessage m in relatedInformation!) {
        yield m.formattedColorized;
      }
    }
  }

  @override
  Iterable<String> get plainTextFormatted sync* {
    yield formattedPlain;
    if (relatedInformation != null) {
      for (FormattedMessage m in relatedInformation!) {
        yield m.formattedPlain;
      }
    }
  }

  Map<String, Object?> toJson() {
    // This should be kept in sync with package:kernel/problems.md
    return <String, Object?>{
      "ansiFormatted": ansiFormatted.toList(),
      "plainTextFormatted": plainTextFormatted.toList(),
      "severity": severity.index,
      "uri": uri?.toString(),
      "involvedFiles": involvedFiles?.map((u) => u.toString()).toList(),
      "codeName": code.name,
    };
  }

  String toJsonString() {
    JsonEncoder encoder = new JsonEncoder.withIndent("  ");
    return encoder.convert(this);
  }
}

class DiagnosticMessageFromJson implements DiagnosticMessage {
  @override
  final Iterable<String> ansiFormatted;

  @override
  final Iterable<String> plainTextFormatted;

  @override
  final Severity severity;

  final Uri? uri;

  final List<Uri>? involvedFiles;

  final String codeName;

  DiagnosticMessageFromJson(this.ansiFormatted, this.plainTextFormatted,
      this.severity, this.uri, this.involvedFiles, this.codeName);

  factory DiagnosticMessageFromJson.fromJson(String jsonString) {
    Map<String, Object> decoded = json.decode(jsonString);
    List<String> ansiFormatted =
        new List<String>.from(_asListOfString(decoded["ansiFormatted"]));
    List<String> plainTextFormatted =
        _asListOfString(decoded["plainTextFormatted"]);
    Severity severity = Severity.values[decoded["severity"] as int];
    Uri? uri =
        decoded["uri"] == null ? null : Uri.parse(decoded["uri"] as String);
    List<Uri>? involvedFiles = decoded["involvedFiles"] == null
        ? null
        : _asListOfString(decoded["involvedFiles"])
            .map((e) => Uri.parse(e))
            .toList();
    String codeName = decoded["codeName"] as String;

    return new DiagnosticMessageFromJson(ansiFormatted, plainTextFormatted,
        severity, uri, involvedFiles, codeName);
  }

  Map<String, Object?> toJson() {
    // This should be kept in sync with package:kernel/problems.md
    return <String, Object?>{
      "ansiFormatted": ansiFormatted.toList(),
      "plainTextFormatted": plainTextFormatted.toList(),
      "severity": severity.index,
      "uri": uri?.toString(),
      "involvedFiles": involvedFiles?.map((u) => u.toString()).toList(),
      "codeName": codeName,
    };
  }

  String toJsonString() {
    JsonEncoder encoder = new JsonEncoder.withIndent("  ");
    return encoder.convert(this);
  }

  static List<String> _asListOfString(Object? value) {
    return (value as List<dynamic>).cast<String>();
  }
}

String? relativizeUri(Uri? uri) {
  // We have this method here for two reasons:
  //
  // 1. It allows us to implement #uri message argument without using it
  // (otherwise, we might get an `UNUSED_IMPORT` warning).
  //
  // 2. We can change `base` argument here if needed.
  return uri == null ? null : util.relativizeUri(Uri.base, uri, util.isWindows);
}

typedef SummaryTemplate = Message Function(int, int, num, num, num);

String itemizeNames(List<String> names) {
  StringBuffer buffer = new StringBuffer();
  for (int i = 0; i < names.length - 1; i++) {
    buffer.write(" - ");
    buffer.writeln(names[i]);
  }
  buffer.write(" - ");
  buffer.write(names.last);
  return "$buffer";
}

/// Convert the synthetic name of an implicit mixin application class
/// into a name suitable for user-faced strings.
///
/// For example, when compiling "class A extends S with M1, M2", the
/// two synthetic classes will be named "_A&S&M1" and "_A&S&M1&M2".
/// This function will return "S with M1" and "S with M1, M2", respectively.
///
/// This method is copied from package:kernel/ast.dart.
// TODO(johnniwinther): Avoid the need for this method.
String demangleMixinApplicationName(String name) {
  List<String> nameParts = name.split('&');
  if (nameParts.length < 2 || name == "&") return name;
  String demangledName = nameParts[1];
  for (int i = 2; i < nameParts.length; i++) {
    demangledName += (i == 2 ? " with " : ", ") + nameParts[i];
  }
  return demangledName;
}

final RegExp templateKey = new RegExp(r'#(\w+)');

/// Replaces occurrences of '#key' in [template], where 'key' is a key in
/// [arguments], with the corresponding values.
String applyArgumentsToTemplate(
    String template, Map<String, dynamic> arguments) {
  // TODO(johnniwinther): Remove `as dynamic` when unsound null safety is
  // no longer supported.
  if (arguments as dynamic == null || arguments.isEmpty) {
    assert(!template.contains(templateKey),
        'Message requires arguments, but none were provided.');
    return template;
  }
  return template.replaceAllMapped(templateKey, (Match match) {
    String? key = match.group(1);
    Object? value = arguments[key];
    assert(value != null, "No value for '$key' found in $arguments");
    return value.toString();
  });
}
