// Copyright (c) 2016, 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 'dart:convert';
import 'dart:io';

import 'package:build/build.dart';
import 'package:glob/glob.dart';
import 'package:path/path.dart' as path;
import 'package:pool/pool.dart';

import '../package_graph/package_graph.dart';
import 'reader.dart';
import 'writer.dart';

/// Pool for async file operations, we don't want to use too many file handles.
final _descriptorPool = Pool(32);

/// Basic [AssetReader] which uses a [PackageGraph] to look up where to read
/// files from disk.
class FileBasedAssetReader extends AssetReader
    implements RunnerAssetReader, PathProvidingAssetReader {
  final PackageGraph packageGraph;

  FileBasedAssetReader(this.packageGraph);

  @override
  Future<bool> canRead(AssetId id) =>
      _descriptorPool.withResource(() => _fileFor(id, packageGraph).exists());

  @override
  Future<List<int>> readAsBytes(AssetId id) => _fileForOrThrow(id, packageGraph)
      .then((file) => _descriptorPool.withResource(file.readAsBytes));

  @override
  Future<String> readAsString(AssetId id, {Encoding encoding}) =>
      _fileForOrThrow(id, packageGraph).then((file) => _descriptorPool
          .withResource(() => file.readAsString(encoding: encoding ?? utf8)));

  @override
  Stream<AssetId> findAssets(Glob glob, {String package}) {
    var packageNode =
        package == null ? packageGraph.root : packageGraph[package];
    if (packageNode == null) {
      throw ArgumentError(
          "Could not find package '$package' which was listed as "
          'an input. Please ensure you have that package in your deps, or '
          'remove it from your input sets.');
    }
    return glob
        .list(followLinks: true, root: packageNode.path)
        .where((e) => e is File && !path.basename(e.path).startsWith('._'))
        .cast<File>()
        .map((file) => _fileToAssetId(file, packageNode));
  }

  @override
  String pathTo(AssetId id) => _filePathFor(id, packageGraph);
}

/// Creates an [AssetId] for [file], which is a part of [packageNode].
AssetId _fileToAssetId(File file, PackageNode packageNode) {
  var filePath = path.normalize(file.absolute.path);
  var relativePath = path.relative(filePath, from: packageNode.path);
  return AssetId(packageNode.name, relativePath);
}

/// Basic [AssetWriter] which uses a [PackageGraph] to look up where to write
/// files to disk.
class FileBasedAssetWriter implements RunnerAssetWriter {
  final PackageGraph packageGraph;

  FileBasedAssetWriter(this.packageGraph);

  @override
  Future writeAsBytes(AssetId id, List<int> bytes) async {
    var file = _fileFor(id, packageGraph);
    await _descriptorPool.withResource(() async {
      await file.create(recursive: true);
      await file.writeAsBytes(bytes);
    });
  }

  @override
  Future writeAsString(AssetId id, String contents,
      {Encoding encoding = utf8}) async {
    var file = _fileFor(id, packageGraph);
    await _descriptorPool.withResource(() async {
      await file.create(recursive: true);
      await file.writeAsString(contents, encoding: encoding);
    });
  }

  @override
  Future delete(AssetId id) {
    if (id.package != packageGraph.root.name) {
      throw InvalidOutputException(
          id, 'Should not delete assets outside of ${packageGraph.root.name}');
    }

    var file = _fileFor(id, packageGraph);
    return _descriptorPool.withResource(() async {
      if (await file.exists()) {
        await file.delete();
      }
    });
  }
}

/// Returns the path to [id] for a given [packageGraph].
String _filePathFor(AssetId id, PackageGraph packageGraph) {
  var package = packageGraph[id.package];
  if (package == null) {
    throw PackageNotFoundException(id.package);
  }
  return path.join(package.path, id.path);
}

/// Returns a [File] for [id] given [packageGraph].
File _fileFor(AssetId id, PackageGraph packageGraph) {
  return File(_filePathFor(id, packageGraph));
}

/// Returns a [Future<File>] for [id] given [packageGraph].
///
/// Throws an `AssetNotFoundException` if it doesn't exist.
Future<File> _fileForOrThrow(AssetId id, PackageGraph packageGraph) {
  if (packageGraph[id.package] == null) {
    return Future.error(PackageNotFoundException(id.package));
  }
  var file = _fileFor(id, packageGraph);
  return _descriptorPool.withResource(file.exists).then((exists) {
    if (!exists) throw AssetNotFoundException(id);
    return file;
  });
}
