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

library watcher.test.utils;

import 'dart:io';

import 'package:path/path.dart' as p;
import 'package:scheduled_test/scheduled_stream.dart';
import 'package:scheduled_test/scheduled_test.dart';
import 'package:watcher/watcher.dart';
import 'package:watcher/src/stat.dart';
import 'package:watcher/src/utils.dart';

// TODO(nweiz): remove this when issue 15042 is fixed.
import 'package:watcher/src/directory_watcher/mac_os.dart';

/// The path to the temporary sandbox created for each test. All file
/// operations are implicitly relative to this directory.
String _sandboxDir;

/// The [Watcher] being used for the current scheduled test.
Watcher _watcher;

/// The mock modification times (in milliseconds since epoch) for each file.
///
/// The actual file system has pretty coarse granularity for file modification
/// times. This means using the real file system requires us to put delays in
/// the tests to ensure we wait long enough between operations for the mod time
/// to be different.
///
/// Instead, we'll just mock that out. Each time a file is written, we manually
/// increment the mod time for that file instantly.
Map<String, int> _mockFileModificationTimes;

typedef Watcher WatcherFactory(String directory);

/// Sets the function used to create the watcher.
set watcherFactory(WatcherFactory factory) {
  _watcherFactory = factory;
}
WatcherFactory _watcherFactory;

/// Creates the sandbox directory the other functions in this library use and
/// ensures it's deleted when the test ends.
///
/// This should usually be called by [setUp].
void createSandbox() {
  var dir = Directory.systemTemp.createTempSync('watcher_test_');
  _sandboxDir = dir.path;

  _mockFileModificationTimes = new Map<String, int>();
  mockGetModificationTime((path) {
    path = p.normalize(p.relative(path, from: _sandboxDir));

    // Make sure we got a path in the sandbox.
    assert(p.isRelative(path) && !path.startsWith(".."));

    var mtime = _mockFileModificationTimes[path];
    return new DateTime.fromMillisecondsSinceEpoch(mtime == null ? 0 : mtime);
  });

  // Delete the sandbox when done.
  currentSchedule.onComplete.schedule(() {
    if (_sandboxDir != null) {
      // TODO(rnystrom): Issue 19155. The watcher should already be closed when
      // we clean up the sandbox.
      if (_watcherEvents != null) {
        _watcherEvents.close();
      }
      new Directory(_sandboxDir).deleteSync(recursive: true);
      _sandboxDir = null;
    }

    _mockFileModificationTimes = null;
    mockGetModificationTime(null);
  }, "delete sandbox");
}

/// Creates a new [Watcher] that watches a temporary file or directory.
///
/// Normally, this will pause the schedule until the watcher is done scanning
/// and is polling for changes. If you pass `false` for [waitForReady], it will
/// not schedule this delay.
///
/// If [path] is provided, watches a subdirectory in the sandbox with that name.
Watcher createWatcher({String path, bool waitForReady}) {
  if (path == null) {
    path = _sandboxDir;
  } else {
    path = p.join(_sandboxDir, path);
  }

  var watcher = _watcherFactory(path);

  // Wait until the scan is finished so that we don't miss changes to files
  // that could occur before the scan completes.
  if (waitForReady != false) {
    schedule(() => watcher.ready, "wait for watcher to be ready");
  }

  return watcher;
}

/// The stream of events from the watcher started with [startWatcher].
ScheduledStream<WatchEvent> _watcherEvents;

/// Creates a new [Watcher] that watches a temporary file or directory and
/// starts monitoring it for events.
///
/// If [path] is provided, watches a path in the sandbox with that name.
void startWatcher({String path}) {
  // We want to wait until we're ready *after* we subscribe to the watcher's
  // events.
  _watcher = createWatcher(path: path, waitForReady: false);

  // Schedule [_watcher.events.listen] so that the watcher doesn't start
  // watching [path] before it exists. Expose [_watcherEvents] immediately so
  // that it can be accessed synchronously after this.
  _watcherEvents = new ScheduledStream(futureStream(schedule(() {
    currentSchedule.onComplete.schedule(() {
      _watcher = null;
      if (!_closePending) _watcherEvents.close();

      // If there are already errors, don't add this to the output and make
      // people think it might be the root cause.
      if (currentSchedule.errors.isEmpty) {
        _watcherEvents.expect(isDone);
      }
    }, "reset watcher");

    return _watcher.events;
  }, "create watcher"), broadcast: true));

  schedule(() => _watcher.ready, "wait for watcher to be ready");
}

