import 'dart:io';

import 'package:cli_util/cli_logging.dart';
import 'package:collection/collection.dart';
import 'package:path/path.dart' as path;
import 'package:yaml/yaml.dart' as yaml;

const validateDEPS = false;

void main(List<String> arguments) {
  Logger logger = Logger.standard();

  // validate the cwd
  if (!FileSystemEntity.isFileSync('DEPS') ||
      !FileSystemEntity.isDirectorySync('pkg')) {
    logger.stderr('Please run this tool from the root of the Dart repo.');
    exit(1);
  }

  print('To run this script, execute:');
  print('');
  print('  dart tools/package_deps/bin/package_deps.dart');
  print('');
  print('See pkg/README.md for more information.');
  print('');
  print('----');
  print('');

  // locate all pkg/ packages
  final packages = <Package>[];
  for (var entity in Directory('pkg').listSync()) {
    if (entity is Directory) {
      var package = Package(entity.path);
      if (package.hasPubspec) {
        packages.add(package);
      }
    }
  }

  List<String> pkgPackages = packages.map((p) => p.packageName).toList();

  // Manually added directories (outside of pkg/).
  List<String> alsoValidate = [
    'tools/package_deps',
  ];

  for (String p in alsoValidate) {
    packages.add(Package(p));
  }

  packages.sort();

  var validateFailure = false;

  // For each, validate the pubspec contents.
  for (var package in packages) {
    print('validating ${package.dir}'
        '${package.publishable ? ' [publishable]' : ''}');

    if (!package.validate(logger, pkgPackages)) {
      validateFailure = true;
    }

    print('');
  }

  // Read and display info about the sdk DEPS file.
  if (validateDEPS) {
    print('SDK DEPS');
    print('');

    var sdkDeps = SdkDeps(File('DEPS'));
    sdkDeps.parse();

    List<String> deps = [...sdkDeps.pkgs, ...sdkDeps.testedPkgs]..sort();
    for (var pkg in deps) {
      final tested = sdkDeps.testedPkgs.contains(pkg);
      print('package:$pkg${tested ? ' [tested]' : ''}');
    }

    // TODO(devoncarew): Validate that published packages solve against the
    // versions brought in from the DEPS file.

    // TODO(devoncarew): Find unused entries in the DEPS file.

  }

  if (validateFailure) {
    exitCode = 1;
  }
}

class Package implements Comparable<Package> {
  final String dir;
  final _regularDependencies = <String>{};
  final _devDependencies = <String>{};
  final _declaredPubDeps = <PubDep>[];
  final _declaredDevPubDeps = <PubDep>[];
  final _declaredOverridePubDeps = <PubDep>[];

  late final String _packageName;
  late final Set<String> _declaredDependencies;
  late final Set<String> _declaredDevDependencies;
  // ignore: unused_field
  late final Set<String> _declaredOverrideDependencies;
  late final bool _publishToNone;

  Package(this.dir) {
    var pubspec = File(path.join(dir, 'pubspec.yaml'));
    var doc = yaml.loadYamlDocument(pubspec.readAsStringSync());
    dynamic docContents = doc.contents.value;
    _packageName = docContents['name'];
    _publishToNone = docContents['publish_to'] == 'none';

    Set<String> process(String section, List<PubDep> target) {
      if (docContents[section] != null) {
        final value = Set<String>.from(docContents[section].keys);

        var deps = docContents[section];
        for (var package in deps.keys) {
          target.add(PubDep.parse(package, deps[package]));
        }

        return value;
      } else {
        return {};
      }
    }

    _declaredDependencies = process('dependencies', _declaredPubDeps);
    _declaredDevDependencies = process('dev_dependencies', _declaredDevPubDeps);
    _declaredOverrideDependencies =
        process('dependency_overrides', _declaredOverridePubDeps);
  }

  String get dirName => path.basename(dir);
  String get packageName => _packageName;

  List<String> get regularDependencies => _regularDependencies.toList()..sort();

  List<String> get devDependencies => _devDependencies.toList()..sort();

  bool get publishable => !_publishToNone;

  @override
  String toString() => 'Package $dirName';

  bool get hasPubspec =>
      FileSystemEntity.isFileSync(path.join(dir, 'pubspec.yaml'));

  @override
  int compareTo(Package other) => dir.compareTo(other.dir);

  bool validate(Logger logger, List<String> pkgPackages) {
    _parseImports();
    return _validatePubspecDeps(logger, pkgPackages);
  }

