// Copyright (c) 2021, 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:core';
import 'dart:io' as io;
import 'dart:isolate';
import 'dart:math';

import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/instrumentation/service.dart';
import 'package:pedantic/pedantic.dart';
import 'package:watcher/watcher.dart';

Future<void> _isolateMain(SendPort sendPort) async {
  var fromMainIsolate = ReceivePort();
  var bazelIsolate = BazelFileWatcherIsolate(
      fromMainIsolate, sendPort, PhysicalResourceProvider.INSTANCE)
    ..start();
  await bazelIsolate.hasFinished;
}

/// Exposes the ability to poll for changes in generated files.
///
/// The only logic here is that we may have multiple "candidate" paths where the
/// file might be located, but after the first time we actually find the file,
/// we can only focus on that particular path, since the files should be
/// consistently in the same place after rebuilds.
class BazelFilePoller {
  /// The possible "candidate" paths that we watch.
  final List<String> _candidates;

  /// The time of last modification of the file under [_validPath].
  _TimestampAndLength? _lastModified;

  /// The resource provider used for polling the files.
  final ResourceProvider _provider;

  /// One of the [_candidates] that is valid, i.e. we found a file with that
  /// path.
  String? _validPath;

  BazelFilePoller(this._provider, this._candidates);

  /// Checks if the file corresponding to the watched path has changed and
  /// returns the event or `null` if nothing changed.
  WatchEvent? poll() {
    _TimestampAndLength? modified;
    if (_validPath == null) {
      var info = _pollAll();
      if (info != null) {
        _validPath = info.path;
        modified = info.modified;
      }
    } else {
      modified = _pollOne(_validPath!);
    }

    // If there is no file, then we have nothing to do.
    if (_validPath == null) return null;

    WatchEvent? result;
    if (modified == null && _lastModified != null) {
      // The file is no longer there, so let's issue a REMOVE event, unset
      // `_validPath` and set the timer to poll more frequently.
      result = WatchEvent(ChangeType.REMOVE, _validPath!);
      _validPath = null;
    } else if (modified != null && _lastModified == null) {
      result = WatchEvent(ChangeType.ADD, _validPath!);
    } else if (_lastModified != null && modified != _lastModified) {
      result = WatchEvent(ChangeType.MODIFY, _validPath!);
    }

    _lastModified = modified;
    return result;
  }

  /// Starts watching the files.
  ///
  /// This should be called when creating an instance of this class to correctly
  /// categorize events (e.g. whether a file already existed or was added).
  void start() {
    assert(_validPath == null);
    assert(_lastModified == null);
    var info = _pollAll();
    if (info != null) {
      _validPath = info.path;
      _lastModified = info.modified;
    }
  }

  /// Tries polling all the possible paths.
  ///
  /// Will set [_validPath] and return its modified time if a file is found.
  /// Returns [null] if nothing is found.
  FileInfo? _pollAll() {
    assert(_validPath == null);
    for (var path in _candidates) {
      var modified = _pollOne(path);
      if (modified != null) {
        return FileInfo(path, modified);
      }
    }
    return null;
  }

  /// Returns the modified time of the path or `null` if the file does not
  /// exist.
  _TimestampAndLength? _pollOne(String path) {
    try {
      // This might seem a bit convoluted but is necessary to deal with a
      // symlink to a directory (e.g., `bazel-bin`).
      var resource = _provider.getResource(
          _provider.getResource(path).resolveSymbolicLinksSync().path);
      if (resource is File) {
        var timestamp = resource.modificationStamp;
        var length = resource.lengthSync;
        return _TimestampAndLength(timestamp, length);
      } else if (resource is Folder) {
        // `ResourceProvider` doesn't currently support getting timestamps of a
        // folder, so we use a dummy value here. But it's still useful: this
        // will correctly generate `ADD` or `REMOVE` events (we'll be just
        // unable to generate any `CHANGE` events).
        return _TimestampAndLength(0, 0);
      }
    } on FileSystemException catch (_) {
      // File doesn't exist, so return null.
      return null;
    }
  }
}

