// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//
//  XCTNSPredicateExpectation.swift
//

/// Expectation subclass for waiting on a condition defined by an NSPredicate and an optional object.
open class XCTNSPredicateExpectation: XCTestExpectation {

    /// A closure to be invoked whenever evaluating the predicate against the object returns true.
    ///
    /// - Returns: `true` if the expectation should be fulfilled, `false` if it should not.
    ///
    /// - SeeAlso: `XCTNSPredicateExpectation.handler`
    public typealias Handler = () -> Bool

    private let queue = DispatchQueue(label: "org.swift.XCTest.XCTNSPredicateExpectation")

    /// The predicate used by the expectation.
    open private(set) var predicate: NSPredicate

    /// The object against which the predicate is evaluated, if any. Default is nil.
    open private(set) var object: Any?

    private var _handler: Handler?

    /// Handler called when evaluating the predicate against the object returns true. If the handler is not
    /// provided, the first successful evaluation will fulfill the expectation. If the handler provided, the
    /// handler will be queried each time the notification is received to determine whether the expectation
    /// should be fulfilled or not.
    open var handler: Handler? {
        get {
            return queue.sync { _handler }
        }
        set {
            dispatchPrecondition(condition: .notOnQueue(queue))
            queue.async { self._handler = newValue }
        }
    }

    private let runLoop = RunLoop.current
    private var timer: Timer?
    private let evaluationInterval = 0.01

    /// Initializes an expectation that waits for a predicate to evaluate as true with an optionally specified object.
    ///
    /// - Parameter predicate: The predicate to evaluate.
    /// - Parameter object: An optional object to evaluate `predicate` with. Default is nil.
    /// - Parameter file: The file name to use in the error message if
    ///   expectations are not met before the wait timeout. Default is the file
    ///   containing the call to this method. It is rare to provide this
    ///   parameter when calling this method.
    /// - Parameter line: The line number to use in the error message if the
    ///   expectations are not met before the wait timeout. Default is the line
    ///   number of the call to this method in the calling file. It is rare to
    ///   provide this parameter when calling this method.
    public init(predicate: NSPredicate, object: Any? = nil, file: StaticString = #file, line: Int = #line) {
        self.predicate = predicate
        self.object = object
        let description = "Expect predicate `\(predicate)`" + (object.map { " for object \($0)" } ?? "")

        super.init(description: description, file: file, line: line)
    }

    deinit {
        assert(timer == nil, "timer should be nil, indicates failure to call cleanUp() internally")
    }

    override func didBeginWaiting() {
        runLoop.perform {
            if self.shouldFulfill() {
                self.fulfill()
            } else {
                self.startPolling()
            }
        }
    }

    private func startPolling() {
        let timer = Timer(timeInterval: evaluationInterval, repeats: true) { [weak self] timer in
            guard let self = self else {
                timer.invalidate()
                return
            }

            if self.shouldFulfill() {
                self.fulfill()
                timer.invalidate()
            }
        }

        runLoop.add(timer, forMode: .defaultRunLoopMode)
        queue.async {
            self.timer = timer
        }
    }

    private func shouldFulfill() -> Bool {
        if predicate.evaluate(with: object) {
            if let handler = handler {
                if handler() {
                    return true
                }
                // We do not fulfill or invalidate the timer if the handler returns
                // false. The object is still re-evaluated until timeout.
            } else {
                return true
            }
        }

        return false
    }

    override func cleanUp() {
        queue.sync {
            if let timer = timer {
                timer.invalidate()
                self.timer = nil
            }
        }
    }

}

/// A closure to be invoked whenever evaluating the predicate against the object returns true.
///
/// - SeeAlso: `XCTNSPredicateExpectation.handler`
@available(*, deprecated, renamed: "XCTNSPredicateExpectation.Handler")
public typealias XCPredicateExpectationHandler = XCTNSPredicateExpectation.Handler
