// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/// Abstractions for the different sources of truth for different packages.
import 'dart:io';

import 'package:nnbd_migration/src/utilities/subprocess_launcher.dart';
import 'package:path/path.dart' as path;

final String defaultPlaygroundPath =
    Platform.environment['TRIAL_MIGRATION_PLAYGROUND'] ??
        resolveTildePath('~/.nnbd_trial_migration');

/// The pub cache inherited by this process.
final String defaultPubCache =
    Platform.environment['PUB_CACHE'] ?? resolveTildePath('~/.pub-cache');

/// Returns the path to the SDK repository this script is a part of.
final String thisSdkRepo = () {
  var maybeSdkRepoDir = Platform.script.toFilePath();
  while (maybeSdkRepoDir != path.dirname(maybeSdkRepoDir)) {
    maybeSdkRepoDir = path.dirname(maybeSdkRepoDir);
    if (File(path.join(maybeSdkRepoDir, 'README.dart-sdk')).existsSync()) {
      return maybeSdkRepoDir;
    }
  }
  throw UnsupportedError(
      'Script ${Platform.script} using this library must be within the SDK repository');
}();
Uri get thisSdkUri => Uri.file(thisSdkRepo);

/// Return a resolved path including the home directory in place of tilde
/// references.
String resolveTildePath(String originalPath) {
  if (!originalPath.startsWith('~/')) {
    return originalPath;
  }

  String homeDir;

  if (Platform.isWindows) {
    homeDir = path.absolute(Platform.environment['USERPROFILE']!);
  } else {
    homeDir = path.absolute(Platform.environment['HOME']!);
  }

  return path.join(homeDir, originalPath.substring(2));
}

/// Abstraction for a package fetched via Git.
class GitPackage extends Package {
  static final RegExp _pathAndPeriodSplitter = RegExp('[\\/.]');
  final String _clonePath;
  final bool? _keepUpdated;
  final String label;

  final Playground _playground;

  SubprocessLauncher? _launcher;

  String? _packagePath;

  GitPackage._(this._clonePath, this._playground, this._keepUpdated,
      {String? name, this.label = 'master'})
      : super(name ?? _buildName(_clonePath));

  SubprocessLauncher get launcher =>
      _launcher ??= SubprocessLauncher('$name-$label', _playground.env);

  @override
  List<String?> get migrationPaths => [_packagePath];
  String get packagePath =>
      // TODO(jcollins-g): allow packages from subdirectories of clones
      _packagePath ??= path.join(_playground.playgroundPath, '$name-$label');

  @override
  String toString() {
    return '$_clonePath ($label)${_keepUpdated! ? ' [synced]' : ''}';
  }

  /// Initialize the package with a shallow clone.  Run only once per
  /// [GitPackage] instance.
  Future<void> _init() async {
    if (_keepUpdated! || !await Directory(packagePath).exists()) {
      // Clone or update.
      if (await Directory(packagePath).exists()) {
        await launcher.runStreamed('git', ['pull'],
            workingDirectory: packagePath);
      } else {
        await launcher.runStreamed('git',
            ['clone', '--branch=$label', '--depth=1', _clonePath, packagePath],
            workingDirectory: _playground.playgroundPath);
        await launcher.runStreamed('git', ['checkout', '-b', '_test_migration'],
            workingDirectory: packagePath);
        await launcher.runStreamed(
            'git', ['branch', '--set-upstream-to', 'origin/$label'],
            workingDirectory: packagePath);
        // TODO(jcollins-g): allow for migrating dependencies?
      }
      await pubTracker.runFutureFromClosure(() =>
          launcher.runStreamed('pub', ['get'], workingDirectory: packagePath));
    }
  }

  static Future<GitPackage> gitPackageFactory(
      String clonePath, Playground playground, bool? keepUpdated,
      {String? name, String label = 'master'}) async {
    GitPackage gitPackage = GitPackage._(clonePath, playground, keepUpdated,
        name: name, label: label);
    await gitPackage._init();
    return gitPackage;
  }

  /// Calculate the "humanish" name of the clone (see `git help clone`).
  static String _buildName(String clonePath) {
    if (Directory(clonePath).existsSync()) {
      // assume we are cloning locally
      return path.basename(clonePath);
    }
    List<String> pathParts = clonePath.split(_pathAndPeriodSplitter);
    int indexOfName = pathParts.lastIndexOf('git') - 1;
    if (indexOfName < 0) {
      throw ArgumentError(
          'GitPackage can not figure out the name for $clonePath, pass it in manually?');
    }
    return pathParts[indexOfName];
  }
}

/// Abstraction for an unmanaged package.
class ManualPackage extends Package {
  final String _packagePath;
  ManualPackage(this._packagePath) : super(_packagePath);

  @override
  List<String> get migrationPaths => [_packagePath];
}

/// Base class for pub, github, SDK, or possibly other package sources.
abstract class Package {
  final String name;

  Package(this.name);

  /// Returns the set of directories for this package.
  List<String?> get migrationPaths;

  @override
  String toString() => name;
}

class Playground {
  final String playgroundPath;

  /// If [clean] is true, this will delete the playground.  Otherwise,
  /// if it exists it will assume it is properly constructed.
  Playground(this.playgroundPath, bool clean) {
    Directory playground = Directory(playgroundPath);
    if (clean) {
      if (playground.existsSync()) {
        playground.deleteSync(recursive: true);
      }
    }
    if (!playground.existsSync()) playground.createSync();
  }

  /// Build an environment for subprocesses.
  Map<String, String> get env => {'PUB_CACHE': pubCachePath};

  String get pubCachePath => path.join(playgroundPath, '.pub-cache');
}

/// Abstraction for a package fetched via pub.
class PubPackage extends Package {
  PubPackage(super.name, [String? version]) {
    throw UnimplementedError();
  }

  @override
  // TODO: implement packagePath
  List<String> get migrationPaths => throw UnimplementedError();
}

/// Abstraction for compiled Dart SDKs (not this repository).
class Sdk {
  /// The root of the compiled SDK.
  late final String sdkPath;

  Sdk(String sdkPath) {
    this.sdkPath = path.canonicalize(sdkPath);
  }
}

/// Abstraction for a package located within pkg or third_party/pkg.
class SdkPackage extends Package {
  /// Where to find packages.  Constructor searches in-order.
  static final List<String> _searchPaths = [
    'pkg',
    path.join('third_party', 'pkg'),
  ];

  late final String _packagePath;

  SdkPackage(String name) : super(name) {
    for (String potentialPath
        in _searchPaths.map((p) => path.join(thisSdkRepo, p, name))) {
      if (Directory(potentialPath).existsSync()) {
        _packagePath = potentialPath;
      }
    }
  }
  @override
  List<String> get migrationPaths => [_packagePath];

  @override
  String toString() => path.relative(_packagePath, from: thisSdkRepo);
}
