// Copyright (c) 2013, 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.

// @dart = 2.9

import "dart:async";
import "dart:io";
import "dart:isolate";

import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";
import "package:path/path.dart";

void testWatchCreateFile() {
  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
  var file = new File(join(dir.path, 'file'));

  var watcher = dir.watch();

  asyncStart();
  var sub;
  sub = watcher.listen((event) {
    if (event is FileSystemCreateEvent && event.path.endsWith('file')) {
      Expect.isFalse(event.isDirectory);
      asyncEnd();
      sub.cancel();
      dir.deleteSync(recursive: true);
    }
  }, onError: (e) {
    dir.deleteSync(recursive: true);
    throw e;
  });

  file.createSync();
}

void testWatchCreateDir() {
  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
  var subdir = new Directory(join(dir.path, 'dir'));

  var watcher = dir.watch();

  asyncStart();
  var sub;
  sub = watcher.listen((event) {
    if (event is FileSystemCreateEvent && event.path.endsWith('dir')) {
      Expect.isTrue(event.isDirectory);
      asyncEnd();
      sub.cancel();
      dir.deleteSync(recursive: true);
    }
  }, onError: (e) {
    dir.deleteSync(recursive: true);
    throw e;
  });

  subdir.createSync();
}

void testWatchModifyFile() {
  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
  var file = new File(join(dir.path, 'file'));
  file.createSync();

  var watcher = dir.watch();

  asyncStart();
  var sub;
  sub = watcher.listen((event) {
    if (event is FileSystemModifyEvent) {
      Expect.isTrue(event.path.endsWith('file'));
      sub.cancel();
      asyncEnd();
      dir.deleteSync(recursive: true);
    }
  }, onError: (e) {
    dir.deleteSync(recursive: true);
    throw e;
  });

  file.writeAsStringSync('a');
}

void testWatchTruncateFile() {
  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
  var file = new File(join(dir.path, 'file'));
  file.writeAsStringSync('ab');
  var fileHandle = file.openSync(mode: FileMode.append);

  var watcher = dir.watch();

  asyncStart();
  var sub;
  sub = watcher.listen((event) {
    if (event is FileSystemModifyEvent) {
      Expect.isTrue(event.path.endsWith('file'));
      Expect.isTrue(event.contentChanged);
      sub.cancel();
      asyncEnd();
      fileHandle.closeSync();
      dir.deleteSync(recursive: true);
    }
  }, onError: (e) {
    dir.deleteSync(recursive: true);
    throw e;
  });

  fileHandle.truncateSync(1);
}

void testWatchMoveFile() {
  // Mac OS doesn't report move events.
  if (Platform.isMacOS) return;
  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
  var file = new File(join(dir.path, 'file'));
  file.createSync();

  var watcher = dir.watch();

  asyncStart();
  var sub;
  sub = watcher.listen((event) {
    if (event is FileSystemMoveEvent) {
      Expect.isTrue(event.path.endsWith('file'));
      if (event.destination != null) {
        Expect.isTrue(event.destination.endsWith('file2'));
      }
      sub.cancel();
      asyncEnd();
      dir.deleteSync(recursive: true);
    }
  }, onError: (e) {
    dir.deleteSync(recursive: true);
    throw e;
  });

  file.renameSync(join(dir.path, 'file2'));
}

void testWatchDeleteFile() {
  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
  var file = new File(join(dir.path, 'file'));
  file.createSync();

  var watcher = dir.watch();

  asyncStart();
  var sub;
  sub = watcher.listen((event) {
    if (event is FileSystemDeleteEvent) {
      Expect.isTrue(event.path.endsWith('file'));
      sub.cancel();
      asyncEnd();
      dir.deleteSync(recursive: true);
    }
  }, onError: (e) {
    dir.deleteSync(recursive: true);
    throw e;
  });

  file.deleteSync();
}

void testWatchDeleteDir() {
  // Windows keeps the directory handle open, even though it's deleted. It'll
  // be flushed completely, once the watcher is closed as well.
  if (Platform.isWindows) return;
  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
  var watcher = dir.watch(events: 0);

  asyncStart();
  watcher.listen((event) {
    if (event is FileSystemDeleteEvent) {
      Expect.isTrue(event.path == dir.path);
    }
  }, onDone: () {
    asyncEnd();
  });

  dir.deleteSync();
}

