(*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *)

type subscribe_mode =
  | All_changes
  | Defer_changes

type timeout = float option

type init_settings = {
  debug_logging: bool;
  defer_states: string list;  (** defer notifications while these states are asserted *)
  expression_terms: Hh_json.json list;  (** See watchman expression terms. *)
  mergebase_with: string;  (** symbolic commit to find changes against *)
  roots: File_path.t list;
  should_track_mergebase: bool;
  subscribe_mode: subscribe_mode;
  subscription_prefix: string;
  sync_timeout: int option;
}

type pushed_changes =
  (*
   * State name and metadata.
   *
   * For example:
   *   State name: "hg.update"
   * Metadata:
   *   {
   *    "partial":false,
   *    "rev":"780dab9ff0a01691c9b18a5ee1194810e555c78b",
   *    "distance":2,
   *    "status":"ok"
   *   }
   *
   * Note: The distance is HG Revision distance, not SVN revision distance.
   *)
  | State_enter of string * Hh_json.json option
  | State_leave of string * Hh_json.json option
  | Files_changed of {
      changes: SSet.t;
      changed_mergebase: bool option;
    }
  | Missed_changes of {
      prev_mergebase: string;
      mergebase: string;
      changes_since_mergebase: SSet.t;
    }

type failure =
  | Dead
  | Restarted

type env

val init : init_settings -> (env * SSet.t, string) Result.t Lwt.t

val recover_from_restart : env -> (env * pushed_changes, failure) Result.t Lwt.t

val get_changes : env -> (env * pushed_changes, failure) Result.t Lwt.t

val close : env -> unit Lwt.t

(* Expose some things for testing. *)
module Testing : sig
  type error_kind

  val get_test_env : unit -> env Lwt.t

  val test_settings : init_settings

  val transform_asynchronous_get_changes_response :
    env -> Hh_json.json -> (env * pushed_changes, error_kind) Result.t Lwt.t
end
