// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

import Foundation

public struct Context {
  internal var handle:ContextHandle {
    didSet {
      log.debug("Updated context \(self)")
    }
  }
  private var _isCancelled:Bool = false
  private var _isCancellable:Bool = false
  private var dirty:ContextFeatures = []
  public var userInfo:[String: Any] = [:]

  internal init(handle:ContextHandle) {
    self.handle = handle
  }

  internal init(handle:ContextHandle, existingDeadline:NSDate?, isCancellable:Bool) {
    self.handle = handle
    self.deadline = existingDeadline
    self._isCancellable = isCancellable
  }

  public mutating func client() throws -> Client {
    try updateHandleIfNeeded()
    return Client(defaultContext: self)
  }

  public var deadline:NSDate? {
    didSet {
      guard oldValue != deadline else { return }
      guard deadline != nil else {
        log.warning("Cannot undo a deadline once one has been set. Instead mutate the root context. This will no-op.")
        deadline = oldValue // TODO Verify that the following didSet won't be a problem
        return
      }
      //      guard oldValue == nil || deadline!.isBefore(oldValue!) else {
      //        log.warning("Cannot set a deadline that is after the old value. Instead mutate the root context. This will no-op.")
      //        deadline = oldValue // TODO Verify that the following didSet won't be a problem
      //        return
      //      }
      dirty.insert(ContextFeatures.Deadline)
    }
  }

  public var isCancelled:Bool { return _isCancelled }

  public var isCancellable:Bool {
    get {
      return !_isCancelled && (_isCancellable || dirty.contains(ContextFeatures.Cancellable))
    }
    set {
      guard _isCancellable != newValue else { return }
      guard newValue == true else {
        log.warning("Cannot set something as not cancellable once it already is marked as such. No-op.")
        return
      }
      // This shouldn't be possible given we were marked as not cancellable previously.
      guard !_isCancelled else {
        log.warning("Already cancelled, so this is a no-op.")
        return
      }
      dirty.insert(ContextFeatures.Cancellable)
    }
  }

  /// Cancels all associated RPC with this context and renders it unusable. Call newContext afterwards
  /// to get a similar context that is workable.
  ///
  /// If this context is not cancellable (it has already been cancelled, or a deadline/timeout
  /// was never set), then this will throw a ContextError.
  ///
  /// If it does not throw right away, the promise will never fail.
  private static let outstandingCancels = GoPromises<Void>(timeout: nil)
  public mutating func cancel() throws -> Promise<Void> {
    guard !_isCancelled else { throw ContextError.ContextIsAlreadyCancelled }
    guard _isCancellable else { throw ContextError.ContextNotCancellable }
    _isCancelled = true
    let (asyncId, p) = Context.outstandingCancels.newPromise()
    swift_io_v_v23_context_CancelableVContext_nativeCancelAsync(handle.goHandle, asyncId, { asyncId in
      if let p = Context.outstandingCancels.getAndDeleteRef(asyncId) {
        RunOnMain {
          do {
            try p.resolve()
          } catch let e {
            log.warning("Unable to resolve cancel async promise: \(e)")
          }
        }
      }
    })
    return p
  }

  internal mutating func updateHandleIfNeeded() throws {
    if (_isCancelled) {
      throw ContextError.ContextIsAlreadyCancelled
    }

    if dirty.contains(ContextFeatures.Deadline) {
      try updateHandleForDeadline()
    }

    if dirty.contains(ContextFeatures.Cancellable) {
      try updateHandleForCancellable()
    }
  }

  private mutating func updateHandleForDeadline() throws {
    guard let deadline = deadline else {
      fatalError("Deadline was assumed to not be nil here, yet was marked as dirty")
    }
    let goHandle = try SwiftVError.catchAndThrowError { errPtr in
      return swift_io_v_v23_context_VContext_nativeWithDeadline(
        self.handle.goHandle, deadline.timeIntervalSince1970, errPtr)
    }
    _isCancellable = true
    dirty.remove(ContextFeatures.Deadline)
    handle = ContextHandle(goHandle)
  }

  private mutating func updateHandleForCancellable() throws {
    let goHandle = try SwiftVError.catchAndThrowError { errPtr in
      return swift_io_v_v23_context_VContext_nativeWithCancel(
        self.handle.goHandle, errPtr)
    }
    _isCancellable = true
    dirty.remove(ContextFeatures.Cancellable)
    handle = ContextHandle(goHandle)
  }

  internal mutating func run<T>(@autoclosure block: () throws ->T) throws -> T {
    guard !_isCancelled else { throw ContextError.ContextIsAlreadyCancelled }
    try updateHandleIfNeeded()
    return try block()
  }
}

public class ContextHandle: CustomStringConvertible, CustomDebugStringConvertible {
  internal let goHandle:GoContextHandle

  internal init(_ goHandle:GoContextHandle) {
    self.goHandle = goHandle
  }

  deinit {
    if goHandle != 0 {
      swift_io_v_v23_context_VContext_nativeFinalize(goHandle)
    }
  }

  public var description: String { return "[ContextHandle \(goHandle)]" }
  public var debugDescription: String { return "[ContextHandle handle=\(goHandle)]" }
}

struct ContextFeatures: OptionSetType {
  let rawValue: Int
  static let Deadline = ContextFeatures(rawValue: 1 << 1)
  static let Cancellable = ContextFeatures(rawValue: 1 << 2)
  // Make sure to add any new ones to updateHandleIfNeeded
  // Unforutnately Swift doesn't yet give us a good enum-style way to iterate on this and prevent
  // future bugs.
}

enum ContextError: ErrorType {
  case ContextNotCancellable
  case ContextIsAlreadyCancelled
}
