// 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.

library package_config.discovery;

import "dart:async";
import "dart:io";
import "dart:typed_data" show Uint8List;

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

import "packages.dart";
import "packages_file.dart" as pkgfile show parse;
import "src/packages_impl.dart";
import "src/packages_io_impl.dart";

/// Reads a package resolution file and creates a [Packages] object from it.
///
/// The [packagesFile] must exist and be loadable.
/// Currently that means the URI must have a `file`, `http` or `https` scheme,
/// and that the file can be loaded and its contents parsed correctly.
///
/// If the [loader] is provided, it is used to fetch non-`file` URIs, and
/// it can support other schemes or set up more complex HTTP requests.
///
/// This function can be used to load an explicitly configured package
/// resolution file, for example one specified using a `--packages`
/// command-line parameter.
Future<Packages> loadPackagesFile(Uri packagesFile,
    {Future<List<int>> loader(Uri uri)}) async {
  Packages parseBytes(List<int> bytes) {
    Map<String, Uri> packageMap = pkgfile.parse(bytes, packagesFile);
    return new MapPackages(packageMap);
  }
  if (packagesFile.scheme == "file") {
    File file = new File.fromUri(packagesFile);
    return parseBytes(await file.readAsBytes());
  }
  if (loader == null) {
    return parseBytes(await _httpGet(packagesFile));
  }
  return parseBytes(await loader(packagesFile));
}

/// Create a [Packages] object for a package directory.
///
/// The [packagesDir] URI should refer to a directory.
/// Package names are resolved as relative to sub-directories of the
/// package directory.
///
/// This function can be used for explicitly configured package directories,
/// for example one specified using a `--package-root` comand-line parameter.
Packages getPackagesDirectory(Uri packagesDir) {
  if (packagesDir.scheme == "file") {
    Directory directory = new Directory.fromUri(packagesDir);
    return new FilePackagesDirectoryPackages(directory);
  }
  if (!packagesDir.path.endsWith('/')) {
    packagesDir = packagesDir.replace(path: packagesDir.path + '/');
  }
  return new NonFilePackagesDirectoryPackages(packagesDir);
}

/// Discover the package configuration for a Dart script.
///
/// The [baseUri] points to either the Dart script or its directory.
/// A package resolution strategy is found by going through the following steps,
/// and stopping when something is found.
///
/// * Check if a `.packages` file exists in the same directory.
/// * If `baseUri`'s scheme is not `file`, then assume a `packages` directory
///   in the same directory, and resolve packages relative to that.
/// * If `baseUri`'s scheme *is* `file`:
///   * Check if a `packages` directory exists.
///   * Otherwise check each successive parent directory of `baseUri` for a
///     `.packages` file.
///
/// If any of these tests succeed, a `Packages` class is returned.
/// Returns the constant [noPackages] if no resolution strategy is found.
///
/// This function currently only supports `file`, `http` and `https` URIs.
/// It needs to be able to load a `.packages` file from the URI, so only
/// recognized schemes are accepted.
///
/// To support other schemes, or more complex HTTP requests,
/// an optional [loader] function can be supplied.
/// It's called to load the `.packages` file for a non-`file` scheme.
/// The loader function returns the *contents* of the file
/// identified by the URI it's given.
/// The content should be a UTF-8 encoded `.packages` file, and must return an
/// error future if loading fails for any reason.
Future<Packages> findPackages(Uri baseUri,
    {Future<List<int>> loader(Uri unsupportedUri)}) {
  if (baseUri.scheme == "file") {
    return new Future<Packages>.sync(() => findPackagesFromFile(baseUri));
  } else if (loader != null) {
    return findPackagesFromNonFile(baseUri, loader: loader);
  } else if (baseUri.scheme == "http" || baseUri.scheme == "https") {
    return findPackagesFromNonFile(baseUri, loader: _httpGet);
  } else {
    return new Future<Packages>.value(Packages.noPackages);
  }
}

