// Copyright (c) 2013, 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:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';

import '../exceptions.dart';
import '../io.dart';
import '../language_version.dart';
import '../package_name.dart';
import '../pubspec.dart';
import '../source.dart';
import '../system_cache.dart';
import 'git.dart';
import 'hosted.dart';
import 'root.dart';

/// A package [Source] that gets packages from a given local file path.
class PathSource extends Source {
  static PathSource instance = PathSource._();
  PathSource._();

  @override
  final name = 'path';

  // /// Returns a reference to a path package named [name] at [path].
  // PackageRef<PathDescription> refFor(String name, String path) {
  //   if (p.isRelative(path)) {
  //     PackageRef(name, {'path':p.absolute(path), 'relative': p.isRelative(path)});
  //   }
  //   return PackageRef(name, {'path': path, 'relative': p.isRelative(path)});
  // }
//{name: myapp, dev_dependencies: {foo: 1.2.2}, dependency_overrides: {foo: {path: ../foo}}, environment: {sdk: >=0.1.2 <1.0.0}}
//{name: myapp, dev_dependencies: {foo: ^1.2.2}, dependency_overrides: {foo: {path: ../foo}}, environment: {sdk: >=0.1.2 <1.0.0}}
  /// Returns an ID for a path package with the given [name] and [version] at
  /// [path].
  ///
  /// If [path] is relative it is resolved relative to [relativeTo]
  PackageId idFor(
    String name,
    Version version,
    String path,
    String relativeTo,
  ) {
    return PackageId(
      name,
      version,
      ResolvedPathDescription(
        PathDescription(p.join(relativeTo, path), p.isRelative(path)),
      ),
    );
  }

  /// Parses a path dependency.
  ///
  /// This takes in a path string and returns a map. The "path" key will be the
  /// original path but resolved relative to the containing path. The
  /// "relative" key will be `true` if the original path was relative.
  @override
  PackageRef parseRef(
    String name,
    Object? description, {
    required Description containingDescription,
    LanguageVersion? languageVersion,
  }) {
    if (description is! String) {
      throw const FormatException('The description must be a path string.');
    }
    final dir = description;
    // Resolve the path relative to the containing file path, and remember
    // whether the original path was relative or absolute.
    final isRelative = p.isRelative(dir);

    if (containingDescription is PathDescription) {
      return PackageRef(
        name,
        PathDescription(
          isRelative
              ? p.join(p.absolute(containingDescription.path), dir)
              : dir,
          isRelative,
        ),
      );
    } else if (containingDescription is RootDescription) {
      return PackageRef(
        name,
        PathDescription(
          p.normalize(
            p.join(
              p.absolute(containingDescription.path),
              description,
            ),
          ),
          isRelative,
        ),
      );
    } else if (containingDescription is GitDescription) {
      if (!isRelative) {
        throw FormatException(
          '"$description" is an absolute path, it can\'t be referenced from a git pubspec.',
        );
      }
      final resolvedPath = p.url.normalize(
        p.url.joinAll([
          containingDescription.path,
          ...p.posix.split(dir),
        ]),
      );
      if (!(p.isWithin('.', resolvedPath) || p.equals('.', resolvedPath))) {
        throw FormatException(
          'the path "$description" cannot refer outside the git repository $resolvedPath.',
        );
      }
      return PackageRef(
        name,
        GitDescription.raw(
          url: containingDescription.url,
          relative: containingDescription.relative,
          ref: containingDescription.ref,
          path: resolvedPath,
        ),
      );
    } else if (containingDescription is HostedDescription) {
      if (isRelative) {
        throw FormatException('"$description" is a relative path, but this '
            'isn\'t a local pubspec.');
      }
      return PackageRef(name, PathDescription(dir, false));
    } else {
      throw FormatException('"$description" is a path, but this '
          'isn\'t a local pubspec.');
    }
  }

  @override
  PackageId parseId(
    String name,
    Version version,
    Object? description, {
    String? containingDir,
  }) {
    if (description is! Map) {
      throw const FormatException('The description must be a map.');
    }
    var path = description['path'];
    if (path is! String) {
      throw const FormatException("The 'path' field of the description must "
          'be a string.');
    }
    final relative = description['relative'];
    if (relative is! bool) {
      throw const FormatException("The 'relative' field of the description "
          'must be a boolean.');
    }

    // Resolve the path relative to the containing file path.
    if (relative) {
      // Relative paths coming from lockfiles that are not on the local file
      // system aren't allowed.
      if (containingDir == null) {
        throw FormatException('"$description" is a relative path, but this '
            'isn\'t a local pubspec.');
      }

      path = p.normalize(
        p.absolute(p.join(containingDir, path)),
      );
    }

    return PackageId(
      name,
      version,
      ResolvedPathDescription(PathDescription(path, relative)),
    );
  }

