// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

library webdriver.async_helpers;

import 'dart:async' show Completer, Future;

import 'package:matcher/matcher.dart';

const defaultInterval = const Duration(milliseconds: 500);
const defaultTimeout = const Duration(seconds: 5);

const clock = const Clock();

Future waitFor(condition(), {matcher: isNotNull,
    Duration timeout: defaultTimeout,
    Duration interval: defaultInterval}) => clock.waitFor(condition,
        matcher: matcher, timeout: timeout, interval: interval);

class Clock {
  const Clock();

  /// Sleep for the specified time.
  Future sleep([Duration interval = defaultInterval]) =>
      new Future.delayed(interval);

  /// The current time.
  DateTime get now => new DateTime.now();

  /// Waits until [condition] evaluates to a value that matches [matcher] or
  /// until [timeout] time has passed. If [condition] returns a [Future], then
  /// uses the value of that [Future] rather than the value of [condition].
  ///
  /// If the wait is successful, then the matching return value of [condition]
  /// is returned. Otherwise, if [condition] throws, then that exception is
  /// rethrown. If [condition] doesn't throw then an [expect] exception is
  /// thrown.
  Future waitFor(condition(), {matcher: isNotNull,
      Duration timeout: defaultTimeout,
      Duration interval: defaultInterval}) async {
    expect(value, matcher) {
      if (matcher is! Matcher) {
        matcher = equals(matcher);
      }

      var matchState = {};
      if (matcher.matches(value, matchState)) {
        return;
      }
      var desc = new StringDescription()
        ..add('Expected: ')
        ..addDescriptionOf(matcher)
        ..add('\n')
        ..add('  Actual: ')
        ..addDescriptionOf(value)
        ..add('\n');

      var mismatchDescription = new StringDescription();
      matcher.describeMismatch(value, mismatchDescription, matchState);
      if (mismatchDescription.length > 0) {
        desc.add('   Which: ${mismatchDescription}\n');
      }
      throw new Exception(desc.toString());
    }

    var endTime = now.add(timeout);
    while (true) {
      try {
        var value = await condition();
        expect(value, matcher);
        return value;
      } catch (e) {
        if (now.isAfter(endTime)) {
          rethrow;
        } else {
          await sleep(interval);
        }
      }
    }
  }
}

class Lock {
  Completer _lock;

  Future acquire() async {
    while (isHeld) {
      await _lock.future;
    }
    _lock = new Completer();
  }

  void release() {
    if (!isHeld) {
      throw new StateError('No lock to release');
    }
    _lock.complete();
    _lock = null;
  }

  bool get isHeld => _lock != null;
}