  void _parseImports() {
    final files = <File>[];

    _collectDartFiles(Directory(dir), files);

    for (var file in files) {
      //print('  ${file.path}');

      var importedPackages = <String>{};

      for (var import in _collectImports(file)) {
        try {
          var uri = Uri.parse(import);
          if (uri.hasScheme && uri.isScheme('package')) {
            var packageName = path.split(uri.path).first;
            importedPackages.add(packageName);
          }
        } on FormatException {
          // ignore
        }
      }

      var topLevelDir = _topLevelDir(file);

      if ({'bin', 'lib'}.contains(topLevelDir)) {
        _regularDependencies.addAll(importedPackages);
      } else {
        _devDependencies.addAll(importedPackages);
      }
    }
  }

  bool _validatePubspecDeps(Logger logger, List<String> pkgPackages) {
    var fail = false;

    if (dirName != packageName) {
      print('  Package name is different from the directory name.');
      fail = true;
    }

    var deps = regularDependencies;
    deps.remove(packageName);

    var devdeps = devDependencies;
    devdeps.remove(packageName);

    // if (deps.isNotEmpty) {
    //   print('  deps    : ${deps}');
    // }
    // if (devdeps.isNotEmpty) {
    //   print('  dev deps: ${devdeps}');
    // }

    void out(String message) {
      logger.stdout(logger.ansi.emphasized(message));
    }

    var undeclaredRegularUses = Set<String>.from(deps)
      ..removeAll(_declaredDependencies);
    if (undeclaredRegularUses.isNotEmpty) {
      out('  ${_printSet(undeclaredRegularUses)} used in lib/ but not '
          "declared in 'dependencies:'.");
      fail = true;
    }

    var undeclaredDevUses = Set<String>.from(devdeps)
      ..removeAll(_declaredDependencies)
      ..removeAll(_declaredDevDependencies);
    if (undeclaredDevUses.isNotEmpty) {
      out('  ${_printSet(undeclaredDevUses)} used in dev dirs but not '
          "declared in 'dev_dependencies:'.");
      fail = true;
    }

    var extraRegularDeclarations = Set<String>.from(_declaredDependencies)
      ..removeAll(deps);
    if (extraRegularDeclarations.isNotEmpty) {
      out('  ${_printSet(extraRegularDeclarations)} declared in '
          "'dependencies:' but not used in lib/.");
      fail = true;
    }

    var extraDevDeclarations = Set<String>.from(_declaredDevDependencies)
      ..removeAll(devdeps);
    // Remove package:pedantic and package:lints as they are often declared as
    // dev dependencies in order to bring in their analysis_options.yaml files.
    extraDevDeclarations.removeAll(['lints', 'pedantic']);
    if (extraDevDeclarations.isNotEmpty) {
      out('  ${_printSet(extraDevDeclarations)} declared in '
          "'dev_dependencies:' but not used in dev dirs.");
      fail = true;
    }

    // Look for things declared in deps, not used in lib/, but that are used in
    // dev dirs.
    var misplacedDeps =
        extraRegularDeclarations.intersection(Set.from(devdeps));
    if (misplacedDeps.isNotEmpty) {
      out("  ${_printSet(misplacedDeps)} declared in 'dependencies:' but "
          'only used in dev dirs.');
      fail = true;
    }

    // Validate that we don't have relative deps into third_party.
    // TODO(devoncarew): This is currently just enforced for publishable
    // packages.
    if (publishable) {
      for (PubDep dep in [..._declaredPubDeps, ..._declaredDevPubDeps]) {
        if (dep is PathPubDep) {
          var path = dep.path;

          if (path.contains('third_party/pkg_tested/') ||
              path.contains('third_party/pkg/')) {
            out('  Prefer a semver dependency for packages brought in via DEPS:');
            out('    $dep');
            fail = true;
          }
        }
      }
    }

    // Validate that published packages don't use path deps.
    if (publishable) {
      for (PubDep dep in _declaredPubDeps) {
        if (dep is PathPubDep) {
          out('  Published packages should use semver deps:');
          out('    $dep');
          fail = true;
        }
      }
    }

    // Validate that non-published packages use relative a (relative) path dep
    // for pkg/ packages.
    if (!publishable) {
      for (PubDep dep in [..._declaredPubDeps, ..._declaredDevPubDeps]) {
        if (pkgPackages.contains(dep.name) && dep is! PathPubDep) {
          // check to see if there is a dependency_override to a path dependency
          final override = _declaredOverridePubDeps
              .singleWhereOrNull((element) => element.name == dep.name);
          if (override != null && override is PathPubDep) {
            continue;
          }

          out('  Prefer a relative path dep for pkg/ packages:');
          out('    $dep');
          fail = true;
        }
      }
    }

    if (!fail) {
      print('  No issues.');
    }

    return !fail;
  }

