// 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
import SyncbaseCore

/// Syncbase is a storage system for developers that makes it easy to synchronize app data between
/// devices. It works even when devices are not connected to the Internet.
public enum Syncbase {
  // Constants
  static let DbName = "db"
  public static let UserdataSyncgroupName = "userdata__",
    UserdataInternalPrefix = "internal__/",
    UserdataInternalSyncgroupPrefix = UserdataInternalPrefix + "syncgroups/"
  // Initialization state
  static var isUnitTest = false
  static var didInit = false
  static var didPostLogin = false
  static var didStartShutdown = false
  // Main database.
  static var db: Database?
  // The userdata collection, created post-login.
  static var userdataCollection: Collection?
  // The handler for auto-joining invites that match our user's blessings. We keep it in a var
  // in order to remove it on `shutdown`.
  static var autojoinInviteHandler: SyncbaseCore.SyncgroupInvitesScanHandler?
  // Options for opening a database.
  static var cloudName: String?
  static var cloudBlessing: String?
  static var disableSyncgroupPublishing = false
  static var disableUserdataSyncgroup = false
  static var mountPoints: [String] = []
  /// Queue used to dispatch all asynchronous callbacks. Defaults to main.
  public static var queue: dispatch_queue_t {
    // Map directly to SyncbaseCore.
    get {
      return SyncbaseCore.Syncbase.queue
    }
    set(queue) {
      SyncbaseCore.Syncbase.queue = queue
    }
  }

  static public var defaultRootDir: String {
    return NSFileManager.defaultManager()
      .URLsForDirectory(.ApplicationSupportDirectory, inDomains: .UserDomainMask)[0]
      .URLByAppendingPathComponent("Syncbase")
      .path!
  }

  static var publishSyncbaseName: String? {
    if disableSyncgroupPublishing {
      return nil
    }
    if usesCloud {
      return cloudName
    }
    return nil
  }

  static var usesCloud: Bool {
    return cloudName != nil && cloudBlessing != nil
  }

  /// Starts Syncbase if needed; creates default database if needed; performs create-or-join for
  /// "userdata" syncgroup if needed.
  ///
  /// The "userdata" collection is a per-user collection (and associated syncgroup) for data that
  /// should automatically get synced across a given user's devices. It has the following schema:
  /// - `internal__/syncgroups/{encodedSyncgroupId}` -> `nil`
  /// - `internal__/ignoredInvites/{encodedSyncgroupId}` -> `nil`
  ///
  /// Cloud usage is optional. It can be used for initial bootstrapping and increased data
  /// availability. Apps that use a cloud will automatically synchronize data across all of the same
  /// user's devices. To allocate a cloud instance of Syncbase, visit https://sb-allocator.v.io/home
  /// to create your instance. There you'll be able to see the parameters for `cloudName` and
  /// `cloudBlessing` parameters. After that, please complete the following steps (until we the
  /// webpage includes similar functionality, see https://github.com/vanadium/issues/issues/1414):