/// The watcher implementation that runs in a separate isolate.
///
/// It'll try to detect when Bazel finished running (through [PollTrigger] which
/// usually will be [_BazelInvocationWatcher]) and then poll all the files to
/// find any changes, which will be sent to the main isolate as
/// [BazelWatcherEvents].
class BazelFileWatcherIsolate {
  final ReceivePort _fromMainIsolate;
  final SendPort _toMainIsolate;
  late final StreamSubscription _fromMainIsolateSubscription;

  /// For each workspace tracks all the data associated with it.
  final _perWorkspaceData = <String, _PerWorkspaceData>{};

  /// A factory for [PollTrigger].
  ///
  /// Used mostly for testing to allow using a different trigger.
  late final PollTrigger Function(String) _pollTriggerFactory;

  /// Resource provider used for polling.
  ///
  /// NB: The default [PollTrigger] (i.e., [_BazelInvocationWatcher]) uses
  /// `dart:io` directly. So for testing both [_provider] and
  /// [_pollTriggerFactory] should be provided.
  final ResourceProvider _provider;

  final _hasFinished = Completer<void>();

  BazelFileWatcherIsolate(
      this._fromMainIsolate, this._toMainIsolate, this._provider,
      {PollTrigger Function(String)? pollTriggerFactory}) {
    _pollTriggerFactory = pollTriggerFactory ?? _defaultPollTrigger;
  }

  Future<void> get hasFinished => _hasFinished.future;

  void handleRequest(dynamic request) async {
    if (request is BazelWatcherStartWatching) {
      var workspaceData = _perWorkspaceData[request.workspace];
      if (workspaceData == null) {
        var trigger = _pollTriggerFactory(request.workspace);
        var subscription =
            trigger.stream.listen((_) => _pollAllWatchers(request.workspace));
        workspaceData = _PerWorkspaceData(trigger, subscription);
        _perWorkspaceData[request.workspace] = workspaceData;
      }
      var requestedPath = request.info.requestedPath;
      var count = workspaceData.watched.add(requestedPath);
      if (count > 1) {
        assert(workspaceData.pollers.containsKey(requestedPath));
        return;
      }
      workspaceData.pollers[requestedPath] =
          BazelFilePoller(_provider, request.info.candidatePaths)..start();
    } else if (request is BazelWatcherStopWatching) {
      var workspaceData = _perWorkspaceData[request.workspace];
      if (workspaceData == null) return;
      var count = workspaceData.watched.remove(request.requestedPath);
      if (count == 0) {
        workspaceData.pollers.remove(request.requestedPath);
        if (workspaceData.watched.isEmpty) {
          workspaceData.trigger.cancel();
          unawaited(workspaceData.pollSubscription.cancel());
          _perWorkspaceData.remove(request.workspace);
        }
      }
    } else if (request is BazelWatcherShutdownIsolate) {
      unawaited(_fromMainIsolateSubscription.cancel());
      _fromMainIsolate.close();
      for (var data in _perWorkspaceData.values) {
        data.trigger.cancel();
        unawaited(data.pollSubscription.cancel());
      }
      _hasFinished.complete();
      _perWorkspaceData.clear();
    } else {
      // We don't have access to the `InstrumentationService` so we send the
      // message to the main isolate to log it.
      _toMainIsolate.send(BazelWatcherError(
          'BazelFileWatcherIsolate got unexpected request: $request'));
    }
  }

  /// Returns the total number of requested file paths that are being watched.
  ///
  /// This is for testing *only*.
  int numWatchedFiles() {
    var total = 0;
    for (var data in _perWorkspaceData.values) {
      total += data.watched.length;
    }
    return total;
  }

  /// Starts listening for messages from the main isolate and sends it
  /// [BazelWatcherIsolateStarted].
  void start() {
    _fromMainIsolateSubscription = _fromMainIsolate.listen(handleRequest);
    _toMainIsolate.send(BazelWatcherIsolateStarted(_fromMainIsolate.sendPort));
  }

