// 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:platform/platform.dart';
import 'package:process/process.dart';

import '../base/common.dart';
import '../base/file_system.dart';
import '../base/logger.dart';
import '../base/terminal.dart';
import '../base/utils.dart';
import '../cache.dart';
import '../dart/analysis.dart';
import '../dart/sdk.dart' as sdk;
import 'analyze.dart';
import 'analyze_base.dart';

/// An aspect of the [AnalyzeCommand] to perform once time analysis.
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 AnsiTerminal terminal,
    this.workingDirectory,
  }) : super(
        argResults,
        repoRoots: repoRoots,
        repoPackages: repoPackages,
        fileSystem: fileSystem,
        logger: logger,
        platform: platform,
        processManager: processManager,
        terminal: terminal,
      );

  /// 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>.from(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 (argResults['flutter-repo'] as bool) {
      // 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);
    }

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

    final String sdkPath = argResults['dart-sdk'] as String ?? sdk.dartSdkPath;

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

    StreamSubscription<bool> subscription;
    subscription = server.onAnalyzing.listen((bool isAnalyzing) {
      if (!isAnalyzing) {
        analysisCompleter.complete();
        subscription?.cancel();
        subscription = null;
      }
    });
    server.onErrors.listen((FileAnalysisErrors fileErrors) {
      // Record the issues found (but filter out to do comments).
      errors.addAll(fileErrors.errors.where((AnalysisError error) => error.type != 'TODO'));
    });

    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');
      }
    }));

    Cache.releaseLockEarly();

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

    await analysisCompleter.future;
    progress?.cancel();
    timer.stop();

    // count missing dartdocs
    final int undocumentedMembers = errors.where((AnalysisError error) {
      return error.code == 'public_member_api_docs';
    }).length;
    if (!(argResults['dartdocs'] as bool)) {
      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 String seconds = (timer.elapsedMilliseconds / 1000.0).toStringAsFixed(1);

    String dartdocMessage;
    if (undocumentedMembers == 1) {
      dartdocMessage = 'one public member lacks documentation';
    } else {
      dartdocMessage = '$undocumentedMembers public members lack documentation';
    }

    // We consider any level of error to be an error exit (we don't report different levels).
    if (errors.isNotEmpty) {
      final int errorCount = errors.length;
      logger.printStatus('');
      if (undocumentedMembers > 0) {
        throwToolExit('$errorCount ${pluralize('issue', errorCount)} found. (ran in ${seconds}s; $dartdocMessage)');
      } else {
        throwToolExit('$errorCount ${pluralize('issue', errorCount)} found. (ran in ${seconds}s)');
      }
    }

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

    if (argResults['congratulate'] as bool) {
      if (undocumentedMembers > 0) {
        logger.printStatus('No issues found! (ran in ${seconds}s; $dartdocMessage)');
      } else {
        logger.printStatus('No issues found! (ran in ${seconds}s)');
      }
    }
  }
}