  /// 1. Install Vanadium from https://vanadium.github.io/installation/
  ///
  /// 2. Install the principal & sb binaries
  /// `jiri go install v.io/...`
  ///
  /// 3. Create your principal
  /// `$JIRI_ROOT/release/go/bin/principal create $JIRI_ROOT/.v23creds`
  ///
  /// 4. Bless it via OAuth. On the Vanadium blessings page, just click bless.
  /// `$JIRI_ROOT/release/go/bin/principal -v23.credentials=$JIRI_ROOT/.v23creds seekblessings`
  ///
  /// 5. Create the shared database using the app client id blessing. Notice the , in the id...
  /// it's _blessing_,db
  /// `$JIRI_ROOT/release/go/bin/sb --v23.credentials=$JIRI_ROOT/.v23creds \
  /// -service=/ns.dev.v.io:8101/sb/syncbased-<SYNCBASEID> -create-if-absent=true \
  /// --db dev.v.io:o:<GOOGLE SIGNIN CLIENTID>,db`
  ///
  /// 6. At this point you can go to sb-allocator.v.io, click debug on your instance,
  /// click Syncbase in the upper right, then verify the database was created. You can't currently
  /// view the collections or syncgroups as the website is not authenticated to show them.
  ///
  /// - parameter rootDir:                     Where data should be persisted.
  /// - parameter cloudName:                   Name of the cloud. See https://sb-allocator.v.io/home
  /// - parameter cloudBlessing:               The cloud's blessing pattern. See https://sb-allocator.v.io/home
  /// - parameter mountPoints:                 // TODO(zinman): Get appropriate documentation on mountPoints
  /// - parameter disableSyncgroupPublishing:  **FOR ADVANCED USERS**. If true, syncgroups will not be published to the cloud peer.
  /// - parameter disableUserdataSyncgroup:    **FOR ADVANCED USERS**. If true, the user's data will not be synced across their devices.
  /// - parameter callback:                    Called on `Syncbase.queue` with either `Database` if successful, or an error if unsuccessful.
  public static func configure(
    // Default to Application Support/Syncbase.
    rootDir rootDir: String = defaultRootDir,
    cloudName: String? = nil,
    cloudBlessing: String? = nil,
    mountPoints: [String],
    disableSyncgroupPublishing: Bool = false,
    disableUserdataSyncgroup: Bool = false,
    queue: dispatch_queue_t = dispatch_get_main_queue()) throws {
      if Syncbase.didInit {
        throw SyncbaseError.AlreadyConfigured
      }
      Syncbase.cloudName = cloudName
      Syncbase.cloudBlessing = cloudBlessing
      Syncbase.mountPoints = mountPoints
      Syncbase.disableSyncgroupPublishing = disableSyncgroupPublishing
      Syncbase.disableUserdataSyncgroup = disableUserdataSyncgroup
      Syncbase.didPostLogin = false
      Syncbase.didStartShutdown = false
      // We don't need to set Syncbase.queue as it is a proxy for SyncbaseCore's queue, which is
      // set in the configure below.
      try SyncbaseError.wrap {
        try SyncbaseCore.Syncbase.configure(rootDir: rootDir, queue: queue)
      }
      // We use SyncbaseCore's isLoggedIn because this frameworks would fail as didInit hasn't
      // been set to true yet.
      if (SyncbaseCore.Syncbase.isLoggedIn) {
        do {
          try Syncbase.postLoginCreateDefaults()
        } catch {
          // If we get an exception after configuring the low-level API, make sure we shutdown
          // Syncbase so that any subsequent call to this configure method doesn't get a
          // SyncbaseError.AlreadyConfigured exception from SyncbaseCore.Syncbase.configure.
          Syncbase.shutdown()
          throw error
        }
      }
      Syncbase.didInit = true
  }

  /// Shuts down the Syncbase service. You must call configure again before any calls will work.
  public static func shutdown() {
    // We don't need to log/worry about the catch {} -- the exception is if we can't get a database
    // handle, which would happen if we haven't logged in, etc. The actual remove handler does not
    // throw any errors.
    do { try database().removeAllSyncgroupInviteHandlers() } catch { }
    do { try database().removeAllWatchChangeHandlers() } catch { }
    do { try database().removeAllInternalWatchChangeHandlers() } catch { }
    if let handler = autojoinInviteHandler {
      do { try database().coreDatabase.stopSyncgroupInvitesScan(handler) } catch { }
    }
    Syncbase.didStartShutdown = true
    SyncbaseCore.Syncbase.shutdown()
    Syncbase.didInit = false
    Syncbase.didPostLogin = false
  }

  private static func postLoginCreateDefaults() throws {
    let coreDb = try SyncbaseCore.Syncbase.database(Syncbase.DbName)
    let database = Database(coreDatabase: coreDb)
    try database.createIfMissing()
    userdataCollection = try database.createCollection(
      name: Syncbase.UserdataSyncgroupName, withoutSyncgroup: true)
    // We only create a userdata syncgroup if we use the cloud (or we're in a unit test).
    if (usesCloud || isUnitTest) && !Syncbase.disableUserdataSyncgroup {
      let syncgroup = try userdataCollection!.syncgroup()
      do {
        // TODO(zinman): Return (via throwing) if this fails because the cloud isn't accessible,
        // instead of it failing because a join isn't possible.
        try syncgroup.join()
      } catch {
        // The above join() will fail the first time the user logs in and we create the syncgroup
        // UNLESS another device of the same user is available to discovery (nearby or connected
        // via some network path). If so, then the join will work. In subsequent boots join() will
        // not throw and we won't re-attempt creation.
        try syncgroup.createIfMissing([userdataCollection!])
      }
      // TODO(zinman): Figure out when/how this can throw and if we should handle it better.
      try database.addInternalUserdataWatchChangeHandler(
        handler: WatchChangeHandler(
          onInitialState: onUserdataWatchChange,
          onChangeBatch: onUserdataWatchChange,
          onError: { err in
            if !Syncbase.didStartShutdown {
              NSLog("Syncbase - Error watching userdata syncgroups: %@", "\(err)")
            }
        }))
      // Auto-join syncgroups with the same blessings.
      autojoinInviteHandler = SyncbaseCore.SyncgroupInvitesScanHandler(onInvite: onSyncgroupInvite)
      try coreDb.scanForSyncgroupInvites(
        try database.databaseId.encode(),
        handler: autojoinInviteHandler!)
    }

    Syncbase.db = database
    Syncbase.didPostLogin = true
  }