void testWatchOnlyModifyFile() {
  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
  var file = new File(join(dir.path, 'file'));

  var watcher = dir.watch(events: FileSystemEvent.modify);

  asyncStart();
  var sub;
  sub = watcher.listen((event) {
    Expect.isTrue(event is FileSystemModifyEvent);
    Expect.isTrue(event.path.endsWith('file'));
    sub.cancel();
    asyncEnd();
    dir.deleteSync(recursive: true);
  }, onError: (e) {
    dir.deleteSync(recursive: true);
    throw e;
  });

  file.createSync();
  file.writeAsStringSync('a');
}

void testMultipleEvents() {
  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
  var file = new File(join(dir.path, 'file'));
  var file2 = new File(join(dir.path, 'file2'));

  var watcher = dir.watch();

  asyncStart();
  int state = 0;
  var sub;
  sub = watcher.listen((event) {
    int newState = 0;
    switch (event.type) {
      case FileSystemEvent.create:
        newState = 1;
        break;

      case FileSystemEvent.modify:
        newState = 2;
        break;

      case FileSystemEvent.move:
        newState = 3;
        break;

      case FileSystemEvent.delete:
        newState = 4;
        sub.cancel();
        asyncEnd();
        dir.deleteSync();
        break;
    }
    if (!Platform.isMacOS) {
      if (newState < state) throw "Bad state";
    }
    state = newState;
  });

  file.createSync();
  file.writeAsStringSync('a');
  file.renameSync(file2.path);
  file2.deleteSync();
}

void testWatchRecursive() {
  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
  if (Platform.isLinux) {
    Expect.throws(() => dir.watch(recursive: true));
    return;
  }
  var dir2 = new Directory(join(dir.path, 'dir'));
  dir2.createSync();
  var file = new File(join(dir.path, 'dir/file'));

  var watcher = dir.watch(recursive: true);

  asyncStart();
  var sub;
  sub = watcher.listen((event) {
    if (event.path.endsWith('file')) {
      sub.cancel();
      asyncEnd();
      dir.deleteSync(recursive: true);
    }
  }, onError: (e) {
    dir.deleteSync(recursive: true);
    throw e;
  });

  file.createSync();
}

void testWatchNonRecursive() {
  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
  var dir2 = new Directory(join(dir.path, 'dir'));
  dir2.createSync();
  var file = new File(join(dir.path, 'dir/file'));

  var watcher = dir.watch(recursive: false);

  asyncStart();
  var sub;
  sub = watcher.listen((event) {
    if (event.path.endsWith('file')) {
      throw "File change event not expected";
    }
  }, onError: (e) {
    dir.deleteSync(recursive: true);
    throw e;
  });

  file.createSync();

  new Timer(const Duration(milliseconds: 300), () {
    sub.cancel();
    asyncEnd();
    dir.deleteSync(recursive: true);
  });
}

void testWatchNonExisting() {
  // MacOS allows listening on non-existing paths.
  if (Platform.isMacOS) return;
  asyncStart();
  new Directory('__some_none_existing_dir__').watch().listen((_) {
    Expect.fail('unexpected error');
  }, onError: (e) {
    asyncEnd();
    Expect.isTrue(e is FileSystemException);
  });
}

void testWatchMoveSelf() {
  // Windows keeps the directory handle open, even though it's deleted. It'll
  // be flushed completely, once the watcher is closed as well.
  if (Platform.isWindows) return;
  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
  var dir2 = new Directory(join(dir.path, 'dir'))..createSync();

  var watcher = dir2.watch();

  asyncStart();
  bool gotDelete = false;
  watcher.listen((event) {
    if (event is FileSystemDeleteEvent) {
      Expect.isTrue(event.path.endsWith('dir'));
      gotDelete = true;
    }
  }, onDone: () {
    Expect.isTrue(gotDelete);
    dir.deleteSync(recursive: true);
    asyncEnd();
  });

  dir2.renameSync(join(dir.path, 'new_dir'));
}