  void _collectDartFiles(Directory dir, List<File> files) {
    for (var entity in dir.listSync(followLinks: false)) {
      if (entity is Directory) {
        var name = path.basename(entity.path);

        // Skip 'pkg/analyzer_cli/test/data'.
        // Skip 'pkg/front_end/test/id_testing/data/'.
        // Skip 'pkg/front_end/test/language_versioning/data/'.
        // Skip 'pkg/front_end/outline_extraction_testcases/'.
        if (name == 'data' && path.split(entity.parent.path).contains('test')) {
          continue;
        }

        // Skip 'pkg/analysis_server/test/mock_packages'.
        if (name == 'mock_packages') {
          continue;
        }

        // Skip 'pkg/front_end/testcases'.
        if (name == 'testcases') {
          continue;
        }

        // Skip 'pkg/front_end/outline_extraction_testcases'.
        if (name == 'outline_extraction_testcases') {
          continue;
        }

        if (!name.startsWith('.')) {
          _collectDartFiles(entity, files);
        }
      } else if (entity is File && entity.path.endsWith('.dart')) {
        files.add(entity);
      }
    }
  }

  // look for both kinds of quotes
  static RegExp importRegex1 = RegExp(r"^(import|export)\s+\'(\S+)\'");
  static RegExp importRegex2 = RegExp(r'^(import|export)\s+"(\S+)"');

  List<String> _collectImports(File file) {
    var results = <String>[];

    for (var line in file.readAsLinesSync()) {
      // Check for a few tokens that should stop our parse.
      if (line.startsWith('class ') ||
          line.startsWith('typedef ') ||
          line.startsWith('mixin ') ||
          line.startsWith('enum ') ||
          line.startsWith('extension ') ||
          line.startsWith('void ') ||
          line.startsWith('Future ') ||
          line.startsWith('final ') ||
          line.startsWith('const ')) {
        break;
      }

      var match = importRegex1.firstMatch(line);
      if (match != null) {
        results.add(match.group(2)!);
        continue;
      }

      match = importRegex2.firstMatch(line);
      if (match != null) {
        results.add(match.group(2)!);
        continue;
      }
    }

    return results;
  }

  String _topLevelDir(File file) {
    var relativePath = path.relative(file.path, from: dir);
    return path.split(relativePath).first;
  }
}

String _printSet(Set<String> value) {
  var list = value.toList()..sort();
  list = list.map((item) => 'package:$item').toList();
  if (list.length > 1) {
    return list.sublist(0, list.length - 1).join(', ') + ' and ' + list.last;
  } else {
    return list.join(', ');
  }
}

class SdkDeps {
  final File file;

  List<String> pkgs = [];
  List<String> testedPkgs = [];

  SdkDeps(this.file);

  void parse() {
    // Var("dart_root") + "/third_party/pkg/dart2js_info":
    final pkgRegExp = RegExp(r'"/third_party/pkg/(\S+)"');

    // Var("dart_root") + "/third_party/pkg_tested/dart_style":
    final testedPkgRegExp = RegExp(r'"/third_party/pkg_tested/(\S+)"');

    for (var line in file.readAsLinesSync()) {
      var pkgDep = pkgRegExp.firstMatch(line);
      var testedPkgDep = testedPkgRegExp.firstMatch(line);

      if (pkgDep != null) {
        pkgs.add(pkgDep.group(1)!);
      } else if (testedPkgDep != null) {
        testedPkgs.add(testedPkgDep.group(1)!);
      }
    }

    pkgs.sort();
    testedPkgs.sort();
  }
}

abstract class PubDep {
  final String name;

  PubDep(this.name);

  @override
  String toString() => name;

  static PubDep parse(String name, Object dep) {
    if (dep is String) {
      return SemverPubDep(name, dep);
    } else if (dep is Map) {
      if (dep.containsKey('path')) {
        return PathPubDep(name, dep['path']);
      } else {
        return UnhandledPubDep(name);
      }
    } else {
      return UnhandledPubDep(name);
    }
  }
}

class SemverPubDep extends PubDep {
  final String value;

  SemverPubDep(String name, this.value) : super(name);

  @override
  String toString() => '$name: $value';
}

class PathPubDep extends PubDep {
  final String path;

  PathPubDep(String name, this.path) : super(name);

  @override
  String toString() => '$name: $path';
}

class UnhandledPubDep extends PubDep {
  UnhandledPubDep(String name) : super(name);
}