  private static func onSyncgroupInvite(invite: SyncbaseCore.SyncgroupInvite) {
    // Auto-accept groups that have blessings that match our own.
    let syncgroupId = Identifier(coreId: invite.syncgroupId)
    guard invite.syncgroupId.blessing == (try? Principal.userBlessing()) &&
    // Ignore userdata syncgroup which is auto-joined if the blessings are correct in Go.
    invite.syncgroupId.name != Syncbase.UserdataSyncgroupName &&
    // Ignore syncgroups that have already been joined.
    !((try? Syncbase.syncgroupInUserdata(syncgroupId)) ?? false) else {
      return
    }
    do {
      let invite = SyncgroupInvite(coreInvite: invite)
      try database().acceptSyncgroupInvite(invite, callback: { (sg, err) in
        if err != nil {
          print("Unable to auto-join syncgroup \(sg) with user blessings: \(err)")
        }
      })
    } catch {
      print("Unable to auto-join syncgroup \(invite.syncgroupId) with user blessings: \(error)")
    }
  }

  private static func onUserdataWatchChange(changes: [WatchChange]) {
    for change in changes {
      guard let row = change.row where change.entityType == .Row && change.changeType == .Put else {
        continue
      }
      guard let syncgroupId = try? Identifier.decode(
        row.stringByReplacingOccurrencesOfString(Syncbase.UserdataInternalSyncgroupPrefix, withString: "")) else {
          print("Syncbase - Unable to decode userdata key: (row)")
          continue
      }
      do {
        let syncgroup = try Syncbase.database().syncgroup(syncgroupId)
        try syncgroup.join()
      } catch {
        NSLog("Syncbase - Error joining syncgroup \(syncgroupId): %@", "\(error)")
      }
    }
  }

  static func addSyncgroupToUserdata(syncgroupId: Identifier) throws {
    if !Syncbase.didInit {
      throw SyncbaseError.NotConfigured
    }
    if !Syncbase.didPostLogin {
      throw SyncbaseError.NotLoggedIn
    }
    guard let userdataCollection = Syncbase.userdataCollection else {
      throw SyncbaseError.IllegalArgument(detail: "No user data collection")
    }
    try userdataCollection.put(try Syncbase.UserdataInternalSyncgroupPrefix + syncgroupId.encode(), value: NSData())
  }

  static func syncgroupInUserdata(syncgroupId: Identifier) throws -> Bool {
    if !Syncbase.didInit {
      throw SyncbaseError.NotConfigured
    }
    if !Syncbase.didPostLogin {
      throw SyncbaseError.NotLoggedIn
    }
    guard let userdataCollection = Syncbase.userdataCollection else {
      throw SyncbaseError.IllegalArgument(detail: "No user data collection")
    }
    return try userdataCollection.exists(try Syncbase.UserdataInternalSyncgroupPrefix + syncgroupId.encode())
  }

  /// Returns the shared database handle. Must have already called `configure` and be logged in,
  /// otherwise this will throw a `SyncbaseError.NotConfigured` or `SyncbaseError.NotLoggedIn`
  /// error.
  public static func database() throws -> Database {
    if !Syncbase.didInit {
      throw SyncbaseError.NotConfigured
    }
    guard let db = Syncbase.db where Syncbase.didPostLogin else {
      throw SyncbaseError.NotLoggedIn
    }
    return db
  }

  public typealias LoginCallback = (err: SyncbaseError?) -> Void