  PollTrigger _defaultPollTrigger(String workspacePath) =>
      _BazelInvocationWatcher(_provider, workspacePath);

  void _pollAllWatchers(String workspace) {
    try {
      var events = <WatchEvent>[];
      for (var watcher in _perWorkspaceData[workspace]!.pollers.values) {
        var event = watcher.poll();
        if (event != null) events.add(event);
      }
      if (events.isNotEmpty) {
        _toMainIsolate.send(BazelWatcherEvents(events));
      }
    } on Exception catch (_) {
      // This shouldn't really happen, but we shouldn't crash when polling
      // either, so just ignore the error and rely on the next try.
      return;
    }
  }
}

/// A watcher service that exposes batch-oriented notification interface for
/// changes to watched files.
///
/// The actual `stat`ing of file takes place in a separate isolate to avoid
/// blocking the main one. Since much of the analysis server is synchronous, we
/// can't use async functions and resort to launching the isolate and buffering
/// the requests until the isolate has started.
///
/// The isolate is started lazily on the first request to watch a path, so
/// instantiating [BazelFileWatcherService] is very cheap.
///
/// The protocol when communicating with the isolate:
/// 1. The watcher isolate sends to the main one a [BazelWatcherIsolateStarted]
///    and expects a [BazelWatcherInitializeIsolate] to be sent from the main
///    isolate as a reply.
/// 2. The main isolate can request to start watching a file by sending
///    [BazelWatcherStartWatching] request. There is no response expected.
/// 3. The watcher isolate will send a [BazelWatcherEvents] notification when
///    changes are detected. Again, no response from the main isolate is
///    expected.
/// 4. The main isolate will send a [BazelWatcherShutdownIsolate] when the
///    isolate is supposed to shut down. No more messages should be exchanged
///    afterwards.
class BazelFileWatcherService {
  final InstrumentationService _instrumetation;

  final _events = StreamController<List<WatchEvent>>.broadcast();

  /// Buffers files to watch until the isolate is ready.
  final _buffer = <BazelWatcherMessage>[];

  late final ReceivePort _fromIsolatePort;
  late final SendPort _toIsolatePort;
  late final StreamSubscription _fromIsolateSubscription;

  /// True if we have launched the isolate.
  bool _isolateIsStarting = false;

  /// True if the isolate is ready to watch files.
  final _isolateHasStarted = Completer<void>();

  BazelFileWatcherService(this._instrumetation);

  Stream<List<WatchEvent>> get events => _events.stream;

  /// Shuts everything down including the watcher isolate.
  /// FIXME(michalt): Remove this if we really never need to shut down the
  /// isolate.
  void shutdown() {
    if (_isolateHasStarted.isCompleted) {
      _toIsolatePort.send(BazelWatcherShutdownIsolate());
    }
    if (_isolateIsStarting) {
      _fromIsolateSubscription.cancel();
      _fromIsolatePort.close();
    }
    _events.close();
  }

  void startWatching(String workspace, BazelSearchInfo info) {
    assert(!_events.isClosed);
    _startIsolateIfNeeded();
    var request = BazelWatcherStartWatching(workspace, info);
    if (!_isolateHasStarted.isCompleted) {
      _buffer.add(request);
    } else {
      _toIsolatePort.send(request);
    }
  }

  void stopWatching(String workspace, String requestedPath) {
    assert(!_events.isClosed);
    var request = BazelWatcherStopWatching(workspace, requestedPath);
    if (!_isolateHasStarted.isCompleted) {
      _buffer.add(request);
    } else {
      _toIsolatePort.send(request);
    }
  }

  void _handleIsolateMessage(dynamic message) {
    if (message is BazelWatcherIsolateStarted) {
      _toIsolatePort = message.sendPort;
      _isolateHasStarted.complete();
    } else if (message is BazelWatcherEvents) {
      _events.add(message.events);
    } else if (message is BazelWatcherError) {
      _instrumetation.logError(message.message);
    } else {
      _instrumetation.logError(
          'Received unexpected message from BazelFileWatcherIsolate: $message');
    }
  }

