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

library pub.source;

import 'dart:async' hide TimeoutException;

import 'package:path/path.dart' as path;

import 'io.dart';
import 'package.dart';
import 'pubspec.dart';
import 'system_cache.dart';
import 'utils.dart';
import 'version.dart';

/// A source from which to get packages.
///
/// Each source has many packages that it looks up using [PackageId]s. The
/// source is responsible for getting these packages into the package cache.
abstract class Source {
  /// The name of the source. Should be lower-case, suitable for use in a
  /// filename, and unique accross all sources.
  String get name;

  /// Whether or not this source is the default source.
  bool get isDefault => systemCache.sources.defaultSource == this;

  /// Whether this source's packages should be cached in Pub's global cache
  /// directory.
  ///
  /// A source should be cached if it requires network access to retrieve
  /// packages. It doesn't need to be cached if all packages are available
  /// locally.
  bool get shouldCache;

  /// The system cache with which this source is registered.
  SystemCache get systemCache {
    assert(_systemCache != null);
    return _systemCache;
  }

  /// The system cache variable. Set by [_bind].
  SystemCache _systemCache;

  /// The root directory of this source's cache within the system cache.
  ///
  /// This shouldn't be overridden by subclasses.
  String get systemCacheRoot => path.join(systemCache.rootDir, name);

  /// Records the system cache to which this source belongs.
  ///
  /// This should only be called once for each source, by
  /// [SystemCache.register]. It should not be overridden by base classes.
  void bind(SystemCache systemCache) {
    assert(_systemCache == null);
    this._systemCache = systemCache;
  }

  /// Get the list of all versions that exist for the package described by
  /// [description]. [name] is the expected name of the package.
  ///
  /// Note that this does *not* require the package to be downloaded locally,
  /// which is the point. This is used during version resolution to determine
  /// which package versions are available to be downloaded (or already
  /// downloaded).
  ///
  /// By default, this assumes that each description has a single version and
  /// uses [describe] to get that version.
  Future<List<Version>> getVersions(String name, description) {
    var id = new PackageId(name, this.name, Version.none, description);
    return describeUncached(id).then((pubspec) => [pubspec.version]);
  }

  /// Loads the (possibly remote) pubspec for the package version identified by
  /// [id]. This may be called for packages that have not yet been downloaded
  /// during the version resolution process.
  ///
  /// If the package has been downloaded to the system cache, the cached pubspec
  /// will be used. Otherwise, it delegates to host-specific lookup behavior.
  ///
  /// For cached sources, by default this uses [downloadToSystemCache] to get
  /// the pubspec. There is no default implementation for non-cached sources;
  /// they must implement it manually.
  Future<Pubspec> describe(PackageId id) {
    if (id.isRoot) throw new ArgumentError("Cannot describe the root package.");
    if (id.source != name) {
      throw new ArgumentError("Package $id does not use source $name.");
    }

    // Try to get it from the system cache first.
    if (shouldCache) {
      return systemCacheDirectory(id).then((packageDir) {
        if (!fileExists(path.join(packageDir, "pubspec.yaml"))) {
          return describeUncached(id);
        }

        return new Pubspec.load(packageDir, _systemCache.sources,
            expectedName: id.name);
      });
    }

    // Not cached, so get it from the source.
    return describeUncached(id);
  }

  /// Loads the pubspec for the package version identified by [id] which is not
  /// already in the system cache.
  ///
  /// For cached sources, by default this uses [downloadToSystemCache] to get
  /// the pubspec. There is no default implementation for non-cached sources;
  /// they must implement it manually.
  ///
  /// This method is effectively protected. Derived classes may override it,
  /// but external code should not call it. Call [describe()] instead.
  Future<Pubspec> describeUncached(PackageId id) {
    if (!shouldCache) {
      throw new UnimplementedError(
          "Source $name must implement describeUncached(id).");
    }
    return downloadToSystemCache(id).then((package) => package.pubspec);
  }

  /// Gets the package identified by [id] and places it at [path].
  ///
  /// Returns a [Future] that completes when the operation finishes. The
  /// [Future] should resolve to true if the package was found in the source
  /// and false if it wasn't. For all other error conditions, it should complete
  /// with an exception.
  ///
  /// [path] is guaranteed not to exist, and its parent directory is guaranteed
  /// to exist.
  ///
  /// Note that [path] may be deleted. If re-getting a package that has already
  /// been gotten would be costly or impossible, [downloadToSystemCache]
  /// should be implemented instead of [get].
  ///
  /// This doesn't need to be implemented if [downloadToSystemCache] is
  /// implemented.
  Future<bool> get(PackageId id, String path) {
    throw new UnimplementedError("Either get() or downloadToSystemCache() must "
        "be implemented for source $name.");
  }

