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

import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer_cli/src/driver.dart';
import 'package:analyzer_cli/src/error_formatter.dart';
import 'package:analyzer_cli/src/error_severity.dart';
import 'package:path/path.dart' as path;

int get currentTimeMillis => DateTime.now().millisecondsSinceEpoch;

/// Analyzes single library [File].
class AnalyzerImpl {
  final int startTime;

  final AnalysisOptions analysisOptions;
  final AnalysisDriver analysisDriver;

  /// Accumulated analysis statistics.
  final AnalysisStats stats;

  /// The library file to analyze.
  final FileState libraryFile;

  /// All files references by the analyzed library.
  final Set<String> files = <String>{};

  /// All [ErrorsResult]s in the analyzed library.
  final List<ErrorsResult> errorsResults = [];

  /// If the file specified on the command line is part of a package, the name
  /// of that package. Otherwise `null`. This allows us to analyze the file
  /// specified on the command line as though it is reached via a "package:"
  /// URI, but avoid suppressing its output in the event that the user has not
  /// specified the "--package-warnings" option.
  String? _selfPackageName;

  final Set<String> gotErrorsFor;

  new(
    this.analysisOptions,
    this.analysisDriver,
    this.libraryFile,
    this.stats,
    this.startTime,
    this.gotErrorsFor,
  );

  void addCompilationUnitSource(
    LibraryFragment unit,
    Set<LibraryFragment> units,
  ) {
    if (!units.add(unit)) {
      return;
    }
    files.add(unit.source.fullName);
  }

  void addLibrarySources(
    LibraryElement library,
    Set<LibraryElement> libraries,
    Set<LibraryFragment> units,
  ) {
    if (!libraries.add(library)) {
      return;
    }
    // Maybe skip library.
    if (!_isAnalyzedLibrary(library)) {
      return;
    }
    // Add compilation units.
    for (final fragment in library.fragments) {
      addCompilationUnitSource(fragment, units);
      // Add imported libraries.
      var importedLibraries = fragment.libraryImports;
      for (var child in importedLibraries) {
        var importedLibrary = child.importedLibrary;
        if (importedLibrary != null) {
          addLibrarySources(importedLibrary, libraries, units);
        }
      }
      // Add exported libraries.
      var exportedLibraries = fragment.libraryExports;
      for (var child in exportedLibraries) {
        var exportedLibrary = child.exportedLibrary;
        if (exportedLibrary != null) {
          addLibrarySources(exportedLibrary, libraries, units);
        }
      }
    }
  }

  /// Treats the [libraryFile] as the top level library and analyzes it using
  /// the analysis engine.
  ///
  /// If [printMode] is `0`, then no diagnostic or performance information is
  /// printed. If [printMode] is `1`, then diagnostics will be printed. If
  /// [printMode] is `2`, then performance information will be printed, and it
  /// will be marked as being for a cold VM.
  Future<DiagnosticSeverity> analyze(
    ErrorFormatter formatter, {
    int printMode = 1,
  }) async {
    setupForAnalysis();
    return await _analyze(printMode, formatter);
  }

  /// Returns the maximal [DiagnosticSeverity] of the recorded diagnostics.
  DiagnosticSeverity computeMaxSeverity() {
    var status = DiagnosticSeverity.NONE;
    for (var result in errorsResults) {
      for (var diagnostic in result.diagnostics) {
        if (_defaultSeverityProcessor(diagnostic) == null) {
          continue;
        }
        status = status.max(computeSeverity(diagnostic, analysisOptions)!);
      }
    }
    return status;
  }

  /// Fills [errorsResults] using [files].
  Future<void> prepareErrors() async {
    for (var path in files) {
      if (gotErrorsFor.add(path)) {
        var errorsResult = await analysisDriver.getErrors(path);
        if (errorsResult is ErrorsResult) {
          errorsResults.add(errorsResult);
        }
      }
    }
  }

  /// Fills [files].
  void prepareSources(LibraryElement library) {
    var units = <LibraryFragment>{};
    var libraries = <LibraryElement>{};
    addLibrarySources(library, libraries, units);
  }

  /// Setup local fields such as the analysis context for analysis.
  void setupForAnalysis() {
    files.clear();
    errorsResults.clear();
    var libraryUri = libraryFile.uri;
    if (libraryUri.isScheme('package') && libraryUri.pathSegments.isNotEmpty) {
      _selfPackageName = libraryUri.pathSegments[0];
    }
  }

  Future<DiagnosticSeverity> _analyze(
    int printMode,
    ErrorFormatter formatter,
  ) async {
    // Don't try to analyze parts.
    if (libraryFile.kind is! LibraryFileKind) {
      var libraryPath = libraryFile.path;
      stderr.writeln('Only libraries can be analyzed.');
      stderr.writeln('$libraryPath is a part and cannot be analyzed.');
      return DiagnosticSeverity.ERROR;
    }

    var libraryElement = await _resolveLibrary();
    prepareSources(libraryElement);
    await prepareErrors();

    // Print errors and performance numbers.
    if (printMode == 1) {
      await formatter.formatErrors(errorsResults);
    } else if (printMode == 2) {
      _printColdPerf();
    }

    // Compute and return max severity.
    return computeMaxSeverity();
  }

  DiagnosticSeverity? _defaultSeverityProcessor(Diagnostic diagnostic) =>
      determineProcessedSeverity(diagnostic, analysisOptions);

  /// Returns true if we want to report diagnostics for this library.
  bool _isAnalyzedLibrary(LibraryElement library) {
    var source = library.firstFragment.source;
    if (source.uri.isScheme('dart')) {
      return false;
    } else if (source.uri.isScheme('package')) {
      if (_isPathInPubCache(source.fullName)) {
        return false;
      }
      return _isAnalyzedPackage(source.uri);
    } else {
      return true;
    }
  }

  /// Determine whether the given URI refers to a package being analyzed.
  bool _isAnalyzedPackage(Uri uri) {
    if (!uri.isScheme('package') || uri.pathSegments.isEmpty) {
      return false;
    }
    var packageName = uri.pathSegments.first;
    if (packageName == _selfPackageName) {
      return true;
    } else {
      return false;
    }
  }

  // TODO(devoncarew): This is never called.
  void _printColdPerf() {
    // Print cold VM performance numbers.
    var totalTime = currentTimeMillis - startTime;
    outSink.writeln('total-cold:$totalTime');
  }

  Future<LibraryElement> _resolveLibrary() async {
    var libraryPath = libraryFile.path;
    analysisDriver.priorityFiles = [libraryPath];
    var elementResult =
        await analysisDriver.getUnitElement(libraryPath) as UnitElementResult;
    return elementResult.fragment.element;
  }

  /// Return `true` if the given [pathName] is in the Pub cache.
  static bool _isPathInPubCache(String pathName) {
    var parts = path.split(pathName);
    if (parts.contains('.pub-cache')) {
      return true;
    }
    for (var i = 0; i < parts.length - 2; i++) {
      if (parts[i] == 'Pub' && parts[i + 1] == 'Cache') {
        return true;
      }
    }
    return false;
  }
}
