// 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].
  ///
  /// If [containingPath] is `null` they are serialized as absolute.
  @override
  dynamic serializeDescription(String? containingPath, description) {
    if (description['relative'] == true && containingPath != null) {
      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));
  }
}
