// 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:collection';
import 'dart:convert';
import 'dart:typed_data';

import 'package:build/build.dart';
import 'package:crypto/crypto.dart';
import 'package:glob/glob.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as p;
import 'package:pedantic/pedantic.dart';
import 'package:pool/pool.dart';
import 'package:watcher/watcher.dart';

import '../asset/cache.dart';
import '../asset/finalized_reader.dart';
import '../asset/reader.dart';
import '../asset/writer.dart';
import '../asset_graph/graph.dart';
import '../asset_graph/node.dart';
import '../asset_graph/optional_output_tracker.dart';
import '../changes/build_script_updates.dart';
import '../environment/build_environment.dart';
import '../logging/build_for_input_logger.dart';
import '../logging/failure_reporter.dart';
import '../logging/human_readable_duration.dart';
import '../logging/logging.dart';
import '../package_graph/apply_builders.dart';
import '../package_graph/package_graph.dart';
import '../performance_tracking/performance_tracking_resolvers.dart';
import '../util/async.dart';
import '../util/build_dirs.dart';
import '../util/constants.dart';
import 'build_definition.dart';
import 'build_directory.dart';
import 'build_result.dart';
import 'finalized_assets_view.dart';
import 'heartbeat.dart';
import 'options.dart';
import 'performance_tracker.dart';
import 'phase.dart';

final _logger = Logger('Build');

List<String> _buildPaths(Set<BuildDirectory> buildDirs) =>
    // The empty string means build everything.
    buildDirs.any((b) => b.directory == '')
        ? []
        : buildDirs.map((b) => b.directory).toList();

class BuildImpl {
  final FinalizedReader _finalizedReader;
  FinalizedReader get finalizedReader => _finalizedReader;

  final AssetGraph assetGraph;

  final BuildScriptUpdates _buildScriptUpdates;
  BuildScriptUpdates get buildScriptUpdates => _buildScriptUpdates;

  final List<BuildPhase> _buildPhases;
  final PackageGraph _packageGraph;
  final AssetReader _reader;
  final Resolvers _resolvers;
  final ResourceManager _resourceManager;
  final RunnerAssetWriter _writer;
  final bool _trackPerformance;
  final bool _verbose;
  final BuildEnvironment _environment;
  final String _logPerformanceDir;

  Future<void> beforeExit() => _resourceManager.beforeExit();

  BuildImpl._(BuildDefinition buildDefinition, BuildOptions options,
      this._buildPhases, this._finalizedReader)
      : _buildScriptUpdates = buildDefinition.buildScriptUpdates,
        _packageGraph = buildDefinition.packageGraph,
        _reader = options.enableLowResourcesMode
            ? buildDefinition.reader
            : CachingAssetReader(buildDefinition.reader),
        _resolvers = options.resolvers,
        _writer = buildDefinition.writer,
        assetGraph = buildDefinition.assetGraph,
        _resourceManager = buildDefinition.resourceManager,
        _verbose = options.verbose,
        _environment = buildDefinition.environment,
        _trackPerformance = options.trackPerformance,
        _logPerformanceDir = options.logPerformanceDir;

  Future<BuildResult> run(Map<AssetId, ChangeType> updates,
      {Set<BuildDirectory> buildDirs}) {
    buildDirs ??= Set<BuildDirectory>();
    finalizedReader.reset(_buildPaths(buildDirs));
    return _SingleBuild(this, buildDirs).run(updates)
      ..whenComplete(_resolvers.reset);
  }

  static Future<BuildImpl> create(
      BuildOptions options,
      BuildEnvironment environment,
      List<BuilderApplication> builders,
      Map<String, Map<String, dynamic>> builderConfigOverrides,
      {bool isReleaseBuild = false}) async {
    // Don't allow any changes to the generated asset directory after this
    // point.
    lockGeneratedOutputDirectory();

    var buildPhases = await createBuildPhases(
        options.targetGraph, builders, builderConfigOverrides, isReleaseBuild);
    if (buildPhases.isEmpty) {
      _logger.severe('Nothing can be built, yet a build was requested.');
    }
    var buildDefinition = await BuildDefinition.prepareWorkspace(
        environment, options, buildPhases);
    var singleStepReader = SingleStepReader(
        buildDefinition.reader,
        buildDefinition.assetGraph,
        buildPhases.length,
        options.packageGraph.root.name,
        _isReadableAfterBuildFactory(buildPhases));
    var finalizedReader = FinalizedReader(
        singleStepReader,
        buildDefinition.assetGraph,
        buildPhases,
        options.packageGraph.root.name);
    var build =
        BuildImpl._(buildDefinition, options, buildPhases, finalizedReader);
    return build;
  }

