// 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 'package:yaml/yaml.dart' as yaml;

import '../base/common.dart';
import '../base/file_system.dart';
import '../base/logger.dart';
import '../base/platform.dart';
import '../base/terminal.dart';
import '../base/utils.dart';
import '../cache.dart';
import '../globals.dart' as globals;

/// Common behavior for `flutter analyze` and `flutter analyze --watch`
abstract class AnalyzeBase {
  AnalyzeBase(this.argResults, {
    @required this.repoRoots,
    @required this.repoPackages,
    @required this.fileSystem,
    @required this.logger,
    @required this.platform,
    @required this.processManager,
    @required this.terminal,
    @required this.experiments,
  });

  /// The parsed argument results for execution.
  final ArgResults argResults;
  @protected
  final List<String> repoRoots;
  @protected
  final List<Directory> repoPackages;
  @protected
  final FileSystem fileSystem;
  @protected
  final Logger logger;
  @protected
  final ProcessManager processManager;
  @protected
  final Platform platform;
  @protected
  final AnsiTerminal terminal;
  @protected
  final List<String> experiments;

  /// Called by [AnalyzeCommand] to start the analysis process.
  Future<void> analyze();

  void dumpErrors(Iterable<String> errors) {
    if (argResults['write'] != null) {
      try {
        final RandomAccessFile resultsFile = fileSystem.file(argResults['write']).openSync(mode: FileMode.write);
        try {
          resultsFile.lockSync();
          resultsFile.writeStringSync(errors.join('\n'));
        } finally {
          resultsFile.close();
        }
      } on Exception catch (e) {
        logger.printError('Failed to save output to "${argResults['write']}": $e');
      }
    }
  }

  void writeBenchmark(Stopwatch stopwatch, int errorCount, int membersMissingDocumentation) {
    const String benchmarkOut = 'analysis_benchmark.json';
    final Map<String, dynamic> data = <String, dynamic>{
      'time': stopwatch.elapsedMilliseconds / 1000.0,
      'issues': errorCount,
      'missingDartDocs': membersMissingDocumentation,
    };
    fileSystem.file(benchmarkOut).writeAsStringSync(toPrettyJson(data));
    logger.printStatus('Analysis benchmark written to $benchmarkOut ($data).');
  }

  bool get isBenchmarking => argResults['benchmark'] as bool;
}

class PackageDependency {
  // This is a map from dependency targets (lib directories) to a list
  // of places that ask for that target (.packages or pubspec.yaml files)
  Map<String, List<String>> values = <String, List<String>>{};
  String canonicalSource;
  void addCanonicalCase(String packagePath, String pubSpecYamlPath) {
    assert(canonicalSource == null);
    add(packagePath, pubSpecYamlPath);
    canonicalSource = pubSpecYamlPath;
  }
  void add(String packagePath, String sourcePath) {
    values.putIfAbsent(packagePath, () => <String>[]).add(sourcePath);
  }
  bool get hasConflict => values.length > 1;
  bool get hasConflictAffectingFlutterRepo {
    assert(globals.fs.path.isAbsolute(Cache.flutterRoot));
    for (final List<String> targetSources in values.values) {
      for (final String source in targetSources) {
        assert(globals.fs.path.isAbsolute(source));
        if (globals.fs.path.isWithin(Cache.flutterRoot, source)) {
          return true;
        }
      }
    }
    return false;
  }
  void describeConflict(StringBuffer result) {
    assert(hasConflict);
    final List<String> targets = values.keys.toList();
    targets.sort((String a, String b) => values[b].length.compareTo(values[a].length));
    for (final String target in targets) {
      final int count = values[target].length;
      result.writeln('  $count ${count == 1 ? 'source wants' : 'sources want'} "$target":');
      bool canonical = false;
      for (final String source in values[target]) {
        result.writeln('    $source');
        if (source == canonicalSource) {
          canonical = true;
        }
      }
      if (canonical) {
        result.writeln('    (This is the actual package definition, so it is considered the canonical "right answer".)');
      }
    }
  }
  String get target => values.keys.single;
}

class PackageDependencyTracker {
  /// Packages whose source is defined in the vended SDK.
  static const List<String> _vendedSdkPackages = <String>['analyzer', 'front_end', 'kernel'];

  // This is a map from package names to objects that track the paths
  // involved (sources and targets).
  Map<String, PackageDependency> packages = <String, PackageDependency>{};

  PackageDependency getPackageDependency(String packageName) {
    return packages.putIfAbsent(packageName, () => PackageDependency());
  }

