// Copyright 2020 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.

import 'dart:io';

import 'package:collection/collection.dart';
import 'package:devtools_tool/utils.dart';
import 'package:path/path.dart' as path;

class DevToolsRepo {
  DevToolsRepo._create(this.repoPath);

  /// The path to the DevTools repository root.
  final String repoPath;

  /// The path to the DevTools 'tool' directory.
  String get toolDirectoryPath => path.join(repoPath, 'tool');

  /// The path to the 'tool/flutter-sdk' directory.
  String get toolFlutterSdkPath =>
      path.join(toolDirectoryPath, sdkDirectoryName);

  /// The name of the Flutter SDK directory.
  String get sdkDirectoryName => 'flutter-sdk';

  /// The path to the DevTools 'devtools_app' directory.
  String get devtoolsAppDirectoryPath =>
      path.join(repoPath, 'packages', 'devtools_app');

  @override
  String toString() => '[DevTools $repoPath]';

  /// This returns the DevToolsRepo instance based on the current working
  /// directory.
  ///
  /// Throws if the current working directory is not contained within a git
  /// checkout of DevTools.
  static DevToolsRepo getInstance() {
    final repoPath = _findRepoRoot(Directory.current);
    if (repoPath == null) {
      throw Exception(
        'dt must be run from inside of the DevTools repository directory',
      );
    }
    return DevToolsRepo._create(repoPath);
  }

  /// Returns the list of Dart or Flutter packages contained within the DevTools
  /// repository.
  ///
  /// A Dart or Flutter package is defined as any directory with a pubspec.yaml
  /// file.
  ///
  /// If a package path contains any part on its path that is in [skip], the
  /// package will not be included in the returned results.
  ///
  /// If [includeSubdirectories] is false, packages that are a subdirectory of
  /// another package will not be included in the returned results.
  List<Package> getPackages({
    List<String> skip = const [],
    bool includeSubdirectories = true,
  }) {
    final result = <Package>[];
    final repoDir = Directory(repoPath);

    for (final entity in repoDir.listSync()) {
      final name = path.basename(entity.path);
      if (entity is Directory && !name.startsWith('.')) {
        _collectPackages(
          entity,
          result,
          skip: skip,
          includeSubdirectories: includeSubdirectories,
        );
      }
    }

    result.sort((a, b) => a.packagePath.compareTo(b.packagePath));

    return result;
  }

  static String? _findRepoRoot(Directory dir) {
    // Look for README.md, packages, tool.
    if (_fileExists(dir, 'README.md') &&
        _dirExists(dir, 'packages') &&
        _dirExists(dir, 'tool')) {
      return dir.path;
    }

    if (dir.path == dir.parent.path) {
      return null;
    } else {
      return _findRepoRoot(dir.parent);
    }
  }

  void _collectPackages(
    Directory dir,
    List<Package> result, {
    bool includeSubdirectories = true,
    List<String> skip = const [],
  }) {
    // Do not collect packages from the Flutter SDK that is stored in the tool/
    // directory.
    if (dir.path.contains(path.join('tool', 'flutter-sdk'))) return;

    if (_fileExists(dir, 'pubspec.yaml')) {
      final isTopLevelPackagesDir = dir.path.endsWith('packages');
      final shouldSkip =
          skip.firstWhereOrNull((skipDir) => dir.path.contains(skipDir)) !=
          null;
      if (isTopLevelPackagesDir || shouldSkip) {
        // Do not include the top level devtools/packages directory in the results
        // even though it has a pubspec.yaml file. Also skip any directories
        // specified by [skip].
        final reason = isTopLevelPackagesDir
            ? 'each DevTools package is analyzed individually'
            : '${skip.toString()} directories are intentionally skipped';
        print('Skipping ${dir.path} in _collectPackages because $reason.');
      } else {
        final ancestor = result.firstWhereOrNull(
          (p) =>
              // Remove the last segment of [dir]'s pathSegments to ensure we
              // are only checking ancestors and not sibling directories with
              // similar names.
              (List.from(dir.uri.pathSegments)..safeRemoveLast())
                  // TODO(kenz): this may cause issues for Windows paths.
                  .join('/')
                  .startsWith(p.packagePath),
        );
        final ancestorDirectoryAdded = ancestor != null;
        if (!includeSubdirectories && ancestorDirectoryAdded) {
          print(
            'Skipping ${dir.path} in _collectPackages because it is a '
            'subdirectory of another package (${ancestor.packagePath}).',
          );
        } else {
          result.add(Package._(this, dir.path));
        }
      }
    }

    for (final entity in dir.listSync(followLinks: false)) {
      final name = path.basename(entity.path);
      if (entity is Directory && !name.startsWith('.') && name != 'build') {
        _collectPackages(
          entity,
          result,
          skip: skip,
          includeSubdirectories: includeSubdirectories,
        );
      }
    }
  }

  /// Reads the file at [uri], which should be a relative path from [repoPath].
  String readFile(Uri uri) {
    return File(path.join(repoPath, uri.path)).readAsStringSync();
  }
}

class FlutterSdk {
  FlutterSdk._(this.sdkPath);

  static FlutterSdk? _current;

  /// The current located Flutter SDK.
  ///
  /// Tries to locate from the running Dart VM. If not found, will print a
  /// warning and use Flutter from PATH.
  static FlutterSdk get current {
    if (_current == null) {
      throw Exception(
        'Cannot use FlutterSdk.current before SDK has been selected.'
        'SDK selection is done by DevToolsCommandRunner.runCommand().',
      );
    }
    return _current!;
  }

