(*
 *    _  _   ____                         _  
 *  _| || |_/ ___|  ___ _ __  _ __   ___ | | 
 * |_  ..  _\___ \ / _ \ '_ \| '_ \ / _ \| | 
 * |_      _|___) |  __/ |_) | |_) | (_) |_| 
 *   |_||_| |____/ \___| .__/| .__/ \___/(_) 
 *                     |_|   |_|             
 *
 * Personal Social Web.
 *
 * Copyright (C) The #Seppo contributors. All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *)

(* https://caml.inria.fr/pub/docs/manual-ocaml/libref/Sys.html *)

let ( >>= ) = Result.bind
let ( let* ) = Result.bind

let err i msgs =
  let exe = Filename.basename Sys.executable_name in
  msgs |> List.cons exe |> String.concat ": " |> prerr_endline;
  i

open Seppo_lib

let webfinger acct =
  let w = acct |> Webfinger.well_known_uri in
  (try w |> Webfinger.Client.http_get
   with
     Ezjsonm.Parse_error (_, e) ->
     Logr.err (fun m -> m "%s failed to decipher %a" E.e9001 Uri.pp w);
     Lwt.return (Error e))
  |> Lwt_main.run

(* TODO add more compliance rules. Check pk. *)
let actor ?(key = None) u =
  u
  |> Ap.Actor.http_get ~key
  |> Lwt_main.run
    (*
    >>= As2.Profile.pubkey_pem
    >>= As2.PubKeyPem.pub_from_pem
    >>= As2.PubKeyPem.check
 *)

let exec (args : string list) =
  let print_version oc =
    let exe = Filename.basename Sys.executable_name in
    Printf.fprintf oc "%s: https://Seppo.mro.name/v/%s+%s\n" exe Version.dune_project_version Version.git_sha;
    0
  and print_help oc =
    let _exe = Filename.basename Sys.executable_name in
    Printf.fprintf oc
      "\n\
       Query AP servers.\n\n\
       If run from commandline:\n\n\
       OPTIONS\n\n\
      \  --help, -h\n\
      \      print this help\n\n\
      \  --version, -V\n\
      \      print version\n\n\
       COMMANDS\n\n\
      \  webfinger alice@example.org\n\
      \      the webfinger json parsed and re-written.\n\n\
      \  actor https://example.org/actors/alice\n\
      \      the AP profile page parsed and re-written.\n\n\
      \  doap\n\
      \      show 'description of a project'\n\n";
    0
  and oc = stdout in
  let tail s = function
    | Error e ->
      Logr.err (fun m -> m "%s '%s': %s" E.e1006 s e);
      1
    | Ok _ ->
      Logr.info (fun m -> m "%s." s);
      0
  in
  match args with
  | [ _; "-h" ] | [ _; "--help" ] -> print_help oc
  | [ _; "-V" ] | [ _; "--version" ] -> print_version oc
  | [ _; "doap" ] ->
    (match "doap.rdf" |> Res.read with
     | Some v -> Printf.fprintf oc "%s" v
     | None -> ());
    0
  | [ _; "webfinger"; acct ] ->
    (let* q = acct
              |> Rfc7565.of_string
              |> Result.get_ok
              |> webfinger in
     q
     |> As2_vocab.Encode.Webfinger.query_result ~base:Uri.empty
     |> Ezjsonm.value_to_channel stdout;
     Ok q)
    |> tail "webfinger"
  | [ _; "actor"; url] ->
    (let* p = url |> Uri.of_string |> actor in
     let lang = As2_vocab.Constants.ActivityStreams.und in
     p
     |> As2_vocab.Encode.person ~lang ~base:Uri.empty
     |> Ezjsonm.value_to_channel stdout;
     Ok p)
    |> tail "actor"
  | _ -> err 2 [ "get help with -h" ]