  /// Authorize using an oauth token. Right now only Google OAuth token is supported
  /// (you should use the Google Sign In SDK to get this).
  ///
  /// You must login and have valid credentials before you can call `database()` to perform any
  /// operation.
  ///
  /// Calls `callback` on `Syncbase.queue` with any error that occured, or nil on success.
  public static func login(credentials: GoogleOAuthCredentials, callback: LoginCallback) {
    SyncbaseCore.Syncbase.login(
      SyncbaseCore.GoogleOAuthCredentials(token: credentials.token),
      callback: { err in
        guard err == nil else {
          callback(err: SyncbaseError(coreError: err!))
          return
        }
        // postLoginCreateDefaults can be blocking when performing create-or-join. Run on
        // a background queue to prevent blocking from the Go callback.
        dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)) {
          var callbackErr: SyncbaseError?
          do {
            try postLoginCreateDefaults()
          } catch let e as SyncbaseError {
            callbackErr = e
          } catch {
            preconditionFailure("Unsupported ErrorType: \(error)")
          }
          dispatch_async(Syncbase.queue) {
            callback(err: callbackErr)
          }
        }
    })
  }

  public static func isLoggedIn() throws -> Bool {
    if !Syncbase.didInit {
      throw SyncbaseError.NotConfigured
    }
    return SyncbaseCore.Syncbase.isLoggedIn
  }

  public static func loggedInUser() -> User? {
    if let bp = try? personalBlessingString(),
      alias = aliasFromBlessingPattern(bp) {
        return User(alias: alias)
    }
    return nil
  }

  static var neighborhoodScans: [ScanNeighborhoodForUsersHandler: SyncbaseCore.NeighborhoodScanHandler] = [:]
  static let neighborhoodScansMu = NSLock()

  /// Scans the neighborhood for nearby users.
  ///
  /// - parameter handler: The handler for to call when a User is found or lost.
  /// Callbacks are called on `Syncbase.queue`.
  public static func startScanForUsersInNeighborhood(handler: ScanNeighborhoodForUsersHandler) throws {
    let coreHandler = NeighborhoodScanHandler(onPeer: { peer in
      guard let alias = aliasFromBlessingPattern(peer.blessings) else {
        NSLog("Syncbase - Could not get blessings from pattern %@", "\(peer.blessings)")
        return
      }
      let user = User(alias: alias)
      dispatch_async(Syncbase.queue) {
        if peer.isLost {
          handler.onLost(user)
        } else {
          handler.onFound(user)
        }
      }
    })
    try SyncbaseError.wrap {
      try Neighborhood.startScan(coreHandler)
    }
    neighborhoodScansMu.lock()
    neighborhoodScans[handler] = coreHandler
    neighborhoodScansMu.unlock()
  }

  /// Stops the handler from receiving new neighborhood scan updates.
  ///
  /// - parameter handler: The original handler passed to a started scan.
  public static func stopScanForUsersInNeighborhood(handler: ScanNeighborhoodForUsersHandler) {
    neighborhoodScansMu.lock()
    if let coreHandler = neighborhoodScans[handler] {
      Neighborhood.stopScan(coreHandler)
      neighborhoodScans.removeValueForKey(handler)
    }
    neighborhoodScansMu.unlock()
  }

  /// Stops all existing scanning handlers from receiving new neighborhood scan updates.
  public static func stopAllScansForUsersInNeighborhood() {
    neighborhoodScansMu.lock()
    for coreHandler in neighborhoodScans.values {
      Neighborhood.stopScan(coreHandler)
    }
    neighborhoodScans.removeAll()
    neighborhoodScansMu.unlock()
  }

  /// Advertises the logged in user's presence to the target set of users who must be around them.
  ///
  /// - parameter usersWhoCanSee: The set of users who are allowed to find this user. If empty
  /// then everyone can see the advertisement.
  public static func startAdvertisingPresenceInNeighborhood(usersWhoCanSee: [User] = []) throws {
    let visibility = try usersWhoCanSee.map { return try blessingPatternFromAlias($0.alias) }
    try SyncbaseError.wrap {
      try Neighborhood.startAdvertising(visibility)
    }
  }

  /// Stops advertising the presence of the logged in user so that they can no longer be found.
  public static func stopAdvertisingPresenceInNeighborhood() throws {
    try SyncbaseError.wrap {
      try Neighborhood.stopAdvertising()
    }
  }

  /// Returns true iff this person appears in the neighborhood.
  public static func isAdvertisingPresenceInNeighborhood() -> Bool {
    return Neighborhood.isAdvertising()
  }
}

public struct ScanNeighborhoodForUsersHandler: Hashable {
  public let onFound: User -> Void
  public let onLost: User -> Void
  // This internal-only variable allows us to test ScanNeighborhoodForUsersHandler structs for equality.
  // This cannot be done otherwise as function calls cannot be tested for equality.
  // Equality/hashValue is used to keep the set of all handlers in use.
  let uniqueId = OSAtomicIncrement32(&uniqueIdCounter)

  public init(onFound: User -> Void, onLost: User -> Void) {
    self.onFound = onFound
    self.onLost = onLost
  }

  public var hashValue: Int {
    return uniqueId.hashValue
  }
}

public func == (lhs: ScanNeighborhoodForUsersHandler, rhs: ScanNeighborhoodForUsersHandler) -> Bool {
  return lhs.uniqueId == rhs.uniqueId
}