  static bool Function(AssetNode, int, String) _isReadableAfterBuildFactory(
          List<BuildPhase> buildPhases) =>
      (AssetNode node, int phaseNum, String package) {
        if (node is GeneratedAssetNode) {
          return node.wasOutput && !node.isFailure;
        }
        return node.isReadable && node.isValidInput;
      };
}

/// Performs a single build and manages state that only lives for a single
/// build.
class _SingleBuild {
  final AssetGraph _assetGraph;
  final List<BuildPhase> _buildPhases;
  final List<Pool> _buildPhasePool;
  final BuildEnvironment _environment;
  final _lazyPhases = <String, Future<Iterable<AssetId>>>{};
  final _lazyGlobs = <AssetId, Future<void>>{};
  final PackageGraph _packageGraph;
  final BuildPerformanceTracker _performanceTracker;
  final AssetReader _reader;
  final Resolvers _resolvers;
  final ResourceManager _resourceManager;
  final bool _verbose;
  final RunnerAssetWriter _writer;
  final Set<BuildDirectory> _buildDirs;
  final String _logPerformanceDir;
  final _failureReporter = FailureReporter();

  int actionsCompletedCount = 0;
  int actionsStartedCount = 0;

  final pendingActions = SplayTreeMap<int, Set<String>>();

  /// Can't be final since it needs access to [pendingActions].
  HungActionsHeartbeat hungActionsHeartbeat;

  _SingleBuild(BuildImpl buildImpl, Set<BuildDirectory> buildDirs)
      : _assetGraph = buildImpl.assetGraph,
        _buildPhases = buildImpl._buildPhases,
        _buildPhasePool = List(buildImpl._buildPhases.length),
        _environment = buildImpl._environment,
        _packageGraph = buildImpl._packageGraph,
        _performanceTracker = buildImpl._trackPerformance
            ? BuildPerformanceTracker()
            : BuildPerformanceTracker.noOp(),
        _reader = buildImpl._reader,
        _resolvers = buildImpl._resolvers,
        _resourceManager = buildImpl._resourceManager,
        _verbose = buildImpl._verbose,
        _writer = buildImpl._writer,
        _buildDirs = buildDirs,
        _logPerformanceDir = buildImpl._logPerformanceDir {
    hungActionsHeartbeat = HungActionsHeartbeat(() {
      final message = StringBuffer();
      const actionsToLogMax = 5;
      var descriptions = pendingActions.values.fold(
          <String>[],
          (combined, actions) =>
              combined..addAll(actions)).take(actionsToLogMax);
      for (final description in descriptions) {
        message.writeln('  - $description');
      }
      var additionalActionsCount =
          actionsStartedCount - actionsCompletedCount - actionsToLogMax;
      if (additionalActionsCount > 0) {
        message.writeln('  .. and $additionalActionsCount more');
      }
      return '$message';
    });
  }

  Future<BuildResult> run(Map<AssetId, ChangeType> updates) async {
    var watch = Stopwatch()..start();
    var result = await _safeBuild(updates);
    var optionalOutputTracker = OptionalOutputTracker(
        _assetGraph, _buildPaths(_buildDirs), _buildPhases);
    if (result.status == BuildStatus.success) {
      final failures = _assetGraph.failedOutputs
          .where((n) => optionalOutputTracker.isRequired(n.id));
      if (failures.isNotEmpty) {
        await _failureReporter.reportErrors(failures);
        result = BuildResult(BuildStatus.failure, result.outputs,
            performance: result.performance);
      }
    }
    await _resourceManager.disposeAll();
    result = await _environment.finalizeBuild(
        result,
        FinalizedAssetsView(_assetGraph, optionalOutputTracker),
        _reader,
        _buildDirs);
    if (result.status == BuildStatus.success) {
      _logger.info('Succeeded after ${humanReadable(watch.elapsed)} with '
          '${result.outputs.length} outputs '
          '($actionsCompletedCount actions)\n');
    } else {
      _logger.severe('Failed after ${humanReadable(watch.elapsed)}');
    }
    return result;
  }

