// 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 'package:build/build.dart';
import 'package:build_config/build_config.dart';
import 'package:build_runner/src/package_graph/build_config_overrides.dart';
import 'package:build_runner/src/watcher/asset_change.dart';
import 'package:build_runner/src/watcher/change_filter.dart';
import 'package:build_runner/src/watcher/collect_changes.dart';
import 'package:build_runner/src/watcher/delete_writer.dart';
import 'package:build_runner/src/watcher/graph_watcher.dart';
import 'package:build_runner/src/watcher/node_watcher.dart';
import 'package:build_runner_core/build_runner_core.dart';
import 'package:build_runner_core/src/asset_graph/graph.dart';
import 'package:build_runner_core/src/generate/build_impl.dart';
import 'package:crypto/crypto.dart';
import 'package:logging/logging.dart';
import 'package:pedantic/pedantic.dart';
import 'package:stream_transform/stream_transform.dart';
import 'package:watcher/watcher.dart';

import '../logging/std_io_logging.dart';
import '../server/server.dart';
import 'terminator.dart';

final _logger = Logger('Watch');

Future<ServeHandler> watch(
  List<BuilderApplication> builders, {
  bool deleteFilesByDefault,
  bool assumeTty,
  String configKey,
  PackageGraph packageGraph,
  RunnerAssetReader reader,
  RunnerAssetWriter writer,
  Resolvers resolvers,
  Level logLevel,
  onLog(LogRecord record),
  Duration debounceDelay,
  DirectoryWatcher Function(String) directoryWatcherFactory,
  Stream terminateEventStream,
  bool skipBuildScriptCheck,
  bool enableLowResourcesMode,
  Map<String, BuildConfig> overrideBuildConfig,
  Set<BuildDirectory> buildDirs,
  bool outputSymlinksOnly,
  bool trackPerformance,
  bool verbose,
  Map<String, Map<String, dynamic>> builderConfigOverrides,
  bool isReleaseBuild,
  String logPerformanceDir,
}) async {
  builderConfigOverrides ??= const {};
  packageGraph ??= PackageGraph.forThisPackage();
  buildDirs ??= Set<BuildDirectory>();

  var environment = OverrideableEnvironment(
      IOEnvironment(packageGraph,
          assumeTty: assumeTty, outputSymlinksOnly: outputSymlinksOnly),
      reader: reader,
      writer: writer,
      onLog: onLog ?? stdIOLogListener(assumeTty: assumeTty, verbose: verbose));
  var logSubscription =
      LogSubscription(environment, verbose: verbose, logLevel: logLevel);
  overrideBuildConfig ??=
      await findBuildConfigOverrides(packageGraph, configKey);
  var options = await BuildOptions.create(
    logSubscription,
    deleteFilesByDefault: deleteFilesByDefault,
    packageGraph: packageGraph,
    overrideBuildConfig: overrideBuildConfig,
    debounceDelay: debounceDelay,
    skipBuildScriptCheck: skipBuildScriptCheck,
    enableLowResourcesMode: enableLowResourcesMode,
    trackPerformance: trackPerformance,
    logPerformanceDir: logPerformanceDir,
    resolvers: resolvers,
  );
  var terminator = Terminator(terminateEventStream);

  var watch = _runWatch(
      options,
      environment,
      builders,
      builderConfigOverrides,
      terminator.shouldTerminate,
      directoryWatcherFactory,
      configKey,
      buildDirs
          .any((target) => target?.outputLocation?.path?.isNotEmpty ?? false),
      buildDirs,
      isReleaseMode: isReleaseBuild ?? false);

  unawaited(watch.buildResults.drain().then((_) async {
    await terminator.cancel();
    await options.logListener.cancel();
  }));

  return createServeHandler(watch);
}

