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

import 'dart:convert';

import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_cli/src/ansi.dart';
import 'package:analyzer_cli/src/options.dart';
import 'package:path/path.dart' as path;

final Map<String, int> _severityCompare = {
  'error': 5,
  'warning': 4,
  'info': 3,
  'lint': 2,
  'hint': 1,
};

String _pluralize(String word, int count) => count == 1 ? word : '${word}s';

/// Given an absolute path, return a relative path if the file is contained in
/// the current directory; return the original path otherwise.
String _relative(String file) {
  return file.startsWith(path.current) ? path.relative(file) : file;
}

/// Returns the given error's severity.
ErrorSeverity _severityIdentity(AnalysisError error) =>
    error.errorCode.errorSeverity;

/// Returns desired severity for the given [error] (or `null` if it's to be
/// suppressed).
typedef SeverityProcessor = ErrorSeverity? Function(AnalysisError error);

/// Analysis statistics counter.
class AnalysisStats {
  /// The total number of diagnostics sent to [formatErrors].
  int unfilteredCount = 0;

  int errorCount = 0;
  int hintCount = 0;
  int lintCount = 0;
  int warnCount = 0;

  AnalysisStats();

  /// The total number of diagnostics reported to the user.
  int get filteredCount => errorCount + warnCount + hintCount + lintCount;

  /// Print statistics to [out].
  void print(StringSink out) {
    var hasErrors = errorCount != 0;
    var hasWarns = warnCount != 0;
    var hasHints = hintCount != 0;
    var hasLints = lintCount != 0;
    var hasContent = false;
    if (hasErrors) {
      out.write(errorCount);
      out.write(' ');
      out.write(_pluralize('error', errorCount));
      hasContent = true;
    }
    if (hasWarns) {
      if (hasContent) {
        if (!hasHints && !hasLints) {
          out.write(' and ');
        } else {
          out.write(', ');
        }
      }
      out.write(warnCount);
      out.write(' ');
      out.write(_pluralize('warning', warnCount));
      hasContent = true;
    }
    if (hasLints) {
      if (hasContent) {
        out.write(hasHints ? ', ' : ' and ');
      }
      out.write(lintCount);
      out.write(' ');
      out.write(_pluralize('lint', lintCount));
      hasContent = true;
    }
    if (hasHints) {
      if (hasContent) {
        out.write(' and ');
      }
      out.write(hintCount);
      out.write(' ');
      out.write(_pluralize('hint', hintCount));
      hasContent = true;
    }
    if (hasContent) {
      out.writeln(' found.');
    } else {
      out.writeln('No issues found!');
    }
  }
}

/// An [AnalysisError] with line and column information.
class CLIError implements Comparable<CLIError> {
  final String severity;
  final String sourcePath;
  final int offset;
  final int line;
  final int column;
  final String message;
  final List<ContextMessage> contextMessages;
  final String errorCode;
  final String? correction;
  final String? url;

  CLIError({
    required this.severity,
    required this.sourcePath,
    required this.offset,
    required this.line,
    required this.column,
    required this.message,
    required this.contextMessages,
    required this.errorCode,
    required this.correction,
    required this.url,
  });

  @override
  int get hashCode =>
      severity.hashCode ^ sourcePath.hashCode ^ errorCode.hashCode ^ offset;
  bool get isError => severity == 'error';
  bool get isHint => severity == 'hint';
  bool get isLint => severity == 'lint';

  bool get isWarning => severity == 'warning';

  @override
  bool operator ==(Object other) {
    return other is CLIError &&
        severity == other.severity &&
        sourcePath == other.sourcePath &&
        errorCode == other.errorCode &&
        offset == other.offset;
  }

  @override
  int compareTo(CLIError other) {
    // severity
    var compare =
        _severityCompare[other.severity]! - _severityCompare[severity]!;
    if (compare != 0) return compare;

    // path
    compare = Comparable.compare(
        sourcePath.toLowerCase(), other.sourcePath.toLowerCase());
    if (compare != 0) return compare;

    // offset
    return offset - other.offset;
  }
}

class ContextMessage {
  final String filePath;
  final String message;
  final int line;
  final int column;
  ContextMessage(this.filePath, this.message, this.line, this.column);
}

/// Helper for formatting [AnalysisError]s.
///
/// The two format options are a user consumable format and a machine consumable
/// format.
abstract class ErrorFormatter {
  final StringSink out;
  final CommandLineOptions options;
  final AnalysisStats stats;
  final SeverityProcessor _severityProcessor;

  ErrorFormatter(this.out, this.options, this.stats,
      {SeverityProcessor? severityProcessor})
      : _severityProcessor = severityProcessor ?? _severityIdentity;

  /// Call to write any batched up errors from [formatErrors].
  void flush();

  Future<void> formatError(
      Map<AnalysisError, ErrorsResult> errorToLine, AnalysisError error);