  Future<void> _updateAssetGraph(Map<AssetId, ChangeType> updates) async {
    await logTimedAsync(_logger, 'Updating asset graph', () async {
      var invalidated = await _assetGraph.updateAndInvalidate(
          _buildPhases, updates, _packageGraph.root.name, _delete, _reader);
      if (_reader is CachingAssetReader) {
        (_reader as CachingAssetReader).invalidate(invalidated);
      }
    });
  }

  /// Runs a build inside a zone with an error handler and stack chain
  /// capturing.
  Future<BuildResult> _safeBuild(Map<AssetId, ChangeType> updates) {
    var done = Completer<BuildResult>();

    var heartbeat = HeartbeatLogger(
        transformLog: (original) => '$original, ${_buildProgress()}',
        waitDuration: Duration(seconds: 1))
      ..start();
    hungActionsHeartbeat.start();
    done.future.whenComplete(() {
      heartbeat.stop();
      hungActionsHeartbeat.stop();
    });

    runZoned(() async {
      if (updates.isNotEmpty) {
        await _updateAssetGraph(updates);
      }
      // Run a fresh build.
      var result = await logTimedAsync(_logger, 'Running build', _runPhases);

      // Write out the dependency graph file.
      await logTimedAsync(_logger, 'Caching finalized dependency graph',
          () async {
        await _writer.writeAsBytes(
            AssetId(_packageGraph.root.name, assetGraphPath),
            _assetGraph.serialize());
      });

      // Log performance information if requested
      if (_logPerformanceDir != null) {
        assert(result.performance != null);
        var logPath =
            p.join(_logPerformanceDir, DateTime.now().toIso8601String());
        await logTimedAsync(_logger, 'Writing performance log to $logPath', () {
          var performanceLogId = AssetId(_packageGraph.root.name, logPath);
          var serialized = jsonEncode(result.performance);
          return _writer.writeAsString(performanceLogId, serialized);
        });
      }

      if (!done.isCompleted) done.complete(result);
    }, onError: (e, StackTrace st) {
      if (!done.isCompleted) {
        _logger.severe('Unhandled build failure!', e, st);
        done.complete(BuildResult(BuildStatus.failure, []));
      }
    });
    return done.future;
  }

  /// Returns a message describing the progress of the current build.
  String _buildProgress() =>
      '$actionsCompletedCount/$actionsStartedCount actions completed.';

  /// Runs the actions in [_buildPhases] and returns a [Future<BuildResult>]
  /// which completes once all [BuildPhase]s are done.
  Future<BuildResult> _runPhases() {
    return _performanceTracker.track(() async {
      final outputs = <AssetId>[];
      for (var phaseNum = 0; phaseNum < _buildPhases.length; phaseNum++) {
        var phase = _buildPhases[phaseNum];
        if (phase.isOptional) continue;
        outputs
            .addAll(await _performanceTracker.trackBuildPhase(phase, () async {
          if (phase is InBuildPhase) {
            var primaryInputs =
                await _matchingPrimaryInputs(phase.package, phaseNum);
            return _runBuilder(phaseNum, phase, primaryInputs);
          } else if (phase is PostBuildPhase) {
            return _runPostProcessPhase(phaseNum, phase);
          } else {
            throw StateError('Unrecognized BuildPhase type $phase');
          }
        }));
      }
      await Future.forEach(
          _lazyPhases.values,
          (Future<Iterable<AssetId>> lazyOuts) async =>
              outputs.addAll(await lazyOuts));
      // Assume success, `_assetGraph.failedOutputs` will be checked later.
      return BuildResult(BuildStatus.success, outputs,
          performance: _performanceTracker);
    });
  }