  /// Downloads the package identified by [id] to the system cache. This is only
  /// called for sources with [shouldCache] set to true.
  ///
  /// By default, this uses [systemCacheDirectory] and [get].
  Future<Package> downloadToSystemCache(PackageId id) {
    var packageDir;
    return systemCacheDirectory(id).then((p) {
      packageDir = p;

      // See if it's already cached.
      if (dirExists(packageDir)) {
        if (!_isCachedPackageCorrupted(packageDir)) return true;
        // Busted, so wipe out the package and re-download.
        deleteEntry(packageDir);
      }

      ensureDir(path.dirname(packageDir));
      return get(id, packageDir);
    }).then((found) {
      if (!found) fail('Package $id not found.');
      return new Package.load(id.name, packageDir, systemCache.sources);
    });
  }

  /// Since pub generates symlinks that point into the system cache (in
  /// particular, targeting the "lib" directories of cached packages), it's
  /// possible to accidentally break cached packages if something traverses
  /// that symlink.
  ///
  /// This tries to determine if the cached package at [packageDir] has been
  /// corrupted. The heuristics are it is corrupted if any of the following are
  /// true:
  ///
  ///   * It has an empty "lib" directory.
  ///   * It has no pubspec.
  bool _isCachedPackageCorrupted(String packageDir) {
    if (!fileExists(path.join(packageDir, "pubspec.yaml"))) return true;

    var libDir = path.join(packageDir, "lib");
    if (dirExists(libDir)) return listDir(libDir).length == 0;

    // If we got here, it's OK.
    return false;
  }

  /// Returns the directory where this package can be found locally. If this is
  /// a cached source, it will be in the system cache. Otherwise, it will
  /// depend on the source.
  Future<String> getDirectory(PackageId id) {
    if (shouldCache) return systemCacheDirectory(id);
    throw new UnimplementedError("Source $name must implement this.");
  }

  /// Returns the directory in the system cache that the package identified by
  /// [id] should be downloaded to. This should return a path to a subdirectory
  /// of [systemCacheRoot].
  ///
  /// This doesn't need to be implemented if [shouldCache] is false.
  Future<String> systemCacheDirectory(PackageId id) {
    return new Future.error(
        "systemCacheDirectory() must be implemented if shouldCache is true.");
  }

  /// When a [Pubspec] or [LockFile] is parsed, it reads in the description for
  /// each dependency. It is up to the dependency's [Source] to determine how
  /// that should be interpreted. This will be called during parsing to validate
  /// that the given [description] is well-formed according to this source, and
  /// to give the source a chance to canonicalize the description.
  ///
  /// [containingPath] is the path to the local file (pubspec or lockfile)
  /// where this description appears. It may be `null` if the description is
  /// coming from some in-memory source (such as pulling down a pubspec from
  /// pub.dartlang.org).
  ///
  /// It should return if a (possibly modified) valid description, or throw a
  /// [FormatException] if not valid.
  ///
  /// [fromLockFile] is true when the description comes from a [LockFile], to
  /// allow the source to use lockfile-specific descriptions via [resolveId].
  dynamic parseDescription(String containingPath, description,
                           {bool fromLockFile: false}) {
    return description;
  }

  /// When a [LockFile] is serialized, it uses this method to get the
  /// [description] in the right format. [containingPath] references the
  /// containing directory of the root package.
  dynamic serializeDescription(String containingPath, description) {
    return description;
  }

  /// Returns whether or not [description1] describes the same package as
  /// [description2] for this source. This method should be light-weight. It
  /// doesn't need to validate that either package exists.
  ///
  /// By default, just uses regular equality.
  bool descriptionsEqual(description1, description2) =>
    description1 == description2;

  /// For some sources, [PackageId]s can point to different chunks of code at
  /// different times. This takes such an [id] and returns a future that
  /// completes to a [PackageId] that will uniquely specify a single chunk of
  /// code forever.
  ///
  /// For example, [GitSource] might take an [id] with description
  /// `http://github.com/dart-lang/some-lib.git` and return an id with a
  /// description that includes the current commit of the Git repository.
  ///
  /// Pub calls this after getting a package, so the source can use the local
  /// package to determine information about the resolved id.
  ///
  /// The returned [PackageId] may have a description field that's invalid
  /// according to [parseDescription], although it must still be serializable
  /// to JSON and YAML. It must also be equal to [id] according to
  /// [descriptionsEqual].
  ///
  /// By default, this just returns [id].
  Future<PackageId> resolveId(PackageId id) => new Future.value(id);

  /// Returns the [Package]s that have been downloaded to the system cache.
  List<Package> getCachedPackages() {
    if (shouldCache) {
      throw new UnimplementedError("Source $name must implement this.");
    }
  }

  /// Returns the source's name.
  String toString() => name;
}