testWatchConsistentModifiedFile() async {
  // When file modification starts before the watcher listen() is called and the first event
  // happens in a very short period of time the modifying event will be missed before the
  // stream listen has been set up and the watcher will hang forever.
  // Bug: https://github.com/dart-lang/sdk/issues/37233
  // Bug: https://github.com/dart-lang/sdk/issues/37909
  asyncStart();
  ReceivePort receivePort = ReceivePort();
  Completer<bool> exiting = Completer<bool>();

  Directory dir;
  Completer<bool> modificationEventReceived = Completer<bool>();

  StreamSubscription receiverSubscription;
  SendPort workerSendPort;
  receiverSubscription = receivePort.listen((object) async {
    if (object == 'modification_started') {
      var watcher = dir.watch();
      var subscription;
      // Wait for event and check the type
      subscription = watcher.listen((data) async {
        if (data is FileSystemModifyEvent) {
          Expect.isTrue(data.path.endsWith('file'));
          await subscription.cancel();
          modificationEventReceived.complete(true);
        }
      });
      return;
    }
    if (object == 'end') {
      await receiverSubscription.cancel();
      exiting.complete(true);
      return;
    }
    // init event
    workerSendPort = object[0];
    dir = new Directory(object[1]);
  });

  Completer<bool> workerExitedCompleter = Completer();
  RawReceivePort exitReceivePort = RawReceivePort((object) {
    workerExitedCompleter.complete(true);
  });
  RawReceivePort errorReceivePort = RawReceivePort((object) {
    print('worker errored: $object');
  });
  Isolate isolate = await Isolate.spawn(modifyFiles, receivePort.sendPort,
      onExit: exitReceivePort.sendPort, onError: errorReceivePort.sendPort);

  await modificationEventReceived.future;
  workerSendPort.send('end');

  await exiting.future;
  await workerExitedCompleter.future;
  exitReceivePort.close();
  errorReceivePort.close();
  // Stop modifier isolate
  isolate.kill();
  asyncEnd();
}

void modifyFiles(SendPort sendPort) async {
  // Send sendPort back to listen for modification signal.
  ReceivePort receivePort = ReceivePort();
  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');

  // Create file within the directory and keep modifying.
  var file = new File(join(dir.path, 'file'));
  file.createSync();
  bool done = false;
  var subscription;
  subscription = receivePort.listen((object) async {
    if (object == 'end') {
      await subscription.cancel();
      done = true;
    }
  });
  sendPort.send([receivePort.sendPort, dir.path]);
  bool notificationSent = false;
  while (!done) {
    // Start modifying the file continuously before watcher start watching.
    for (int i = 0; i < 100; i++) {
      file.writeAsStringSync('a');
    }
    if (!notificationSent) {
      sendPort.send('modification_started');
      notificationSent = true;
    }
    await Future.delayed(Duration());
  }
  // Clean up the directory and files
  dir.deleteSync(recursive: true);
  sendPort.send('end');
}

testWatchOverflow() async {
  // When underlying buffer for ReadDirectoryChangesW overflows(on Windows),
  // it will send an exception to Stream which has been listened.
  // Bug: https://github.com/dart-lang/sdk/issues/37233
  asyncStart();
  ReceivePort receivePort = ReceivePort();
  Completer<bool> exiting = Completer<bool>();

  Directory dir =
      Directory.systemTemp.createTempSync('dart_file_system_watcher');
  var file = new File(join(dir.path, 'file'));
  file.createSync();

  Isolate isolate =
      await Isolate.spawn(watcher, receivePort.sendPort, paused: true);

  var subscription;
  subscription = receivePort.listen((object) async {
    if (object == 'end') {
      exiting.complete(true);
      subscription.cancel();
      // Clean up the directory and files
      dir.deleteSync(recursive: true);
      asyncEnd();
    } else if (object == 'start') {
      isolate.pause(isolate.pauseCapability);
      // Populate the buffer to overflows and check for exception
      for (int i = 0; i < 2000; i++) {
        file.writeAsStringSync('a');
      }
      isolate.resume(isolate.pauseCapability);
    }
  });
  // Resume paused isolate to create watcher
  isolate.resume(isolate.pauseCapability);

  await exiting.future;
  isolate.kill();
}

void watcher(SendPort sendPort) async {
  runZonedGuarded(() {
    var watcher = Directory.systemTemp.watch(recursive: true);
    watcher.listen((data) async {});
    sendPort.send('start');
  }, (error, stack) {
    print(error);
    sendPort.send('end');
  });
}

void main() {
  if (!FileSystemEntity.isWatchSupported) return;
  testWatchCreateFile();
  testWatchCreateDir();
  testWatchModifyFile();
  testWatchTruncateFile();
  testWatchMoveFile();
  testWatchDeleteFile();
  testWatchDeleteDir();
  testWatchOnlyModifyFile();
  testMultipleEvents();
  testWatchNonRecursive();
  testWatchNonExisting();
  testWatchMoveSelf();
  testWatchConsistentModifiedFile();
  if (Platform.isWindows) testWatchOverflow();
}