  /// Gets a list of all inputs matching the [phaseNumber], as well as
  /// its [Builder]s primary inputs.
  ///
  /// Lazily builds any optional build actions that might potentially produce
  /// a primary input to this phase.
  Future<Set<AssetId>> _matchingPrimaryInputs(
      String package, int phaseNumber) async {
    var ids = Set<AssetId>();
    var phase = _buildPhases[phaseNumber];
    await Future.wait(
        _assetGraph.outputsForPhase(package, phaseNumber).map((node) async {
      if (!shouldBuildForDirs(node.id, _buildPaths(_buildDirs), phase)) {
        return;
      }

      var input = _assetGraph.get(node.primaryInput);
      if (input is GeneratedAssetNode) {
        if (input.state != NodeState.upToDate) {
          await _runLazyPhaseForInput(input.phaseNumber, input.primaryInput);
        }
        if (!input.wasOutput) return;
        if (input.isFailure) return;
      }
      ids.add(input.id);
    }));
    return ids;
  }

  /// Runs a normal builder with [primaryInputs] as inputs and returns only the
  /// outputs that were newly created.
  ///
  /// Does not return outputs that didn't need to be re-ran or were declared
  /// but not output.
  Future<Iterable<AssetId>> _runBuilder(int phaseNumber, InBuildPhase action,
      Iterable<AssetId> primaryInputs) async {
    var outputLists = await Future.wait(
        primaryInputs.map((input) => _runForInput(phaseNumber, action, input)));
    return outputLists.fold<List<AssetId>>(
        <AssetId>[], (combined, next) => combined..addAll(next));
  }

  /// Lazily runs [phaseNumber] with [input]..
  Future<Iterable<AssetId>> _runLazyPhaseForInput(
      int phaseNumber, AssetId input) {
    return _lazyPhases.putIfAbsent('$phaseNumber|$input', () async {
      // First check if `input` is generated, and whether or not it was
      // actually output. If it wasn't then we just return an empty list here.
      var inputNode = _assetGraph.get(input);
      if (inputNode is GeneratedAssetNode) {
        // Make sure the `inputNode` is up to date, and rebuild it if not.
        if (inputNode.state != NodeState.upToDate) {
          await _runLazyPhaseForInput(
              inputNode.phaseNumber, inputNode.primaryInput);
        }
        if (!inputNode.wasOutput || inputNode.isFailure) return <AssetId>[];
      }

      // We can never lazily build `PostProcessBuildAction`s.
      var action = _buildPhases[phaseNumber] as InBuildPhase;

      return _runForInput(phaseNumber, action, input);
    });
  }

  /// Checks whether [node] can be read by this step - attempting to build the
  /// asset if necessary.
  FutureOr<bool> _isReadableNode(
      AssetNode node, int phaseNum, String fromPackage) {
    if (node is GeneratedAssetNode) {
      if (node.phaseNumber >= phaseNum) return false;
      return doAfter(
          _ensureAssetIsBuilt(node), (_) => node.wasOutput && !node.isFailure);
    }
    return node.isReadable && node.isValidInput;
  }

  FutureOr<void> _ensureAssetIsBuilt(AssetNode node) {
    if (node is GeneratedAssetNode && node.state != NodeState.upToDate) {
      return _runLazyPhaseForInput(node.phaseNumber, node.primaryInput);
    }
    return null;
  }