  /// Read the .packages file in [directory] and add referenced packages to [dependencies].
  void addDependenciesFromPackagesFileIn(Directory directory) {
    final String dotPackagesPath = globals.fs.path.join(directory.path, '.packages');
    final File dotPackages = globals.fs.file(dotPackagesPath);
    if (dotPackages.existsSync()) {
      // this directory has opinions about what we should be using
      final Iterable<String> lines = dotPackages
        .readAsStringSync()
        .split('\n')
        .where((String line) => !line.startsWith(RegExp(r'^ *#')));
      for (final String line in lines) {
        final int colon = line.indexOf(':');
        if (colon > 0) {
          final String packageName = line.substring(0, colon);
          final String packagePath = globals.fs.path.fromUri(line.substring(colon+1));
          // Ensure that we only add `analyzer` and dependent packages defined in the vended SDK (and referred to with a local
          // globals.fs.path. directive). Analyzer package versions reached via transitive dependencies (e.g., via `test`) are ignored
          // since they would produce spurious conflicts.
          if (!_vendedSdkPackages.contains(packageName) || packagePath.startsWith('..')) {
            add(packageName, globals.fs.path.normalize(globals.fs.path.absolute(directory.path, packagePath)), dotPackagesPath);
          }
        }
      }
    }
  }

  void addCanonicalCase(String packageName, String packagePath, String pubSpecYamlPath) {
    getPackageDependency(packageName).addCanonicalCase(packagePath, pubSpecYamlPath);
  }

  void add(String packageName, String packagePath, String dotPackagesPath) {
    getPackageDependency(packageName).add(packagePath, dotPackagesPath);
  }

  void checkForConflictingDependencies(Iterable<Directory> pubSpecDirectories, PackageDependencyTracker dependencies) {
    for (final Directory directory in pubSpecDirectories) {
      final String pubSpecYamlPath = globals.fs.path.join(directory.path, 'pubspec.yaml');
      final File pubSpecYamlFile = globals.fs.file(pubSpecYamlPath);
      if (pubSpecYamlFile.existsSync()) {
        // we are analyzing the actual canonical source for this package;
        // make sure we remember that, in case all the packages are actually
        // pointing elsewhere somehow.
        final dynamic pubSpecYaml = yaml.loadYaml(globals.fs.file(pubSpecYamlPath).readAsStringSync());
        if (pubSpecYaml is yaml.YamlMap) {
          final dynamic packageName = pubSpecYaml['name'];
          if (packageName is String) {
            final String packagePath = globals.fs.path.normalize(globals.fs.path.absolute(globals.fs.path.join(directory.path, 'lib')));
            dependencies.addCanonicalCase(packageName, packagePath, pubSpecYamlPath);
          } else {
            throwToolExit('pubspec.yaml is malformed. The name should be a String.');
          }
        } else {
          throwToolExit('pubspec.yaml is malformed.');
        }
      }
      dependencies.addDependenciesFromPackagesFileIn(directory);
    }

    // prepare a union of all the .packages files
    if (dependencies.hasConflicts) {
      final StringBuffer message = StringBuffer();
      message.writeln(dependencies.generateConflictReport());
      message.writeln('Make sure you have run "pub upgrade" in all the directories mentioned above.');
      if (dependencies.hasConflictsAffectingFlutterRepo) {
        message.writeln(
          'For packages in the flutter repository, try using "flutter update-packages" to do all of them at once.\n'
          'If you need to actually upgrade them, consider "flutter update-packages --force-upgrade". '
          '(This will update your pubspec.yaml files as well, so you may wish to do this on a separate branch.)'
        );
      }
      message.write(
        'If this does not help, to track down the conflict you can use '
        '"pub deps --style=list" and "pub upgrade --verbosity=solver" in the affected directories.'
      );
      throwToolExit(message.toString());
    }
  }

  bool get hasConflicts {
    return packages.values.any((PackageDependency dependency) => dependency.hasConflict);
  }

  bool get hasConflictsAffectingFlutterRepo {
    return packages.values.any((PackageDependency dependency) => dependency.hasConflictAffectingFlutterRepo);
  }

  String generateConflictReport() {
    assert(hasConflicts);
    final StringBuffer result = StringBuffer();
    for (final String package in packages.keys.where((String package) => packages[package].hasConflict)) {
      result.writeln('Package "$package" has conflicts:');
      packages[package].describeConflict(result);
    }
    return result.toString();
  }

  Map<String, String> asPackageMap() {
    final Map<String, String> result = <String, String>{};
    for (final String package in packages.keys) {
      result[package] = packages[package].target;
    }
    return result;
  }
}