/// Find the location of the package resolution file/directory for a Dart file.
///
/// Checks for a `.packages` file in the [workingDirectory].
/// If not found, checks for a `packages` directory in the same directory.
/// If still not found, starts checking parent directories for
/// `.packages` until reaching the root directory.
///
/// Returns a [File] object of a `.packages` file if one is found, or a
/// [Directory] object for the `packages/` directory if that is found.
FileSystemEntity _findPackagesFile(String workingDirectory) {
  var dir = new Directory(workingDirectory);
  if (!dir.isAbsolute) dir = dir.absolute;
  if (!dir.existsSync()) {
    throw new ArgumentError.value(
        workingDirectory, "workingDirectory", "Directory does not exist.");
  }
  File checkForConfigFile(Directory directory) {
    assert(directory.isAbsolute);
    var file = new File(path.join(directory.path, ".packages"));
    if (file.existsSync()) return file;
    return null;
  }
  // Check for $cwd/.packages
  var packagesCfgFile = checkForConfigFile(dir);
  if (packagesCfgFile != null) return packagesCfgFile;
  // Check for $cwd/packages/
  var packagesDir = new Directory(path.join(dir.path, "packages"));
  if (packagesDir.existsSync()) return packagesDir;
  // Check for cwd(/..)+/.packages
  var parentDir = dir.parent;
  while (parentDir.path != dir.path) {
    packagesCfgFile = checkForConfigFile(parentDir);
    if (packagesCfgFile != null) break;
    dir = parentDir;
    parentDir = dir.parent;
  }
  return packagesCfgFile;
}

/// Finds a package resolution strategy for a local Dart script.
///
/// The [fileBaseUri] points to either a Dart script or the directory of the
/// script. The `fileBaseUri` must be a `file:` URI.
///
/// This function first tries to locate a `.packages` file in the `fileBaseUri`
/// directory. If that is not found, it instead checks for the presence of
/// a `packages/` directory in the same place.
/// If that also fails, it starts checking parent directories for a `.packages`
/// file, and stops if it finds it.
/// Otherwise it gives up and returns [Packages.noPackages].
Packages findPackagesFromFile(Uri fileBaseUri) {
  Uri baseDirectoryUri = fileBaseUri;
  if (!fileBaseUri.path.endsWith('/')) {
    baseDirectoryUri = baseDirectoryUri.resolve(".");
  }
  String baseDirectoryPath = baseDirectoryUri.toFilePath();
  FileSystemEntity location = _findPackagesFile(baseDirectoryPath);
  if (location == null) return Packages.noPackages;
  if (location is File) {
    List<int> fileBytes = location.readAsBytesSync();
    Map<String, Uri> map =
        pkgfile.parse(fileBytes, new Uri.file(location.path));
    return new MapPackages(map);
  }
  assert(location is Directory);
  return new FilePackagesDirectoryPackages(location);
}

/// Finds a package resolution strategy for a Dart script.
///
/// The [nonFileUri] points to either a Dart script or the directory of the
/// script.
/// The [nonFileUri] should not be a `file:` URI since the algorithm for
/// finding a package resolution strategy is more elaborate for `file:` URIs.
/// In that case, use [findPackagesFromFile].
///
/// This function first tries to locate a `.packages` file in the [nonFileUri]
/// directory. If that is not found, it instead assumes a `packages/` directory
/// in the same place.
///
/// By default, this function only works for `http:` and `https:` URIs.
/// To support other schemes, a loader must be provided, which is used to
/// try to load the `.packages` file. The loader should return the contents
/// of the requested `.packages` file as bytes, which will be assumed to be
/// UTF-8 encoded.
Future<Packages> findPackagesFromNonFile(Uri nonFileUri,
    {Future<List<int>> loader(Uri name)}) async {
  if (loader == null) loader = _httpGet;
  Uri packagesFileUri = nonFileUri.resolve(".packages");

  try {
    List<int> fileBytes = await loader(packagesFileUri);
    Map<String, Uri> map = pkgfile.parse(fileBytes, packagesFileUri);
    return new MapPackages(map);
  } catch (_) {
    // Didn't manage to load ".packages". Assume a "packages/" directory.
    Uri packagesDirectoryUri = nonFileUri.resolve("packages/");
    return new NonFilePackagesDirectoryPackages(packagesDirectoryUri);
  }
}

/// Fetches a file over http.
Future<List<int>> _httpGet(Uri uri) async {
  HttpClient client = new HttpClient();
  HttpClientRequest request = await client.getUrl(uri);
  HttpClientResponse response = await request.close();
  if (response.statusCode != HttpStatus.OK) {
    throw 'Failure getting $uri: '
        '${response.statusCode} ${response.reasonPhrase}';
  }
  List<List<int>> splitContent = await response.toList();
  int totalLength = 0;
  for (var list in splitContent) {
    totalLength += list.length;
  }
  Uint8List result = new Uint8List(totalLength);
  int offset = 0;
  for (List<int> contentPart in splitContent) {
    result.setRange(offset, offset + contentPart.length, contentPart);
    offset += contentPart.length;
  }
  return result;
}