  Future<Iterable<AssetId>> _runForInput(
      int phaseNumber, InBuildPhase phase, AssetId input) {
    var pool = _buildPhasePool[phaseNumber] ??= Pool(buildPhasePoolSize);
    return pool.withResource(() {
      final builder = phase.builder;
      var tracker =
          _performanceTracker.addBuilderAction(input, phase.builderLabel);
      return tracker.track(() async {
        var builderOutputs = expectedOutputs(builder, input);

        // Add `builderOutputs` to the primary outputs of the input.
        var inputNode = _assetGraph.get(input);
        assert(inputNode != null,
            'Inputs should be known in the static graph. Missing $input');
        assert(
            inputNode.primaryOutputs.containsAll(builderOutputs),
            'input $input with builder $builder missing primary outputs: \n'
                    'Got ${inputNode.primaryOutputs.join(', ')} '
                    'which was missing:\n' +
                builderOutputs
                    .where((id) => !inputNode.primaryOutputs.contains(id))
                    .join(', '));

        var wrappedReader = SingleStepReader(_reader, _assetGraph, phaseNumber,
            input.package, _isReadableNode, _getUpdatedGlobNode);

        if (!await tracker.trackStage(
            'Setup', () => _buildShouldRun(builderOutputs, wrappedReader))) {
          return <AssetId>[];
        }

        await _cleanUpStaleOutputs(builderOutputs);
        await FailureReporter.clean(phaseNumber, input);

        // We may have read some inputs in the call to `_buildShouldRun`, we want
        // to remove those.
        wrappedReader.assetsRead.clear();

        var wrappedWriter = AssetWriterSpy(_writer);
        var actionDescription =
            _actionLoggerName(phase, input, _packageGraph.root.name);
        var logger = BuildForInputLogger(Logger(actionDescription));

        actionsStartedCount++;
        pendingActions
            .putIfAbsent(phaseNumber, () => Set<String>())
            .add(actionDescription);

        await tracker.trackStage(
            'Build',
            () => runBuilder(builder, [input], wrappedReader, wrappedWriter,
                        PerformanceTrackingResolvers(_resolvers, tracker),
                        logger: logger,
                        resourceManager: _resourceManager,
                        stageTracker: tracker)
                    .catchError((_) {
                  // Errors tracked through the logger
                }));
        actionsCompletedCount++;
        hungActionsHeartbeat.ping();
        pendingActions[phaseNumber].remove(actionDescription);

        // Reset the state for all the `builderOutputs` nodes based on what was
        // read and written.
        await tracker.trackStage(
            'Finalize',
            () => _setOutputsState(builderOutputs, wrappedReader, wrappedWriter,
                actionDescription, logger.errorsSeen));

        return wrappedWriter.assetsWritten;
      });
    });
  }

  Future<Iterable<AssetId>> _runPostProcessPhase(
      int phaseNum, PostBuildPhase phase) async {
    var actionNum = 0;
    var outputLists = await Future.wait(phase.builderActions
        .map((action) => _runPostProcessAction(phaseNum, actionNum++, action)));
    return outputLists.fold<List<AssetId>>(
        <AssetId>[], (combined, next) => combined..addAll(next));
  }

  Future<Iterable<AssetId>> _runPostProcessAction(
      int phaseNum, int actionNum, PostBuildAction action) async {
    var anchorNodes = _assetGraph.packageNodes(action.package).where((node) {
      if (node is PostProcessAnchorNode && node.actionNumber == actionNum) {
        var inputNode = _assetGraph.get(node.primaryInput);
        if (inputNode is SourceAssetNode) {
          return true;
        } else if (inputNode is GeneratedAssetNode) {
          return inputNode.wasOutput &&
              !inputNode.isFailure &&
              inputNode.state == NodeState.upToDate;
        }
      }
      return false;
    }).cast<PostProcessAnchorNode>();
    var outputLists = await Future.wait(anchorNodes.map((anchorNode) =>
        _runPostProcessBuilderForAnchor(
            phaseNum, actionNum, action.builder, anchorNode)));
    return outputLists.fold<List<AssetId>>(
        <AssetId>[], (combined, next) => combined..addAll(next));
  }