  /// On both Windows and linux we prefer `/` in the pubspec.lock for relative
  /// paths.
  static String relativePathWithPosixSeparators(String path) {
    assert(p.isRelative(path));
    return p.posix.joinAll(p.split(path));
  }

  @override
  Future<List<PackageId>> doGetVersions(
    PackageRef ref,
    Duration? maxAge,
    SystemCache cache,
  ) async {
    final description = ref.description;
    if (description is! PathDescription) {
      throw ArgumentError('Wrong source');
    }
    // There's only one package ID for a given path. We just need to find the
    // version.
    final pubspec = _loadPubspec(ref, cache);
    final id = PackageId(
      ref.name,
      pubspec.version,
      ResolvedPathDescription(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);

  Pubspec _loadPubspec(PackageRef ref, SystemCache cache) {
    final description = ref.description;
    if (description is! PathDescription) {
      throw ArgumentError('Wrong source');
    }
    final dir = _validatePath(ref.name, description);
    return Pubspec.load(
      dir,
      cache.sources,
      containingDescription: description,
      expectedName: ref.name,
    );
  }

  @override
  String doGetDirectory(
    PackageId id,
    SystemCache cache, {
    String? relativeFrom,
  }) {
    final description = id.description.description;
    if (description is! PathDescription) {
      throw ArgumentError('Wrong source');
    }
    return description.relative
        ? p.relative(description.path, from: relativeFrom)
        : description.path;
  }

  /// Ensures that [description] is a valid path description and returns a
  /// normalized path to the package.
  ///
  /// It must be a map, with a "path" key containing a path that points to an
  /// existing directory. Throws an [PackageNotFoundException] if the path is
  /// invalid or a pubspec.yaml file doesn't exist at the location.
  String _validatePath(String name, PathDescription description) {
    final dir = description.path;

    if (dirExists(dir)) {
      final pubspecPath = p.join(dir, 'pubspec.yaml');
      if (!fileExists(pubspecPath)) {
        throw PackageNotFoundException(
          'No pubspec.yaml found for package $name in $dir.',
          innerError: FileException('$pubspecPath doesn\'t exist', pubspecPath),
        );
      }
      return dir;
    }
    if (fileExists(dir)) {
      throw PackageNotFoundException(
        'Path dependency for package $name must refer to a directory, '
        'not a file. Was "$dir".',
        innerError: FileException('$dir is not a directory.', dir),
      );
    }
    throw PackageNotFoundException(
      'could not find package $name at "${description.format()}"',
      innerError: FileException('$dir does not exist.', dir),
    );
  }
}

class PathDescription extends Description {
  final String path;
  final bool relative;

  PathDescription(this.path, this.relative) : assert(!p.isRelative(path));
  @override
  String format() {
    return relative ? p.relative(path) : path;
  }

  @override
  Object? serializeForPubspec({
    required String? containingDir,
    required LanguageVersion languageVersion,
  }) {
    return relative
        ? PathSource.relativePathWithPosixSeparators(
            p.relative(path, from: containingDir),
          )
        : path;
  }

  @override
  Source get source => PathSource.instance;

  @override
  bool operator ==(Object other) {
    return other is PathDescription &&
        canonicalize(path) == canonicalize(other.path);
  }

  @override
  int get hashCode => canonicalize(path).hashCode;
}

class ResolvedPathDescription extends ResolvedDescription {
  @override
  PathDescription get description => super.description as PathDescription;

  ResolvedPathDescription(PathDescription super.description);

  @override
  Object? serializeForLockfile({required String? containingDir}) {
    if (description.relative) {
      return {
        'path': PathSource.relativePathWithPosixSeparators(
          p.relative(description.path, from: containingDir),
        ),
        'relative': true,
      };
    }
    return {'path': description.path, 'relative': p.relative('false')};
  }

  @override
  bool operator ==(Object other) =>
      other is ResolvedPathDescription && other.description == description;

  @override
  int get hashCode => description.hashCode;
}
