// 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 '../utils.dart';

/// A package [Source] that gets packages from a given local file path.
class PathSource extends Source {
  @override
  final name = 'path';

  @override
  BoundSource bind(SystemCache systemCache) =>
      BoundPathSource(this, systemCache);

  /// Given a valid path reference description, returns the file path it
  /// describes.
  ///
  /// This returned path may be relative or absolute and it is up to the caller
  /// to know how to interpret a relative path.
  String pathFromDescription(description) => description['path'];

  /// Returns a reference to a path package named [name] at [path].
  PackageRef refFor(String name, String path) {
    return PackageRef(
        name, this, {'path': path, 'relative': p.isRelative(path)});
  }

  /// Returns an ID for a path package with the given [name] and [version] at
  /// [path].
  PackageId idFor(String name, Version version, String path) {
    return PackageId(
        name, this, version, {'path': path, 'relative': p.isRelative(path)});
  }

  @override
  bool descriptionsEqual(description1, description2) {
    // Compare real paths after normalizing and resolving symlinks.
    var path1 = canonicalize(description1['path']);
    var path2 = canonicalize(description2['path']);
    return path1 == path2;
  }

  @override
  int hashDescription(description) =>
      canonicalize(description['path']).hashCode;

  /// 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,
    description, {
    String? containingPath,
    LanguageVersion? languageVersion,
  }) {
    if (description is! String) {
      throw FormatException('The description must be a path string.');
    }

    // Resolve the path relative to the containing file path, and remember
    // whether the original path was relative or absolute.
    var isRelative = p.isRelative(description);
    if (isRelative) {
      // Relative paths coming from pubspecs that are not on the local file
      // system aren't allowed. This can happen if a hosted or git dependency
      // has a path dependency.
      if (containingPath == null) {
        throw FormatException('"$description" is a relative path, but this '
            'isn\'t a local pubspec.');
      }

      description = p.normalize(p.join(p.dirname(containingPath), description));
    }

    return PackageRef(
        name, this, {'path': description, 'relative': isRelative});
  }

  @override
  PackageId parseId(String name, Version version, description,
      {String? containingPath}) {
    if (description is! Map) {
      throw FormatException('The description must be a map.');
    }

    if (description['path'] is! String) {
      throw FormatException("The 'path' field of the description must "
          'be a string.');
    }

    if (description['relative'] is! bool) {
      throw FormatException("The 'relative' field of the description "
          'must be a boolean.');
    }

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

      description = Map.from(description);
      description['path'] =
          p.normalize(p.join(p.dirname(containingPath), description['path']));
    }

    return PackageId(name, this, version, description);
  }

  /// Serializes path dependency's [description].
  ///
  /// For the descriptions where `relative` attribute is `true`, tries to make
  /// `path` relative to the specified [containingPath].
  @override
  dynamic serializeDescription(String containingPath, description) {
    if (description['relative']) {
      return {
        'path': relativePathWithPosixSeparators(
            p.relative(description['path'], from: containingPath)),
        'relative': true
      };
    }
    return description;
  }

  /// 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));
  }

  /// Converts a parsed relative path to its original relative form.
  @override
  String formatDescription(description) {
    var sourcePath = description['path'];
    if (description['relative']) sourcePath = p.relative(description['path']);
    return sourcePath;
  }
}

/// The [BoundSource] for [PathSource].
class BoundPathSource extends BoundSource {
  @override
  final PathSource source;

  @override
  final SystemCache systemCache;

  BoundPathSource(this.source, this.systemCache);

  @override
  Future<List<PackageId>> doGetVersions(
      PackageRef ref, Duration? maxAge) async {
    // There's only one package ID for a given path. We just need to find the
    // version.
    var pubspec = _loadPubspec(ref);
    var id = PackageId(ref.name, source, pubspec.version, ref.description);
    memoizePubspec(id, pubspec);
    return [id];
  }

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

  Pubspec _loadPubspec(PackageRef ref) {
    var dir = _validatePath(ref.name, ref.description);
    return Pubspec.load(dir, systemCache.sources, expectedName: ref.name);
  }

  @override
  String getDirectory(PackageId id, {String? relativeFrom}) {
    return id.description['relative']
        ? p.relative(id.description['path'], from: relativeFrom)
        : id.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 [ApplicationException] if the path is
  /// invalid.
  String _validatePath(String name, description) {
    var dir = description['path'];

    if (dirExists(dir)) return dir;

    if (fileExists(dir)) {
      fail('Path dependency for package $name must refer to a directory, '
          'not a file. Was "$dir".');
    }

    throw PackageNotFoundException('could not find package $name at "$dir"',
        innerError: FileException('$dir does not exist.', dir));
  }
}