  Future<Iterable<AssetId>> _runPostProcessBuilderForAnchor(
      int phaseNum,
      int actionNum,
      PostProcessBuilder builder,
      PostProcessAnchorNode anchorNode) async {
    var input = anchorNode.primaryInput;
    var inputNode = _assetGraph.get(input);
    assert(inputNode != null,
        'Inputs should be known in the static graph. Missing $input');

    var wrappedReader = SingleStepReader(
        _reader, _assetGraph, phaseNum, input.package, _isReadableNode);

    if (!await _postProcessBuildShouldRun(anchorNode, wrappedReader)) {
      return <AssetId>[];
    }
    // We may have read some inputs in the call to `_buildShouldRun`, we want
    // to remove those.
    wrappedReader.assetsRead.clear();

    // Clean out the impacts of the previous run
    await FailureReporter.clean(phaseNum, input);
    await _cleanUpStaleOutputs(anchorNode.outputs);
    anchorNode.outputs
      ..toList().forEach(_assetGraph.remove)
      ..clear();
    inputNode.deletedBy.remove(anchorNode.id);

    var wrappedWriter = AssetWriterSpy(_writer);
    var actionDescription = '$builder on $input';
    var logger = BuildForInputLogger(Logger(actionDescription));

    actionsStartedCount++;
    pendingActions
        .putIfAbsent(phaseNum, () => Set<String>())
        .add(actionDescription);

    await runPostProcessBuilder(
        builder, input, wrappedReader, wrappedWriter, logger,
        addAsset: (assetId) {
      if (_assetGraph.contains(assetId)) {
        throw InvalidOutputException(assetId, 'Asset already exists');
      }
      var node = GeneratedAssetNode(assetId,
          primaryInput: input,
          builderOptionsId: anchorNode.builderOptionsId,
          isHidden: true,
          phaseNumber: phaseNum,
          wasOutput: true,
          isFailure: false,
          state: NodeState.upToDate);
      _assetGraph.add(node);
      anchorNode.outputs.add(assetId);
    }, deleteAsset: (assetId) {
      if (!_assetGraph.contains(assetId)) {
        throw AssetNotFoundException(assetId);
      }
      if (assetId != input) {
        throw InvalidOutputException(assetId, 'Can only delete primary input');
      }
      _assetGraph.get(assetId).deletedBy.add(anchorNode.id);
    }).catchError((_) {
      // Errors tracked through the logger
    });
    actionsCompletedCount++;
    hungActionsHeartbeat.ping();
    pendingActions[phaseNum].remove(actionDescription);

    var assetsWritten = wrappedWriter.assetsWritten.toSet();

    // Reset the state for all the output nodes based on what was read and
    // written.
    inputNode.primaryOutputs.addAll(assetsWritten);
    await _setOutputsState(assetsWritten, wrappedReader, wrappedWriter,
        actionDescription, logger.errorsSeen);

    return assetsWritten;
  }

  /// Checks and returns whether any [outputs] need to be updated.
  Future<bool> _buildShouldRun(
      Iterable<AssetId> outputs, AssetReader reader) async {
    assert(
        outputs.every(_assetGraph.contains),
        'Outputs should be known statically. Missing '
        '${outputs.where((o) => !_assetGraph.contains(o)).toList()}');
    assert(outputs.isNotEmpty, 'Can\'t run a build with no outputs');

    // We only check the first output, because all outputs share the same inputs
    // and invalidation state.
    var firstOutput = outputs.first;
    var node = _assetGraph.get(firstOutput) as GeneratedAssetNode;
    assert(
        outputs.skip(1).every((output) =>
            (_assetGraph.get(output) as GeneratedAssetNode)
                .inputs
                .difference(node.inputs)
                .isEmpty),
        'All outputs of a build action should share the same inputs.');

    // No need to build an up to date output
    if (node.state == NodeState.upToDate) return false;
    // Early bail out condition, this is a forced update.
    if (node.state == NodeState.definitelyNeedsUpdate) return true;
    // This is a fresh build or the first time we've seen this output.
    if (node.previousInputsDigest == null) return true;

    var digest = await _computeCombinedDigest(
        node.inputs, node.builderOptionsId, reader);
    if (digest != node.previousInputsDigest) {
      return true;
    } else {
      // Make sure to update the `state` field for all outputs.
      for (var id in outputs) {
        (_assetGraph.get(id) as NodeWithInputs).state = NodeState.upToDate;
      }
      return false;
    }
  }

  /// Checks if a post process build should run based on [anchorNode].
  Future<bool> _postProcessBuildShouldRun(
      PostProcessAnchorNode anchorNode, AssetReader reader) async {
    var inputsDigest = await _computeCombinedDigest(
        [anchorNode.primaryInput], anchorNode.builderOptionsId, reader);

    if (inputsDigest != anchorNode.previousInputsDigest) {
      anchorNode.previousInputsDigest = inputsDigest;
      return true;
    }

    return false;
  }

