// Copyright (c) 2016, 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.

import 'dart:async';

import 'package:pub_semver/pub_semver.dart';

import '../exceptions.dart';
import '../language_version.dart';
import '../package_name.dart';
import '../pubspec.dart';
import '../sdk.dart';
import '../source.dart';
import '../system_cache.dart';
import '../utils.dart';

/// A package [Source] that gets packages from a hard-coded SDK.
class SdkSource extends Source {
  static final SdkSource instance = SdkSource._();

  SdkSource._();

  @override
  final name = 'sdk';

  /// Parses an SDK dependency.
  @override
  PackageRef parseRef(String name, description,
      {String? containingDir, LanguageVersion? languageVersion}) {
    if (description is! String) {
      throw FormatException('The description must be an SDK name.');
    }

    return PackageRef(name, SdkDescription(description));
  }

  @override
  PackageId parseId(String name, Version version, description,
      {String? containingDir}) {
    if (description is! String) {
      throw FormatException('The description must be an SDK name.');
    }

    return PackageId(
      name,
      version,
      ResolvedSdkDescription(SdkDescription(description)),
    );
  }

  @override
  Future<List<PackageId>> doGetVersions(
      PackageRef ref, Duration? maxAge, SystemCache cache) async {
    final description = ref.description;
    if (description is! SdkDescription) {
      throw ArgumentError('Wrong source');
    }
    var pubspec = _loadPubspec(ref, cache);
    var id = PackageId(
      ref.name,
      pubspec.version,
      ResolvedSdkDescription(description),
    );
    // Store the pubspec in memory if we need to refer to it again.
    cache.cachedPubspecs[id] = pubspec;
    return [id];
  }

  @override
  Future<Pubspec> doDescribe(
    PackageId id,
    SystemCache cache,
  ) async =>
      _loadPubspec(id.toRef(), cache);

  /// Loads the pubspec for the SDK package named [ref].
  ///
  /// Throws a [PackageNotFoundException] if [ref]'s SDK is unavailable or
  /// doesn't contain the package.
  Pubspec _loadPubspec(PackageRef ref, SystemCache cache) =>
      Pubspec.load(_verifiedPackagePath(ref), cache.sources,
          expectedName: ref.name);

  /// Returns the path for the given [ref].
  ///
  /// Throws a [PackageNotFoundException] if [ref]'s SDK is unavailable or
  /// doesn't contain the package.
  String _verifiedPackagePath(PackageRef ref) {
    final description = ref.description;
    if (description is! SdkDescription) {
      throw ArgumentError('Wrong source');
    }
    var sdkName = description.sdk;
    var sdk = sdks[sdkName];
    if (sdk == null) {
      throw PackageNotFoundException('unknown SDK "$sdkName"');
    } else if (!sdk.isAvailable) {
      throw PackageNotFoundException(
        'the ${sdk.name} SDK is not available',
        hint: sdk.installMessage,
      );
    }

    var path = sdk.packagePath(ref.name);
    if (path != null) return path;

    throw PackageNotFoundException(
        'could not find package ${ref.name} in the ${sdk.name} SDK');
  }

  @override
  String doGetDirectory(PackageId id, SystemCache cache,
      {String? relativeFrom}) {
    try {
      return _verifiedPackagePath(id.toRef());
    } on PackageNotFoundException catch (error) {
      // [PackageNotFoundException]s are uncapitalized and unpunctuated because
      // they're used within other sentences by the version solver, but
      // [ApplicationException]s should be full sentences.
      throw ApplicationException('${capitalize(error.message)}.');
    }
  }
}

class SdkDescription extends Description {
  /// The sdk the described package comes from.
  final String sdk;

  SdkDescription(this.sdk);
  @override
  String format() => sdk;

  @override
  Object? serializeForPubspec({
    required String? containingDir,
    required LanguageVersion languageVersion,
  }) {
    return sdk;
  }

  @override
  Source get source => SdkSource.instance;

  @override
  int get hashCode => sdk.hashCode;

  @override
  bool operator ==(Object other) {
    return other is SdkDescription && other.sdk == sdk;
  }
}

class ResolvedSdkDescription extends ResolvedDescription {
  @override
  SdkDescription get description => super.description as SdkDescription;

  ResolvedSdkDescription(SdkDescription description) : super(description);

  @override
  Object? serializeForLockfile({required String? containingDir}) {
    return description.sdk;
  }

  @override
  int get hashCode => description.hashCode;

  @override
  bool operator ==(Object other) {
    return other is ResolvedSdkDescription && other.description == description;
  }
}