  Future<void> formatErrors(List<ErrorsResult> results) async {
    stats.unfilteredCount += results.length;

    var errors = <AnalysisError>[];
    var errorToLine = <AnalysisError, ErrorsResult>{};
    for (var result in results) {
      for (var error in result.errors) {
        if (_computeSeverity(error) != null) {
          errors.add(error);
          errorToLine[error] = result;
        }
      }
    }

    for (var error in errors) {
      await formatError(errorToLine, error);
    }
  }

  /// Compute the severity for this [error] or `null` if this error should be
  /// filtered.
  ErrorSeverity? _computeSeverity(AnalysisError error) =>
      _severityProcessor(error);
}

class HumanErrorFormatter extends ErrorFormatter {
  late final AnsiLogger ansi = AnsiLogger(options.color);

  // This is a Set in order to de-dup CLI errors.
  final Set<CLIError> batchedErrors = {};

  HumanErrorFormatter(
      StringSink out, CommandLineOptions options, AnalysisStats stats,
      {SeverityProcessor? severityProcessor})
      : super(out, options, stats, severityProcessor: severityProcessor);

  @override
  void flush() {
    // sort
    var sortedErrors = batchedErrors.toList()..sort();

    // print
    for (var error in sortedErrors) {
      if (error.isError) {
        stats.errorCount++;
      } else if (error.isWarning) {
        stats.warnCount++;
      } else if (error.isLint) {
        stats.lintCount++;
      } else if (error.isHint) {
        stats.hintCount++;
      }

      // warning • 'foo' is not a bar. • lib/foo.dart:1:2 • foo_warning
      var issueColor = (error.isError || error.isWarning) ? ansi.red : '';
      out.write('  $issueColor${error.severity}${ansi.none} '
          '${ansi.bullet} ${ansi.bold}${error.message}${ansi.none} ');
      out.write('${ansi.bullet} ${error.sourcePath}');
      out.write(':${error.line}:${error.column} ');
      out.write('${ansi.bullet} ${error.errorCode}');
      out.writeln();

      // If verbose, also print any associated correction and URL.
      if (options.verbose) {
        var padding = ' '.padLeft(error.severity.length + 2);
        for (var message in error.contextMessages) {
          out.write('$padding${message.message} ');
          out.write('at ${message.filePath}');
          out.writeln(':${message.line}:${message.column}');
        }
        if (error.correction != null) {
          out.writeln('$padding${error.correction}');
        }
        if (error.url != null) {
          out.writeln('$padding${error.url}');
        }
      }
    }

    // clear out batched errors
    batchedErrors.clear();
  }

  @override
  Future<void> formatError(
      Map<AnalysisError, ErrorsResult> errorToLine, AnalysisError error) async {
    var source = error.source;
    var result = errorToLine[error]!;
    var location = result.lineInfo.getLocation(error.offset);

    var severity = _severityProcessor(error)!;

    // Get display name; translate INFOs into LINTS and HINTS.
    var errorType = severity.displayName;
    if (severity == ErrorSeverity.INFO) {
      if (error.errorCode.type == ErrorType.HINT ||
          error.errorCode.type == ErrorType.LINT) {
        errorType = error.errorCode.type.displayName;
      }
    }

    // warning • 'foo' is not a bar. • lib/foo.dart:1:2 • foo_warning
    String sourcePath;
    if (source.uri.isScheme('dart')) {
      sourcePath = source.uri.toString();
    } else if (source.uri.isScheme('package')) {
      sourcePath = _relative(source.fullName);
      if (sourcePath == source.fullName) {
        // If we weren't able to shorten the path name, use the package: version.
        sourcePath = source.uri.toString();
      }
    } else {
      sourcePath = _relative(source.fullName);
    }
    var contextMessages = <ContextMessage>[];
    for (var message in error.contextMessages) {
      // TODO(scheglov) We should add `LineInfo` to `DiagnosticMessage`.
      var session = result.session.analysisContext;
      if (session is DriverBasedAnalysisContext) {
        var fileResult = await session.driver.getFile(message.filePath);
        if (fileResult is FileResult) {
          var lineInfo = fileResult.lineInfo;
          var location = lineInfo.getLocation(message.offset);
          contextMessages.add(ContextMessage(
              message.filePath,
              message.messageText(includeUrl: true),
              location.lineNumber,
              location.columnNumber));
        }
      }
    }

    batchedErrors.add(CLIError(
      severity: errorType,
      sourcePath: sourcePath,
      offset: error.offset,
      line: location.lineNumber,
      column: location.columnNumber,
      message: error.message,
      contextMessages: contextMessages,
      errorCode: error.errorCode.name.toLowerCase(),
      correction: error.correction,
      url: error.errorCode.url,
    ));
  }
}