  /// Deletes any of [outputs] which previously were output.
  ///
  /// This should be called after deciding that an asset really needs to be
  /// regenerated based on its inputs hash changing. All assets in [outputs]
  /// must correspond to a [GeneratedAssetNode].
  Future<void> _cleanUpStaleOutputs(Iterable<AssetId> outputs) =>
      Future.wait(outputs
          .map(_assetGraph.get)
          .cast<GeneratedAssetNode>()
          .where((n) => n.wasOutput)
          .map((n) => _delete(n.id)));

  Future<GlobAssetNode> _getUpdatedGlobNode(
      Glob glob, String package, int phaseNum) {
    var globNodeId = GlobAssetNode.createId(package, glob, phaseNum);
    var globNode = _assetGraph.get(globNodeId) as GlobAssetNode;
    if (globNode == null) {
      globNode = GlobAssetNode(
          globNodeId, glob, phaseNum, NodeState.definitelyNeedsUpdate);
      _assetGraph.add(globNode);
    }

    return toFuture(
        doAfter(_updateGlobNodeIfNecessary(globNode), (_) => globNode));
  }

  FutureOr<void> _updateGlobNodeIfNecessary(GlobAssetNode globNode) {
    if (globNode.state == NodeState.upToDate) return null;

    return _lazyGlobs.putIfAbsent(globNode.id, () async {
      var potentialNodes = _assetGraph
          .packageNodes(globNode.id.package)
          .where((n) => n.isReadable && n.isValidInput)
          .where((n) =>
              n is! GeneratedAssetNode ||
              (n as GeneratedAssetNode).phaseNumber < globNode.phaseNumber)
          .where((n) => globNode.glob.matches(n.id.path))
          .toList();

      await Future.wait(potentialNodes
          .whereType<GeneratedAssetNode>()
          .map(_ensureAssetIsBuilt)
          .map(toFuture));

      var actualMatches = <AssetId>[];
      for (var node in potentialNodes) {
        node.outputs.add(globNode.id);
        if (node is GeneratedAssetNode && (!node.wasOutput || node.isFailure)) {
          continue;
        }
        actualMatches.add(node.id);
      }

      globNode
        ..results = actualMatches
        ..inputs = HashSet.of(potentialNodes.map((n) => n.id))
        ..state = NodeState.upToDate
        ..lastKnownDigest =
            md5.convert(utf8.encode(globNode.results.join(' ')));

      unawaited(_lazyGlobs.remove(globNode.id));
    });
  }

  /// Computes a single [Digest] based on the combined [Digest]s of [ids] and
  /// [builderOptionsId].
  Future<Digest> _computeCombinedDigest(Iterable<AssetId> ids,
      AssetId builderOptionsId, AssetReader reader) async {
    var combinedBytes = Uint8List.fromList(List.filled(16, 0));
    void _combine(Uint8List other) {
      assert(other.length == 16);
      assert(other is Uint8List);
      for (var i = 0; i < 16; i++) {
        combinedBytes[i] ^= other[i];
      }
    }

    var builderOptionsNode = _assetGraph.get(builderOptionsId);
    _combine(builderOptionsNode.lastKnownDigest.bytes as Uint8List);

    // Limit the total number of digests we are computing at a time. Otherwise
    // this can overload the event queue.
    await Future.wait(ids.map((id) async {
      var node = _assetGraph.get(id);
      if (node is GlobAssetNode) {
        await _updateGlobNodeIfNecessary(node);
      } else if (!await reader.canRead(id)) {
        // We want to add something here, a missing/unreadable input should be
        // different from no input at all.
        //
        // This needs to be unique per input so we use the md5 hash of the id.
        _combine(md5.convert(id.toString().codeUnits).bytes as Uint8List);
        return;
      } else {
        node.lastKnownDigest ??= await reader.digest(id);
      }
      _combine(node.lastKnownDigest.bytes as Uint8List);
    }));

    return Digest(combinedBytes);
  }