/// Repeatedly run builds as files change on disk until [until] fires.
///
/// Sets up file watchers and collects changes then triggers new builds. When
/// [until] fires the file watchers will be stopped and up to one additional
/// build may run if there were pending changes.
///
/// The [BuildState.buildResults] stream will end after the final build has been
/// run.
WatchImpl _runWatch(
        BuildOptions options,
        BuildEnvironment environment,
        List<BuilderApplication> builders,
        Map<String, Map<String, dynamic>> builderConfigOverrides,
        Future until,
        DirectoryWatcher Function(String) directoryWatcherFactory,
        String configKey,
        bool willCreateOutputDirs,
        Set<BuildDirectory> buildDirs,
        {bool isReleaseMode = false}) =>
    WatchImpl(options, environment, builders, builderConfigOverrides, until,
        directoryWatcherFactory, configKey, willCreateOutputDirs, buildDirs,
        isReleaseMode: isReleaseMode);

class WatchImpl implements BuildState {
  BuildImpl _build;

  AssetGraph get assetGraph => _build?.assetGraph;

  final _readyCompleter = Completer<void>();
  Future<void> get ready => _readyCompleter.future;

  final String _configKey; // may be null

  /// Delay to wait for more file watcher events.
  final Duration _debounceDelay;

  /// Injectable factory for creating directory watchers.
  final DirectoryWatcher Function(String) _directoryWatcherFactory;

  /// Whether or not we will be creating any output directories.
  ///
  /// If not, then we don't care about source edits that don't have outputs.
  final bool _willCreateOutputDirs;

  /// Should complete when we need to kill the build.
  final _terminateCompleter = Completer<Null>();

  /// The [PackageGraph] for the current program.
  final PackageGraph packageGraph;

  /// The directories to build upon file changes and where to output them.
  final Set<BuildDirectory> _buildDirs;

  @override
  Future<BuildResult> currentBuild;

  /// Pending expected delete events from the build.
  final Set<AssetId> _expectedDeletes = Set<AssetId>();

  FinalizedReader _reader;
  FinalizedReader get reader => _reader;

  WatchImpl(
      BuildOptions options,
      BuildEnvironment environment,
      List<BuilderApplication> builders,
      Map<String, Map<String, dynamic>> builderConfigOverrides,
      Future until,
      this._directoryWatcherFactory,
      this._configKey,
      this._willCreateOutputDirs,
      this._buildDirs,
      {bool isReleaseMode = false})
      : _debounceDelay = options.debounceDelay,
        packageGraph = options.packageGraph {
    buildResults = _run(
            options, environment, builders, builderConfigOverrides, until,
            isReleaseMode: isReleaseMode)
        .asBroadcastStream();
  }

  @override
  Stream<BuildResult> buildResults;