/// Whether an event to close [_watcherEvents] has been scheduled.
bool _closePending = false;

/// Schedule closing the watcher stream after the event queue has been pumped.
///
/// This is necessary when events are allowed to occur, but don't have to occur,
/// at the end of a test. Otherwise, if they don't occur, the test will wait
/// indefinitely because they might in the future and because the watcher is
/// normally only closed after the test completes.
void startClosingEventStream() {
  schedule(() {
    _closePending = true;
    pumpEventQueue().then((_) => _watcherEvents.close()).whenComplete(() {
      _closePending = false;
    });
  }, 'start closing event stream');
}

/// A list of [StreamMatcher]s that have been collected using
/// [_collectStreamMatcher].
List<StreamMatcher> _collectedStreamMatchers;

/// Collects all stream matchers that are registered within [block] into a
/// single stream matcher.
///
/// The returned matcher will match each of the collected matchers in order.
StreamMatcher _collectStreamMatcher(block()) {
  var oldStreamMatchers = _collectedStreamMatchers;
  _collectedStreamMatchers = new List<StreamMatcher>();
  try {
    block();
    return inOrder(_collectedStreamMatchers);
  } finally {
    _collectedStreamMatchers = oldStreamMatchers;
  }
}

/// Either add [streamMatcher] as an expectation to [_watcherEvents], or collect
/// it with [_collectStreamMatcher].
///
/// [streamMatcher] can be a [StreamMatcher], a [Matcher], or a value.
void _expectOrCollect(streamMatcher) {
  if (_collectedStreamMatchers != null) {
    _collectedStreamMatchers.add(new StreamMatcher.wrap(streamMatcher));
  } else {
    _watcherEvents.expect(streamMatcher);
  }
}

/// Expects that [matchers] will match emitted events in any order.
///
/// [matchers] may be [Matcher]s or values, but not [StreamMatcher]s.
void inAnyOrder(Iterable matchers) {
  matchers = matchers.toSet();
  _expectOrCollect(nextValues(matchers.length, unorderedMatches(matchers)));
}

/// Expects that the expectations established in either [block1] or [block2]
/// will match the emitted events.
///
/// If both blocks match, the one that consumed more events will be used.
void allowEither(block1(), block2()) {
  _expectOrCollect(either(
      _collectStreamMatcher(block1), _collectStreamMatcher(block2)));
}

/// Allows the expectations established in [block] to match the emitted events.
///
/// If the expectations in [block] don't match, no error will be raised and no
/// events will be consumed. If this is used at the end of a test,
/// [startClosingEventStream] should be called before it.
void allowEvents(block()) {
  _expectOrCollect(allow(_collectStreamMatcher(block)));
}

/// Returns a matcher that matches a [WatchEvent] with the given [type] and
/// [path].
Matcher isWatchEvent(ChangeType type, String path) {
  return predicate((e) {
    return e is WatchEvent && e.type == type &&
        e.path == p.join(_sandboxDir, p.normalize(path));
  }, "is $type $path");
}

/// Returns a [Matcher] that matches a [WatchEvent] for an add event for [path].
Matcher isAddEvent(String path) => isWatchEvent(ChangeType.ADD, path);

/// Returns a [Matcher] that matches a [WatchEvent] for a modification event for
/// [path].
Matcher isModifyEvent(String path) => isWatchEvent(ChangeType.MODIFY, path);

/// Returns a [Matcher] that matches a [WatchEvent] for a removal event for
/// [path].
Matcher isRemoveEvent(String path) => isWatchEvent(ChangeType.REMOVE, path);

/// Expects that the next event emitted will be for an add event for [path].
void expectAddEvent(String path) =>
    _expectOrCollect(isWatchEvent(ChangeType.ADD, path));

/// Expects that the next event emitted will be for a modification event for
/// [path].
void expectModifyEvent(String path) =>
    _expectOrCollect(isWatchEvent(ChangeType.MODIFY, path));