  /// Sets the state for all [outputs] of a build step, by:
  ///
  /// - Setting `needsUpdate` to `false` for each output
  /// - Setting `wasOutput` based on `writer.assetsWritten`.
  /// - Setting `isFailed` based on action success.
  /// - Adding `outputs` as outputs to all `reader.assetsRead`.
  /// - Setting the `lastKnownDigest` on each output based on the new contents.
  /// - Setting the `previousInputsDigest` on each output based on the inputs.
  /// - Storing the error message with the [_failureReporter].
  Future<void> _setOutputsState(
      Iterable<AssetId> outputs,
      SingleStepReader reader,
      AssetWriterSpy writer,
      String actionDescription,
      Iterable<ErrorReport> errors) async {
    if (outputs.isEmpty) return;

    final inputsDigest = await _computeCombinedDigest(
        reader.assetsRead,
        (_assetGraph.get(outputs.first) as GeneratedAssetNode).builderOptionsId,
        reader);

    final isFailure = errors.isNotEmpty;

    for (var output in outputs) {
      var wasOutput = writer.assetsWritten.contains(output);
      var digest = wasOutput ? await _reader.digest(output) : null;
      var node = _assetGraph.get(output) as GeneratedAssetNode;

      // **IMPORTANT**: All updates to `node` must be synchronous. With lazy
      // builders we can run arbitrary code between updates otherwise, at which
      // time a node might not be in a valid state.
      _removeOldInputs(node, reader.assetsRead);
      _addNewInputs(node, reader.assetsRead);
      node
        ..state = NodeState.upToDate
        ..wasOutput = wasOutput
        ..isFailure = isFailure
        ..lastKnownDigest = digest
        ..previousInputsDigest = inputsDigest;

      if (isFailure) {
        await _failureReporter.markReported(actionDescription, node, errors);
        var needsMarkAsFailure = Queue.of(node.primaryOutputs);
        var allSkippedFailures = <GeneratedAssetNode>[];
        while (needsMarkAsFailure.isNotEmpty) {
          var output = needsMarkAsFailure.removeLast();
          var outputNode = _assetGraph.get(output) as GeneratedAssetNode
            ..state = NodeState.upToDate
            ..wasOutput = false
            ..isFailure = true
            ..lastKnownDigest = null
            ..previousInputsDigest = null;
          allSkippedFailures.add(outputNode);
          needsMarkAsFailure.addAll(outputNode.primaryOutputs);

          // Make sure output invalidation follows primary outputs for builds
          // that won't run.
          node.outputs.add(output);
          outputNode.inputs.add(node.id);
        }
        await _failureReporter.markSkipped(allSkippedFailures);
      }
    }
  }

  /// Removes old inputs from [node] based on [updatedInputs], and cleans up all
  /// the old edges.
  void _removeOldInputs(GeneratedAssetNode node, Set<AssetId> updatedInputs) {
    var removedInputs = node.inputs.difference(updatedInputs);
    node.inputs.removeAll(removedInputs);
    for (var input in removedInputs) {
      var inputNode = _assetGraph.get(input);
      assert(inputNode != null, 'Asset Graph is missing $input');
      inputNode.outputs.remove(node.id);
    }
  }

  /// Adds new inputs to [node] based on [updatedInputs], and adds the
  /// appropriate edges.
  void _addNewInputs(GeneratedAssetNode node, Set<AssetId> updatedInputs) {
    var newInputs = updatedInputs.difference(node.inputs);
    node.inputs.addAll(newInputs);
    for (var input in newInputs) {
      var inputNode = _assetGraph.get(input);
      assert(inputNode != null, 'Asset Graph is missing $input');
      inputNode.outputs.add(node.id);
    }
  }

  Future _delete(AssetId id) => _writer.delete(id);
}

String _actionLoggerName(
    InBuildPhase phase, AssetId primaryInput, String rootPackageName) {
  var asset = primaryInput.package == rootPackageName
      ? primaryInput.path
      : primaryInput.uri;
  return '${phase.builderLabel} on $asset';
}