  /// Starts the isolate if it has not yet been started.
  void _startIsolateIfNeeded() {
    if (_isolateIsStarting) return;
    _isolateIsStarting = true;
    _startIsolateImpl();
    _isolateHasStarted.future.then((_) {
      _buffer.forEach(_toIsolatePort.send);
      _buffer.clear();
    });
  }

  Future<void> _startIsolateImpl() async {
    _fromIsolatePort = ReceivePort();
    _fromIsolateSubscription = _fromIsolatePort.listen(_handleIsolateMessage);
    await Isolate.spawn(_isolateMain, _fromIsolatePort.sendPort);
  }
}

/// Notification that we issue when searching for generated files in a Bazel
/// workspace.
///
/// This allows clients to watch for changes to the generated files.
class BazelSearchInfo {
  /// Candidate paths that we searched.
  final List<String> candidatePaths;

  /// Absolute path that we tried searching for.
  ///
  /// This is not necessarily the path of the actual file that will be used. See
  /// `BazelWorkspace.findFile` for details.
  final String requestedPath;

  BazelSearchInfo(this.requestedPath, this.candidatePaths);
}

class BazelWatcherError implements BazelWatcherMessage {
  final String message;
  BazelWatcherError(this.message);
}

class BazelWatcherEvents implements BazelWatcherMessage {
  final List<WatchEvent> events;
  BazelWatcherEvents(this.events);
}

/// Sent by the watcher isolate to transfer the [SendPort] to the main isolate.
class BazelWatcherIsolateStarted implements BazelWatcherMessage {
  final SendPort sendPort;
  BazelWatcherIsolateStarted(this.sendPort);
}

abstract class BazelWatcherMessage {}

class BazelWatcherShutdownIsolate implements BazelWatcherMessage {}

class BazelWatcherStartWatching implements BazelWatcherMessage {
  final String workspace;
  final BazelSearchInfo info;
  BazelWatcherStartWatching(this.workspace, this.info);
}

class BazelWatcherStopWatching implements BazelWatcherMessage {
  final String workspace;
  final String requestedPath;
  BazelWatcherStopWatching(this.workspace, this.requestedPath);
}

class FileInfo {
  String path;
  _TimestampAndLength modified;
  FileInfo(this.path, this.modified);
}

/// Triggers polling every time something appears in the [stream].
abstract class PollTrigger {
  Stream<Object> get stream;
  void cancel();
}

/// Watches for finished Bazel invocations.
///
/// The idea here is to detect when Bazel finished running and use that to
/// trigger polling. To detect that we use the `command.log` file that bazel
/// contiuously updates as the build progresses. We find that file based on [1]:
///
/// - In the workspace directory there should be a `bazel-out` symlink whose
///   target should be of the form:
///   `[...]/<hash of workspace>/execroot/<workspace name>/bazel-out`
/// - The file should be in `[...]/<hash of workspace>/command.log`.
///
/// In other words, we need to get the target of the symlink and then trim three
/// last parts of the path.
///
/// [1] https://docs.bazel.build/versions/master/output_directories.html
///
/// NB: We're not using a [ResourceProvider] because it doesn't support finding a
/// target of a symlink.
class _BazelInvocationWatcher implements PollTrigger {
  /// Determines how often do we check for `command.log` changes.
  ///
  /// Note that on some systems the granularity is about 1s, so let's set this
  /// to some greater value just to be safe we don't miss any updates.
  static const _pollInterval = Duration(seconds: 2);

  /// To confirm that a build finished, we check for these messages in the
  /// `command.log`.
  static const _buildCompletedMsgs = [
    'Build completed successfully',
    'Build completed',
    'Build did NOT complete successfully',
  ];

  final _controller = StreamController<WatchEvent>.broadcast();
  final ResourceProvider _provider;
  final String _workspacePath;
  late final Timer _timer;
  BazelFilePoller? _poller;
  String? _commandLogPath;

  _BazelInvocationWatcher(this._provider, this._workspacePath) {
    _timer = Timer.periodic(_pollInterval, _poll);
  }