  /// Sets the active Flutter SDK to the one that contains the Dart VM being
  /// used to run this script.
  ///
  /// Throws if the current VM is not inside a Flutter SDK.
  static void useFromCurrentVm() {
    _current = findFromCurrentVm();
  }

  /// Sets the active Flutter SDK to the one found in the `PATH` environment
  /// variable (by running which/where).
  ///
  /// Throws if an SDK is not found on PATH.
  static void useFromPathEnvironmentVariable() {
    _current = findFromPathEnvironmentVariable();
  }

  /// Sets the active Flutter SDK to the one at [sdkPath].
  ///
  /// Throws if an SDK is not found at [sdkPath].
  static void useFromPath(String sdkPath) {
    _current = findFromPath(sdkPath);
  }

  /// Finds the Flutter SDK that contains the Dart VM being used to run this
  /// script.
  ///
  /// Throws if the current VM is not inside a Flutter SDK.
  static FlutterSdk findFromCurrentVm() {
    // Look for it relative to the current Dart process.
    final dartVmPath = Platform.resolvedExecutable;
    final pathSegments = path.split(dartVmPath);
    // TODO(dantup): Should we add tool/flutter-sdk to the front here, to
    // ensure we _only_ ever use this one, to avoid potentially updating a
    // different Flutter if the user runs explicitly with another Flutter?
    final expectedSegments = path.posix.split('bin/cache/dart-sdk/bin/dart');

    if (pathSegments.length >= expectedSegments.length) {
      // Remove the trailing 'dart'.
      pathSegments.removeLast();
      expectedSegments.removeLast();

      while (expectedSegments.isNotEmpty) {
        if (expectedSegments.last == pathSegments.last) {
          pathSegments.removeLast();
          expectedSegments.removeLast();
        } else {
          break;
        }
      }

      if (expectedSegments.isEmpty) {
        final flutterSdkRoot = path.joinAll(pathSegments);
        return FlutterSdk._(flutterSdkRoot);
      }
    }

    throw Exception(
      'Unable to locate the Flutter SDK from the current running Dart VM:\n'
      '${Platform.resolvedExecutable}',
    );
  }

  static FlutterSdk findFromPath(String sdkPath) {
    var resolvedPath = sdkPath;
    try {
      resolvedPath = File(sdkPath).resolveSymbolicLinksSync();
    } catch (_) {
      // Fallback to the unresolved path if resolution fails.
    }

    final resolvedPathParent = path.dirname(resolvedPath);
    if (path.basename(resolvedPathParent) == 'bin') {
      return FlutterSdk._(path.dirname(resolvedPathParent));
    } else if (path.basename(resolvedPath) == 'bin') {
      return FlutterSdk._(resolvedPathParent);
    } else if (Directory(path.join(resolvedPath, 'bin')).existsSync()) {
      return FlutterSdk._(resolvedPath);
    }

    throw Exception('Unable to locate the Flutter SDK at "$sdkPath"');
  }

  /// Finds a Flutter SDK in the `PATH` environment variable
  /// (by running which/where).
  ///
  /// Throws if an SDK is not found on PATH.
  static FlutterSdk findFromPathEnvironmentVariable() {
    final whichCommand = Platform.isWindows ? 'where.exe' : 'which';
    final result = Process.runSync(whichCommand, ['flutter']);
    if (result.exitCode == 0) {
      final sdkPath = result.stdout.toString().split('\n').first.trim();
      return findFromPath(sdkPath);
    }

    throw Exception('Unable to locate the Flutter SDK on PATH');
  }

  final String sdkPath;

  /// The name of the 'flutter' shell script for the current platform.
  static String get flutterExecutableName => shellScriptName('flutter');

  /// The name of the 'dart' wrapper shell script in Flutter for the current
  /// platform.
  ///
  /// On windows, 'dart' is fine for running the .exe from the Dart SDK directly
  /// but the wrapper in the Flutter bin folder is a .bat and needs an explicit
  /// extension.
  static String get dartWrapperExecutableName => shellScriptName('dart');

  String get flutterExePath => path.join(sdkPath, 'bin', flutterExecutableName);

  String get dartExePath =>
      path.join(sdkPath, 'bin', dartWrapperExecutableName);

  String get dartSdkPath => path.join(sdkPath, 'bin', 'cache', 'dart-sdk');

  String get pubToolPath => path.join(dartSdkPath, 'bin', 'pub');

  @override
  String toString() => '[Flutter sdk: $sdkPath]';
}

class Package {
  Package._(this.repo, this.packagePath);

  final DevToolsRepo repo;
  final String packagePath;

  String get relativePath => path.relative(packagePath, from: repo.repoPath);

  bool get hasAnyDartCode {
    final dartFiles = <String>[];

    _collectDartFiles(Directory(packagePath), dartFiles);

    return dartFiles.isNotEmpty;
  }

  void _collectDartFiles(Directory dir, List<String> result) {
    for (final entity in dir.listSync(followLinks: false)) {
      final name = path.basename(entity.path);
      if (entity is Directory && !name.startsWith('.') && name != 'build') {
        _collectDartFiles(entity, result);
      } else if (entity is File && path.extension(name) == '.dart') {
        result.add(entity.path);
      }
    }
  }

  @override
  String toString() => '[Package $relativePath]';
}

bool _fileExists(Directory parent, String name) {
  return FileSystemEntity.isFileSync(path.join(parent.path, name));
}

bool _dirExists(Directory parent, String name) {
  return FileSystemEntity.isDirectorySync(path.join(parent.path, name));
}

extension _SafeAccessList<T> on List<T> {
  T? safeRemoveLast() => isNotEmpty ? removeLast() : null;
}
