(**************************************************************************)
(*                                BELENIOS                                *)
(*                                                                        *)
(*  Copyright © 2024-2024 Inria                                           *)
(*                                                                        *)
(*  This program is free software: you can redistribute it and/or modify  *)
(*  it under the terms of the GNU Affero General Public License as        *)
(*  published by the Free Software Foundation, either version 3 of the    *)
(*  License, or (at your option) any later version, with the additional   *)
(*  exemption that compiling, linking, and/or using OpenSSL is allowed.   *)
(*                                                                        *)
(*  This program is distributed in the hope that it will be useful, but   *)
(*  WITHOUT ANY WARRANTY; without even the implied warranty of            *)
(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *)
(*  Affero General Public License for more details.                       *)
(*                                                                        *)
(*  You should have received a copy of the GNU Affero General Public      *)
(*  License along with this program.  If not, see                         *)
(*  <http://www.gnu.org/licenses/>.                                       *)
(**************************************************************************)

(** {1 Predefined types} *)

type weight = abstract wrap <ocaml module="Belenios_core.Common_types.Weight">
type uuid = string wrap <ocaml module="Belenios_core.Common_types.Uuid">
type hash = string wrap <ocaml module="Belenios_core.Common_types.Hash">
type 'a proof <ocaml predef from="Belenios_core.Serializable"> = abstract
type 'a template <ocaml predef from="Belenios_core.Serializable"> = abstract
type 'a cert <ocaml predef from="Belenios_core.Serializable"> = abstract
type 'a polynomial <ocaml predef from="Belenios_core.Serializable"> = abstract
type 'a vinput <ocaml predef from="Belenios_core.Serializable"> = abstract

(** {1 Web-specific types} *)

type user = {
  domain : string;
  name : string;
} <ocaml field_prefix="user_">

type auth_config = {
  auth_system : string;
  auth_instance : string;
  auth_config : (string * string) list;
  ?auth_portal : string option;
}

type sealed = {
  ?date_open : float option;
  ?date_close : float option;
  ?date_publish : float option;
}

type sealing_op =
  [ Seal of sealed
  | Unseal ]

type sealing_event = {
  date : float;
  op : sealing_op;
}

type cred_authority_info <ocaml predef from="Belenios_web_api.Serializable"> = abstract
type ('a, 'b) credentials_certificate <ocaml predef from="Belenios_web_api.Serializable"> = abstract

type metadata = {
  owners: int list;
  ?auth_config: auth_config list option;
  ?cred_authority : string option;
  ?cred_authority_info : cred_authority_info option;
  ?trustees : string list option;
  ?languages : string list option;
  ?contact : string option;
  ?booth_version : int option;
  ?billing_request : string option;
  ?sealed : bool option;
  ?logo : string option;
} <ocaml field_prefix="e_">

type extended_record = {
  username : string;
  date : float;
  credential : string;
} <ocaml field_prefix="r_">

type credential_mapping = {
  credential : string;
  ?ballot : string option;
} <ocaml field_prefix="c_">

type election_state =
  [ Draft
  | Open
  | Closed
  | Shuffling
  | EncryptedTally
  | Tallied
  | Archived
  ]

(** {1 Types related to elections being prepared} *)

type voter <ocaml predef from="Belenios_core.Serializable"> = abstract

type draft_voter = {
  id <ocaml mutable> : voter;
} <ocaml field_prefix="sv_">

type 'a draft_trustee = {
  id : string;
  token : string;
  public_key <ocaml mutable> : string;
  ?private_key : 'a option;
  ?name : string option;
} <ocaml field_prefix="st_">

type 'a draft_threshold_trustee = {
  id : string;
  token : string;
  ?step <ocaml mutable> : int option;
  ?cert <ocaml mutable> : 'a cert option;
  ?polynomial <ocaml mutable> : 'a polynomial option;
  ?vinput <ocaml mutable> : 'a vinput option;
  ?voutput <ocaml mutable> : string option;
  ?name : string option;
} <ocaml field_prefix="stt_">

type 'a draft_basic_params = {
  trustees <ocaml mutable> : 'a draft_trustee list;
} <ocaml field_prefix="dbp_">

type 'a draft_threshold_params = {
  ?threshold <ocaml mutable> : int option;
  trustees <ocaml mutable> : 'a draft_threshold_trustee list;
  ?parameters <ocaml mutable> : string option;
  ?error <ocaml mutable> : string option;
} <ocaml field_prefix="dtp_">

type 'a draft_trustees =
  [ Basic of 'a draft_basic_params
  | Threshold of 'a draft_threshold_params
  ]

type 'question raw_draft_election = {
  version : int;
  owners : int list;
  group <ocaml mutable> : string;
  voters <ocaml mutable> : draft_voter list;
  questions <ocaml mutable> : 'question template;
  trustees <ocaml mutable> : abstract draft_trustees;
  metadata <ocaml mutable> : metadata;
  public_creds : string;
  public_creds_received <ocaml mutable> : bool;
  ?public_creds_certificate <ocaml mutable> : (abstract, abstract) credentials_certificate option;
  creation_date : float;
  ?administrator <ocaml mutable> : string option;
  ~credential_authority_visited <ocaml default="false" mutable> : bool;
  ~voter_authentication_visited <ocaml default="false" mutable> : bool;
  ~trustees_setup_step <ocaml default="1" mutable> : int;
  ~pending_credentials <ocaml default="false" mutable> : bool;
  ~private_creds_downloaded <ocaml default="false" mutable> : bool;
} <ocaml field_prefix="se_">

(** {1 Administrator accounts} *)

type account = {
    id : int;
    name : string;
    ?email : string option;
    last_connected : float;
    authentications : user list;
    ?consent : float option;
    ?capabilities : int option;
    ?language : string option;
    ~default_voter_languages <ocaml default="[]"> : string list;
    ~default_contact <ocaml default="\"\""> : string;
    ?voters_limit : int option;
}

(** {1 Views} *)

type username_or_address = [ Username | Address ]

type voters_config = {
  has_explicit_weights : bool;
  username_or_address : username_or_address;
  nb_voters : int;
}

type password_record = {
  username : string;
  salt : string;
  hashed : string;
  ?address : string option;
}

(** {1 Running elections} *)

type election_dates = {
  creation : float;
  ?finalization : float option;
  ?tally : float option;
  ?archive : float option;
  ?last_mail : float option;
  ?auto_open : float option;
  ?auto_close : float option;
  ?publish : float option;
  ?grace_period : float option;
} <ocaml field_prefix="e_date_">

type election_records = (string * float) list <json repr="object">

type decryption_tokens = string list

type skipped_shufflers = string list

type shuffle_token = {
    trustee : string;
    token : string;
    trustee_id : int;
    ?name : string option;
} <ocaml field_prefix="tk_">

type shuffle_state = {
    skipped : skipped_shufflers;
    ?token : shuffle_token option;
}

type some_state_state =
  [ Decryption of decryption_tokens
  | Shuffle of shuffle_state
  ]

type state_state = some_state_state nullable

type credentials_seed = {
    seed : string;
    token : string;
}

type credentials_params = {
    belenios_url : string;
    version : int;
    group : string;
    certificate : (abstract, abstract) credentials_certificate;
}

type 'a encrypted_msg <ocaml predef from="Belenios_core.Serializable"> = abstract

type 'a credentials_record = {
    credential : 'a;
    ?address : string option;
    ?weight : weight option;
}

type credentials_records =
  (string * abstract encrypted_msg credentials_record) list
  <json repr="object">