  @override
  Stream<WatchEvent> get stream => _controller.stream;

  @override
  void cancel() => _timer.cancel();

  bool _buildFinished(String contents) {
    // Only look at the last 1024 characters.
    var offset = max(0, contents.length - 1024);
    return _buildCompletedMsgs.any((msg) => contents.contains(msg, offset));
  }

  Future<String?> _getCommandLogPath() async {
    String? resolvedLink;
    var bazelOut = _inWorkspace('bazel-out');
    var blazeOut = _inWorkspace('blaze-out');
    if (await io.Link(bazelOut).exists()) {
      resolvedLink = await io.Link(bazelOut).target();
    } else if (await io.Link(blazeOut).exists()) {
      resolvedLink = await io.Link(blazeOut).target();
    }
    if (resolvedLink == null) return null;
    var pathContext = _provider.pathContext;
    return pathContext.join(
        pathContext
            .dirname(pathContext.dirname(pathContext.dirname(resolvedLink))),
        'command.log');
  }

  String _inWorkspace(String p) =>
      _provider.pathContext.join(_workspacePath, p);

  Future<void> _poll(Timer _) async {
    try {
      _commandLogPath ??= await _getCommandLogPath();
      if (_commandLogPath == null) return;

      _poller ??= BazelFilePoller(_provider, [_commandLogPath!]);
      var event = _poller!.poll();
      if (event == null) return;

      var file = io.File(_commandLogPath!);
      var contents = file.readAsStringSync();
      if (_buildFinished(contents)) {
        _controller.add(WatchEvent(ChangeType.MODIFY, _commandLogPath!));
      }
    } on Exception catch (_) {
      // Ignore failures, it's possible that the file was deleted between when
      // we checked and tried to read it, etc.
      return;
    }
  }
}

class _Multiset<T> {
  final _counts = <T, int>{};

  bool get isEmpty => _counts.isEmpty;

  int get length =>
      _counts.values.fold(0, (accumulator, count) => accumulator + count);

  /// Returns the number of [elem] objects after the addition.
  int add(T elem) =>
      _counts.update(elem, (count) => count + 1, ifAbsent: () => 1);

  /// Returns the number of [elem] objects after the removal.
  int remove(T elem) {
    var newCount = _counts.update(elem, (count) => count - 1);
    if (newCount == 0) {
      _counts.remove(elem);
    }
    return newCount;
  }
}

class _PerWorkspaceData {
  /// For each requested file stores the corresponding [BazelFilePoller].
  final pollers = <String, BazelFilePoller>{};

  /// Keeps count of the number of requests to watch a file, so that we can stop
  /// watching when we reach 0 clients.
  final watched = _Multiset();

  /// The [PollTrigger] that detects when we should poll files.
  final PollTrigger trigger;

  /// Subscription of [trigger].
  final StreamSubscription<Object> pollSubscription;

  _PerWorkspaceData(this.trigger, this.pollSubscription);
}

/// Stores the timestamp of a file and its length.
///
/// This turns out to be important for tracking files that change a lot, like
/// the `command.log` that we use to detect the finished build.  Bazel writes to
/// the file continuously and because the resolution of a timestamp is pretty
/// low, it's quite possible to receive the same timestamp even though the file
/// has changed.  We use its length to remedy that.  It's not perfect (for that
/// we'd have to compute the hash), but it should be reasonable trade-off (to
/// avoid any performance impact from reading and hashing the file).
class _TimestampAndLength {
  final int timestamp;
  final int length;
  _TimestampAndLength(this.timestamp, this.length);

  @override
  int get hashCode =>
      // We don't really need to compute hashes, just check the equality. But
      // throw in case someone expects this to work.
      throw UnimplementedError(
          '_TimestampAndLength.hashCode has not been implemented yet');

  @override
  bool operator ==(Object other) {
    if (other is! _TimestampAndLength) return false;
    return timestamp == other.timestamp && length == other.length;
  }

  // For debugging only.
  @override
  String toString() =>
      '_TimestampAndLength(timestamp=$timestamp, length=$length)';
}