/// Expects that the next event emitted will be for a removal event for [path].
void expectRemoveEvent(String path) =>
    _expectOrCollect(isWatchEvent(ChangeType.REMOVE, path));

/// Consumes an add event for [path] if one is emitted at this point in the
/// schedule, but doesn't throw an error if it isn't.
///
/// If this is used at the end of a test, [startClosingEventStream] should be
/// called before it.
void allowAddEvent(String path) =>
    _expectOrCollect(allow(isWatchEvent(ChangeType.ADD, path)));

/// Consumes a modification event for [path] if one is emitted at this point in
/// the schedule, but doesn't throw an error if it isn't.
///
/// If this is used at the end of a test, [startClosingEventStream] should be
/// called before it.
void allowModifyEvent(String path) =>
    _expectOrCollect(allow(isWatchEvent(ChangeType.MODIFY, path)));

/// Consumes a removal event for [path] if one is emitted at this point in the
/// schedule, but doesn't throw an error if it isn't.
///
/// If this is used at the end of a test, [startClosingEventStream] should be
/// called before it.
void allowRemoveEvent(String path) =>
    _expectOrCollect(allow(isWatchEvent(ChangeType.REMOVE, path)));

/// Schedules writing a file in the sandbox at [path] with [contents].
///
/// If [contents] is omitted, creates an empty file. If [updatedModified] is
/// `false`, the mock file modification time is not changed.
void writeFile(String path, {String contents, bool updateModified}) {
  if (contents == null) contents = "";
  if (updateModified == null) updateModified = true;

  schedule(() {
    var fullPath = p.join(_sandboxDir, path);

    // Create any needed subdirectories.
    var dir = new Directory(p.dirname(fullPath));
    if (!dir.existsSync()) {
      dir.createSync(recursive: true);
    }

    new File(fullPath).writeAsStringSync(contents);

    // Manually update the mock modification time for the file.
    if (updateModified) {
      // Make sure we always use the same separator on Windows.
      path = p.normalize(path);

      var milliseconds = _mockFileModificationTimes.putIfAbsent(path, () => 0);
      _mockFileModificationTimes[path]++;
    }
  }, "write file $path");
}

/// Schedules deleting a file in the sandbox at [path].
void deleteFile(String path) {
  schedule(() {
    new File(p.join(_sandboxDir, path)).deleteSync();
  }, "delete file $path");
}

/// Schedules renaming a file in the sandbox from [from] to [to].
///
/// If [contents] is omitted, creates an empty file.
void renameFile(String from, String to) {
  schedule(() {
    new File(p.join(_sandboxDir, from)).renameSync(p.join(_sandboxDir, to));

    // Make sure we always use the same separator on Windows.
    to = p.normalize(to);

    // Manually update the mock modification time for the file.
    var milliseconds = _mockFileModificationTimes.putIfAbsent(to, () => 0);
    _mockFileModificationTimes[to]++;
  }, "rename file $from to $to");
}

/// Schedules creating a directory in the sandbox at [path].
void createDir(String path) {
  schedule(() {
    new Directory(p.join(_sandboxDir, path)).createSync();
  }, "create directory $path");
}

/// Schedules renaming a directory in the sandbox from [from] to [to].
void renameDir(String from, String to) {
  schedule(() {
    new Directory(p.join(_sandboxDir, from))
        .renameSync(p.join(_sandboxDir, to));
  }, "rename directory $from to $to");
}

/// Schedules deleting a directory in the sandbox at [path].
void deleteDir(String path) {
  schedule(() {
    new Directory(p.join(_sandboxDir, path)).deleteSync(recursive: true);
  }, "delete directory $path");
}

/// Runs [callback] with every permutation of non-negative [i], [j], and [k]
/// less than [limit].
///
/// Returns a set of all values returns by [callback].
///
/// [limit] defaults to 3.
Set withPermutations(callback(int i, int j, int k), {int limit}) {
  if (limit == null) limit = 3;
  var results = new Set();
  for (var i = 0; i < limit; i++) {
    for (var j = 0; j < limit; j++) {
      for (var k = 0; k < limit; k++) {
        results.add(callback(i, j, k));
      }
    }
  }
  return results;
}