  /// Runs a build any time relevant files change.
  ///
  /// Only one build will run at a time, and changes are batched.
  ///
  /// File watchers are scheduled synchronously.
  Stream<BuildResult> _run(
      BuildOptions options,
      BuildEnvironment environment,
      List<BuilderApplication> builders,
      Map<String, Map<String, dynamic>> builderConfigOverrides,
      Future until,
      {bool isReleaseMode = false}) {
    var watcherEnvironment = OverrideableEnvironment(environment,
        writer: OnDeleteWriter(environment.writer, _expectedDeletes.add));
    var firstBuildCompleter = Completer<BuildResult>();
    currentBuild = firstBuildCompleter.future;
    var controller = StreamController<BuildResult>();

    Future<BuildResult> doBuild(List<List<AssetChange>> changes) async {
      assert(_build != null);
      _logger..info('${'-' * 72}\n')..info('Starting Build\n');
      var mergedChanges = collectChanges(changes);

      _expectedDeletes.clear();
      if (!options.skipBuildScriptCheck) {
        if (_build.buildScriptUpdates
            .hasBeenUpdated(mergedChanges.keys.toSet())) {
          _terminateCompleter.complete();
          _logger.severe('Terminating builds due to build script update');
          return BuildResult(BuildStatus.failure, [],
              failureType: FailureType.buildScriptChanged);
        }
      }
      return _build.run(mergedChanges, buildDirs: _buildDirs);
    }

    var terminate = Future.any([until, _terminateCompleter.future]).then((_) {
      _logger.info('Terminating. No further builds will be scheduled\n');
    });

    Digest originalRootPackagesDigest;
    final rootPackagesId = AssetId(packageGraph.root.name, '.packages');

    // Start watching files immediately, before the first build is even started.
    var graphWatcher = PackageGraphWatcher(packageGraph,
        logger: _logger,
        watch: (node) =>
            PackageNodeWatcher(node, watch: _directoryWatcherFactory));
    graphWatcher
        .watch()
        .asyncMap<AssetChange>((change) {
          // Delay any events until the first build is completed.
          if (firstBuildCompleter.isCompleted) return change;
          return firstBuildCompleter.future.then((_) => change);
        })
        .asyncMap<AssetChange>((change) {
          var id = change.id;
          assert(originalRootPackagesDigest != null);
          if (id == rootPackagesId) {
            // Kill future builds if the root packages file changes.
            return watcherEnvironment.reader
                .readAsBytes(rootPackagesId)
                .then((bytes) {
              if (md5.convert(bytes) != originalRootPackagesDigest) {
                _terminateCompleter.complete();
                _logger
                    .severe('Terminating builds due to package graph update, '
                        'please restart the build.');
              }
              return change;
            });
          } else if (_isBuildYaml(id) ||
              _isConfiguredBuildYaml(id) ||
              _isPackageBuildYamlOverride(id)) {
            controller.add(BuildResult(BuildStatus.failure, [],
                failureType: FailureType.buildConfigChanged));

            // Kill future builds if the build.yaml files change.
            _terminateCompleter.complete();
            _logger.severe(
                'Terminating builds due to ${id.package}:${id.path} update.');
          }
          return change;
        })
        .where((change) {
          assert(_readyCompleter.isCompleted);
          return shouldProcess(
            change,
            assetGraph,
            options,
            _willCreateOutputDirs,
            _expectedDeletes,
          );
        })
        .transform(debounceBuffer(_debounceDelay))
        .transform(takeUntil(terminate))
        .transform(asyncMapBuffer((changes) => currentBuild = doBuild(changes)
          ..whenComplete(() => currentBuild = null)))
        .listen((BuildResult result) {
          if (controller.isClosed) return;
          controller.add(result);
        })
        .onDone(() async {
          await currentBuild;
          await _build?.beforeExit();
          if (!controller.isClosed) await controller.close();
          _logger.info('Builds finished. Safe to exit\n');
        });

    // Schedule the actual first build for the future so we can return the
    // stream synchronously.
    () async {
      await logTimedAsync(_logger, 'Waiting for all file watchers to be ready',
          () => graphWatcher.ready);
      originalRootPackagesDigest = md5
          .convert(await watcherEnvironment.reader.readAsBytes(rootPackagesId));

      BuildResult firstBuild;
      try {
        _build = await BuildImpl.create(
            options, watcherEnvironment, builders, builderConfigOverrides,
            isReleaseBuild: isReleaseMode);

        firstBuild = await _build.run({}, buildDirs: _buildDirs);
      } on CannotBuildException {
        _terminateCompleter.complete();

        firstBuild = BuildResult(BuildStatus.failure, []);
      } on BuildScriptChangedException {
        _terminateCompleter.complete();

        firstBuild = BuildResult(BuildStatus.failure, [],
            failureType: FailureType.buildScriptChanged);
      }

      _reader = _build?.finalizedReader;
      _readyCompleter.complete();
      // It is possible this is already closed if the user kills the process
      // early, which results in an exception without this check.
      if (!controller.isClosed) controller.add(firstBuild);
      firstBuildCompleter.complete(firstBuild);
    }();

    return controller.stream;
  }

  bool _isBuildYaml(AssetId id) => id.path == 'build.yaml';
  bool _isConfiguredBuildYaml(AssetId id) =>
      id.package == packageGraph.root.name &&
      id.path == 'build.$_configKey.yaml';
  bool _isPackageBuildYamlOverride(AssetId id) =>
      id.package == packageGraph.root.name &&
      id.path.contains(_packageBuildYamlRegexp);
  final _packageBuildYamlRegexp = RegExp(r'^[a-z0-9_]+\.build\.yaml$');
}
