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

/// A programmatic API for reflecting on Pub's cache directory.
library pub_cache;

import 'dart:io';

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

import 'src/impl.dart';

/// A programmatic API for reflecting on Pub's cache directory.
class PubCache {
  /// Return the location of Pub's package cache.
  static Directory getSystemCacheLocation() {
    Map env = Platform.environment;

    if (env.containsKey('PUB_CACHE')) {
      return new Directory(env['PUB_CACHE']);
    } else if (Platform.operatingSystem == 'windows') {
      return new Directory(path.join(env['APPDATA'], 'Pub', 'Cache'));
    } else {
      return new Directory('${env['HOME']}/.pub-cache');
    }
  }

  // The location of the pub cache.
  final Directory location;

  List<Application> _applications;
  List<PackageRef> _packageRefs;

  String get _hostedPackageDirectoryName {
    final url = Uri.parse(Platform.environment['PUB_HOSTED_URL'] ?? 'https://pub.dartlang.org');
    return url.host;
  }

  /// Create a pubcache instance. [dir] defaults to the default platform pub
  /// cache location.
  PubCache([Directory dir])
      : location = dir == null ? getSystemCacheLocation() : dir {
    _parse();
  }

  /// Return the contents of `bin/` - the scripts for the activated applications.
  List<File> getBinScripts() {
    Directory dir = _getSubDir(location, 'bin');
    return dir.existsSync()
        ? dir.listSync().where((entity) => entity is File).cast<File>().toList()
        : <File>[];
  }

  /// Return applications that have been installed via `pub global activate`.
  List<Application> getGlobalApplications() => _applications;

  /// Get all the packages and their versions that have been installed into the
  /// cache.
  List<PackageRef> getPackageRefs() => _packageRefs;

  /// Return the list of package names (not versions) that are available in the
  /// cache.
  List<String> getCachedPackages() =>
      new Set<String>.from(getPackageRefs().map((p) => p.name)).toList();

  /// Return all available cached versions for a given package.
  List<PackageRef> getAllPackageVersions(String packageName) =>
      getPackageRefs().where((p) => p.name == packageName).toList();

  /// Return the most recent verison of the given package contained in the
  /// cache. This method will prefer to return only release verions. If
  /// [includePreRelease] is true, then the very latest verision will be
  /// returned, include pre-release versions.
  PackageRef getLatestVersion(String packageName,
      {bool includePreRelease: false}) {
    List<PackageRef> refs = getAllPackageVersions(packageName);

    if (refs.isEmpty) return null;
    if (refs.length == 1) return refs.first;

    PackageRef latest = refs.first;

    if (includePreRelease) {
      for (int i = 1; i < refs.length; i++) {
        if (refs[i].version > latest.version) latest = refs[i];
      }
    } else {
      List<Version> versions = refs.map((ref) => ref.version).toList();
      Version latestVersion = Version.primary(versions);
      for (PackageRef ref in refs) {
        if (ref.version == latestVersion) latest = ref;
      }
    }

    return latest;
  }

  void _parse() {
    // Read the activated applications.
    _applications = [];

    Directory globalPackagesDir = _getSubDir(location, 'global_packages');
    if (globalPackagesDir.existsSync()) {
      _applications = globalPackagesDir
          .listSync()
          .where((item) => item is Directory)
          .map((dir) => new Application._(this, dir))
          .toList();
    }

    // Scan hosted packages
    _packageRefs = <PackageRef>[];

    Directory dartlangDir =
        new Directory(path.join(location.path, 'hosted', _hostedPackageDirectoryName));
    if (dartlangDir.existsSync()) {
      _packageRefs.addAll(dartlangDir
          .listSync()
          .where((dir) => dir is Directory)
          .map((dir) => new DirectoryPackageRef('hosted', dir)));
    }

    // Scan for git packages (ignore the git/cache directory).
    // ace-a1a140cc933e7d44d2955a6d6033308754bb9235
    Directory gitDir = new Directory(path.join(location.path, 'git'));
    if (gitDir.existsSync()) {
      Iterable<PackageRef> gitRefs = gitDir
          .listSync()
          .where(
              (dir) => dir is Directory && path.basename(dir.path) != 'cache')
          .map((dir) => new GitDirectoryPackageRef(dir));
      _packageRefs.addAll(gitRefs);
    }
  }

  Directory _getSubDir(Directory dir, String name) =>
      new Directory(path.join(dir.path, name));
}

/// A Dart application; a package with an entry-point, available via `pub global
/// activate`.
class Application {
  final PubCache _cache;
  final Directory _dir;

  List<PackageRef> _packageRefs;

  Application._(this._cache, this._dir);

  /// The name of the defining package.
  String get name => path.basename(_dir.path);

  /// The version of the application and of the defining package.
  Version get version {
    PackageRef ref = getDefiningPackageRef();
    return ref == null ? Version.none : ref.version;
  }

  /// Return the reference to the defining package. This is the package that
  /// defines the application.
  PackageRef getDefiningPackageRef() {
    for (PackageRef ref in getPackageRefs()) {
      if (ref.name == name) return ref;
    }
    return null;
  }

  /// Return all the package references for the application. This includes the
  /// defining package as well as the direct and transitive dependencies.
  List<PackageRef> getPackageRefs() {
    if (_packageRefs == null) _parsePubspecLock();
    return _packageRefs;
  }

  String toString() => '${name} ${version}';

  void _parsePubspecLock() {
    File pubspecLock = new File(path.join(_dir.path, 'pubspec.lock'));
    Map doc = yaml.loadYaml(pubspecLock.readAsStringSync());
    Map packages = doc['packages'];
    _packageRefs = packages.keys.map((key) {
      Map m = packages[key];
      String source = m['source'];
      if (source == 'git') {
        return new PackageRefImpl.git(key, m['version'], m['description'],
            (curRef) {
          for (PackageRef ref in _cache.getPackageRefs()) {
            if (ref == curRef) return ref.resolve();
          }
          return null;
        });
      } else if (source == 'hosted') {
        return new PackageRefImpl.hosted(key, m['version'], (curRef) {
          for (PackageRef ref in _cache.getPackageRefs()) {
            if (ref == curRef) return ref.resolve();
          }
          return null;
        });
      } else if (source == 'path') {
        return new PackageRefImpl.path(key, m['version'], m['description']);
      } else {
        return new PackageRefImpl(source, key, m['version']);
      }
    }).toList();
  }
}

/// A package reference, including the package name and version. This package
/// reference can be resolved to the actual package on disk.
abstract class PackageRef {
  /// The type of the package reference. Valid types include `hosted` and `git`.
  String get sourceType;

  /// The name of the package.
  String get name;

  /// The version of the package.
  Version get version;

  /// Resolve the package reference into the actual package, including the
  /// location on disk.
  Package resolve();

  bool operator ==(other) {
    return this.sourceType == other.sourceType &&
        this.name == other.name &&
        this.version == other.version;
  }

  String toString() => '${name} ${version}';
}

/// A representation of a package, including the name, version, and location on
/// disk.
class Package {
  final Directory location;
  final String name;
  final Version version;

  Package(this.location, this.name, this.version);

  String toString() => '${name} ${version}';
}
