// Copyright 2014 The Flutter Authors. 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:async';

import 'package:args/args.dart';
import 'package:meta/meta.dart';
import 'package:process/process.dart';

import '../artifacts.dart';
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/logger.dart';
import '../base/platform.dart';
import '../base/terminal.dart';
import '../dart/analysis.dart';
import 'analyze_base.dart';

class AnalyzeOnce extends AnalyzeBase {
  AnalyzeOnce(
    ArgResults argResults,
    List<String> repoRoots,
    List<Directory> repoPackages, {
    @required FileSystem fileSystem,
    @required Logger logger,
    @required Platform platform,
    @required ProcessManager processManager,
    @required Terminal terminal,
    @required Artifacts artifacts,
    this.workingDirectory,
  }) : super(
        argResults,
        repoRoots: repoRoots,
        repoPackages: repoPackages,
        fileSystem: fileSystem,
        logger: logger,
        platform: platform,
        processManager: processManager,
        terminal: terminal,
        artifacts: artifacts,
      );

  /// The working directory for testing analysis using dartanalyzer.
  final Directory workingDirectory;

  @override
  Future<void> analyze() async {
    final String currentDirectory =
        (workingDirectory ?? fileSystem.currentDirectory).path;

    // find directories from argResults.rest
    final Set<String> directories = Set<String>.of(argResults.rest
        .map<String>((String path) => fileSystem.path.canonicalize(path)));
    if (directories.isNotEmpty) {
      for (final String directory in directories) {
        final FileSystemEntityType type = fileSystem.typeSync(directory);

        if (type == FileSystemEntityType.notFound) {
          throwToolExit("'$directory' does not exist");
        } else if (type != FileSystemEntityType.directory) {
          throwToolExit("'$directory' is not a directory");
        }
      }
    }

    if (isFlutterRepo) {
      // check for conflicting dependencies
      final PackageDependencyTracker dependencies = PackageDependencyTracker();
      dependencies.checkForConflictingDependencies(repoPackages, dependencies);
      directories.addAll(repoRoots);
      if (argResults.wasParsed('current-package') && (argResults['current-package'] as bool)) {
        directories.add(currentDirectory);
      }
    } else {
      if (argResults['current-package'] as bool) {
        directories.add(currentDirectory);
      }
    }

    if (directories.isEmpty) {
      throwToolExit('Nothing to analyze.', exitCode: 0);
    }

    final Completer<void> analysisCompleter = Completer<void>();
    final List<AnalysisError> errors = <AnalysisError>[];

    final AnalysisServer server = AnalysisServer(
      sdkPath,
      directories.toList(),
      fileSystem: fileSystem,
      platform: platform,
      logger: logger,
      processManager: processManager,
      terminal: terminal,
    );

    Stopwatch timer;
    Status progress;
    try {
      StreamSubscription<bool> subscription;

      void handleAnalysisStatus(bool isAnalyzing) {
        if (!isAnalyzing) {
          analysisCompleter.complete();
          subscription?.cancel();
          subscription = null;
        }
      }

      subscription = server.onAnalyzing.listen((bool isAnalyzing) => handleAnalysisStatus(isAnalyzing));

      void handleAnalysisErrors(FileAnalysisErrors fileErrors) {
        fileErrors.errors.removeWhere((AnalysisError error) => error.type == 'TODO');

        errors.addAll(fileErrors.errors);
      }

      server.onErrors.listen(handleAnalysisErrors);

      await server.start();
      // Completing the future in the callback can't fail.
      unawaited(server.onExit.then<void>((int exitCode) {
        if (!analysisCompleter.isCompleted) {
          analysisCompleter.completeError('analysis server exited: $exitCode');
        }
      }));

      // collect results
      timer = Stopwatch()..start();
      final String message = directories.length > 1
          ? '${directories.length} ${directories.length == 1 ? 'directory' : 'directories'}'
          : fileSystem.path.basename(directories.first);
      progress = argResults['preamble'] as bool
          ? logger.startProgress(
            'Analyzing $message...',
          )
          : null;

      await analysisCompleter.future;
    } finally {
      await server.dispose();
      progress?.cancel();
      timer?.stop();
    }

    final int undocumentedMembers = AnalyzeBase.countMissingDartDocs(errors);
    if (!isDartDocs) {
      errors.removeWhere((AnalysisError error) => error.code == 'public_member_api_docs');
    }

    // emit benchmarks
    if (isBenchmarking) {
      writeBenchmark(timer, errors.length, undocumentedMembers);
    }

    // --write
    dumpErrors(errors.map<String>((AnalysisError error) => error.toLegacyString()));

    // report errors
    if (errors.isNotEmpty && (argResults['preamble'] as bool)) {
      logger.printStatus('');
    }
    errors.sort();
    for (final AnalysisError error in errors) {
      logger.printStatus(error.toString(), hangingIndent: 7);
    }

    final int errorCount = errors.length;
    final String seconds = (timer.elapsedMilliseconds / 1000.0).toStringAsFixed(1);
    final String dartDocMessage = AnalyzeBase.generateDartDocMessage(undocumentedMembers);
    final String errorsMessage = AnalyzeBase.generateErrorsMessage(
      issueCount: errorCount,
      seconds: seconds,
      undocumentedMembers: undocumentedMembers,
      dartDocMessage: dartDocMessage,
    );

    if (errorCount > 0) {
      logger.printStatus('');
      throwToolExit(errorsMessage, exitCode: _isFatal(errors) ? 1 : 0);
    }

    if (argResults['congratulate'] as bool) {
      logger.printStatus(errorsMessage);
    }

    if (server.didServerErrorOccur) {
      throwToolExit('Server error(s) occurred. (ran in ${seconds}s)');
    }
  }

  bool _isFatal(List<AnalysisError> errors) {
    for (final AnalysisError error in errors) {
      final AnalysisSeverity severityLevel = error.writtenError.severityLevel;
      if (severityLevel == AnalysisSeverity.error) {
        return true;
      }
      if (severityLevel == AnalysisSeverity.warning &&
        (argResults['fatal-warnings'] as bool || argResults['fatal-infos'] as bool)) {
        return true;
      }
      if (severityLevel == AnalysisSeverity.info && argResults['fatal-infos'] as bool) {
        return true;
      }
    }
    return false;
  }
}