class JsonErrorFormatter extends ErrorFormatter {
  JsonErrorFormatter(
      StringSink out, CommandLineOptions options, AnalysisStats stats,
      {SeverityProcessor? severityProcessor})
      : super(out, options, stats, severityProcessor: severityProcessor);

  @override
  void flush() {}

  @override
  Future<void> formatError(
      Map<AnalysisError, ErrorsResult> errorToLine, AnalysisError error) async {
    throw UnsupportedError('Cannot format a single error');
  }

  @override
  Future<void> formatErrors(List<ErrorsResult> results) async {
    Map<String, dynamic> range(
            Map<String, dynamic> start, Map<String, dynamic> end) =>
        {
          'start': start,
          'end': end,
        };

    Map<String, dynamic> position(int offset, int line, int column) => {
          'offset': offset,
          'line': line,
          'column': column,
        };

    Map<String, dynamic> location(
        String filePath, int offset, int length, LineInfo lineInfo) {
      var startLocation = lineInfo.getLocation(offset);
      var startLine = startLocation.lineNumber;
      var startColumn = startLocation.columnNumber;
      var endLocation = lineInfo.getLocation(offset + length);
      var endLine = endLocation.lineNumber;
      var endColumn = endLocation.columnNumber;
      return {
        'file': filePath,
        'range': range(position(offset, startLine, startColumn),
            position(offset + length, endLine, endColumn)),
      };
    }

    var diagnostics = <Map<String, dynamic>>[];
    for (var result in results) {
      var errors = result.errors;
      var lineInfo = result.lineInfo;
      for (var error in errors) {
        var contextMessages = <Map<String, dynamic>>[];
        for (var contextMessage in error.contextMessages) {
          contextMessages.add({
            'location': location(contextMessage.filePath, contextMessage.offset,
                contextMessage.length, lineInfo),
            'message': contextMessage.messageText(includeUrl: true),
          });
        }
        var errorCode = error.errorCode;
        var problemMessage = error.problemMessage;
        var url = error.errorCode.url;
        diagnostics.add({
          'code': errorCode.name.toLowerCase(),
          'severity': errorCode.errorSeverity.name,
          'type': errorCode.type.name,
          'location': location(problemMessage.filePath, problemMessage.offset,
              problemMessage.length, lineInfo),
          'problemMessage': problemMessage.messageText(includeUrl: true),
          if (error.correction != null) 'correctionMessage': error.correction,
          if (contextMessages.isNotEmpty) 'contextMessages': contextMessages,
          if (url != null) 'documentation': url,
        });
      }
    }
    out.writeln(json.encode({
      'version': 1,
      'diagnostics': diagnostics,
    }));
  }
}

class MachineErrorFormatter extends ErrorFormatter {
  static final int _pipeCodeUnit = '|'.codeUnitAt(0);
  static final int _slashCodeUnit = '\\'.codeUnitAt(0);
  static final int _newline = '\n'.codeUnitAt(0);
  static final int _return = '\r'.codeUnitAt(0);
  final Set<AnalysisError> _seenErrors = <AnalysisError>{};

  MachineErrorFormatter(
      StringSink out, CommandLineOptions options, AnalysisStats stats,
      {SeverityProcessor? severityProcessor})
      : super(out, options, stats, severityProcessor: severityProcessor);

  @override
  void flush() {}

  @override
  Future<void> formatError(
      Map<AnalysisError, ErrorsResult> errorToLine, AnalysisError error) async {
    // Ensure we don't over-report (#36062).
    if (!_seenErrors.add(error)) {
      return;
    }
    var source = error.source;
    var location = errorToLine[error]!.lineInfo.getLocation(error.offset);
    var length = error.length;

    var severity = _severityProcessor(error);

    if (severity == ErrorSeverity.ERROR) {
      stats.errorCount++;
    } else if (severity == ErrorSeverity.WARNING) {
      stats.warnCount++;
    } else if (error.errorCode.type == ErrorType.HINT) {
      stats.hintCount++;
    } else if (error.errorCode.type == ErrorType.LINT) {
      stats.lintCount++;
    }

    out.write(severity);
    out.write('|');
    out.write(error.errorCode.type);
    out.write('|');
    out.write(error.errorCode.name);
    out.write('|');
    out.write(_escapeForMachineMode(source.fullName));
    out.write('|');
    out.write(location.lineNumber);
    out.write('|');
    out.write(location.columnNumber);
    out.write('|');
    out.write(length);
    out.write('|');
    out.write(_escapeForMachineMode(error.message));
    out.writeln();
  }

  static String _escapeForMachineMode(String input) {
    var result = StringBuffer();
    for (var c in input.codeUnits) {
      if (c == _newline) {
        result.write(r'\n');
      } else if (c == _return) {
        result.write(r'\r');
      } else {
        if (c == _slashCodeUnit || c == _pipeCodeUnit) {
          result.write('\\');
        }
        result.writeCharCode(c);
      }
    }
    return result.toString();
  }
}
