(*
 *    _  _   ____                         _  
 *  _| || |_/ ___|  ___ _ __  _ __   ___ | | 
 * |_  ..  _\___ \ / _ \ '_ \| '_ \ / _ \| | 
 * |_      _|___) |  __/ |_) | |_) | (_) |_| 
 *   |_||_| |____/ \___| .__/| .__/ \___/(_) 
 *                     |_|   |_|             
 *
 * Personal Social Web.
 *
 * webfinger_test.ml
 *
 * 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/>.
 *)

open Seppo_lib

let test_uri_from_string () =
  Logr.debug (fun m -> m "%s.%s" "webfinger" "uri_from_string");
  Uri.make ~scheme:Webfinger.scheme
    ~userinfo:"a:b/c" ~host:"d.e" ()
  |> Uri.to_string
  |> Assrt.equals_string __LOC__ "acct://a:b%2Fc@d.e";
  "mailto:demo@d.seppo.social"
  |> Uri.of_string
  |> Uri.host
  |> Option.value ~default:"-"
  |> Assrt.equals_string __LOC__ "-";

  "acct:ab/c@d.e"
  |> Webfinger.of_string
  |> Webfinger.to_string
  |> Assrt.equals_string __LOC__ "acct:ab%2Fc@d.e";
  "acct:ab/c@d.e"
  |> Webfinger.of_string
  |> Webfinger.well_known_uri
  |> Result.get_ok
  |> Uri.host
  |> Option.value ~default:"-"
  |> Assrt.equals_string __LOC__ "d.e";
  "acct:ab/c@d.e"
  |> Webfinger.of_string
  |> Webfinger.well_known_uri
  |> Result.get_ok
  |> Uri.to_string
  |> Assrt.equals_string __LOC__ "https://d.e/.well-known/webfinger?resource=acct:ab%252Fc@d.e";
  "acct:demo@d.seppo.social"
  |> Webfinger.of_string
  |> Webfinger.well_known_uri
  |> Result.get_ok
  |> Uri.host
  |> Option.value ~default:"-"
  |> Assrt.equals_string __LOC__ "d.seppo.social";
  "@a@b.c"
  |> Webfinger.of_string
  |> Webfinger.to_string
  |> Assrt.equals_string __LOC__ "acct:a@b.c";
  "a@b.c"
  |> Webfinger.of_string
  |> Webfinger.to_string
  |> Assrt.equals_string __LOC__ "acct:a@b.c";
  "http://a@b.c"
  |> Webfinger.of_string
  |> Webfinger.to_string
  |> Assrt.equals_string __LOC__ "http://a@b.c"

let test_handle () =
  Logr.debug (fun m -> m "%s.%s" "webfinger" "handle");
  let open Webfinger.Client in
  (Localpart "uh", Domainpart "ah.oh")
  |> to_short
  |> Assrt.equals_string __LOC__ "uh@ah.oh";

  (match "uh@ah.oh" |> Webfinger.Client.from_string with
   | Ok (Localpart "uh", Domainpart "ah.oh") -> assert true
   | Ok _ -> Assrt.equals_string __LOC__ "h" "i"
   | Error e -> Assrt.equals_string __LOC__ "" e
  );

  let Rfc7565 u = "ok@example.com"
                  |> Webfinger.Client.from_string
                  |> Result.get_ok
                  |> Webfinger.Client.to_rfc7565 in
  u |> Uri.to_string
  |> Assrt.equals_string __LOC__ "acct://ok@example.com";

  (match Webfinger.("@ok@example.com" |> of_string |> Client.from_uri) with
   | Ok (Localpart "ok", Domainpart "example.com") -> assert true
   | Ok _ -> Assrt.equals_string __LOC__ "h" "i"
   | Error e -> Assrt.equals_string __LOC__ "" e
  );

  let u = "@ok@example.com"
          |> Webfinger.of_string
          |> Webfinger.Client.from_uri 
          |> Result.get_ok in
  u |> Webfinger.Client.to_string
  |> Assrt.equals_string __LOC__ "acct:ok@example.com"

let test_webfinger () =
  Logr.debug (fun m -> m "webfinger");
  Webfinger.jsonm (Auth.Uid "usr", Uri.of_string "scheme://example.com/p/a/t/h/")
  |> Result.get_ok
  |> Ezjsonm.value_to_string ~minify:false
  |> Assrt.equals_string __LOC__
    {|{
  "subject": "acct:usr@example.com",
  "links": [
    {
      "href": "scheme://example.com/p/a/t/h/activitypub/actor.jsa",
      "rel": "self",
      "type": "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
    },
    {
      "href": "scheme://example.com/p/a/t/h/",
      "rel": "http://webfinger.net/rel/profile-page",
      "type": "text/html"
    },
    {
      "href": "scheme://example.com/p/a/t/h/o/p/",
      "rel": "alternate",
      "type": "application/atom+xml"
    },
    {
      "rel": "http://ostatus.org/schema/1.0/subscribe",
      "template": "scheme://example.com/p/a/t/h/seppo.cgi/activitypub/actor.xml?id={uri}"
    }
  ]
}|};
  assert true

let test_decode () =
  Logr.debug (fun m -> m "webfinger_decode");
  let j = File.in_channel "data/webfinger/gnusocial.json" Ezjsonm.value_from_channel in
  let q = As2_vocab.Decode.Webfinger.query_result j |> Result.get_ok in
  q.subject |> Assrt.equals_string __LOC__ "acct:administrator@gnusocial.net";
  As2_vocab.Encode.Webfinger.query_result ~base:Uri.empty q
  |> Ezjsonm.value_to_string ~minify:false
  |> Assrt.equals_string __LOC__ {|{
  "subject": "acct:administrator@gnusocial.net",
  "aliases": [
    "https://gnusocial.net/index.php/user/1",
    "https://gnusocial.net/administrator",
    "https://gnusocial.net/user/1",
    "https://gnusocial.net/index.php/administrator"
  ],
  "links": [
    {
      "href": "https://gnusocial.net/administrator",
      "rel": "http://webfinger.net/rel/profile-page",
      "type": "text/html"
    },
    {
      "rel": "http://ostatus.org/schema/1.0/subscribe",
      "template": "https://gnusocial.net/main/remotefollowsub?profile={uri}"
    },
    {
      "href": "https://gnusocial.net/index.php/user/1",
      "rel": "self",
      "type": "application/activity+json"
    }
  ]
}|};
  let j = File.in_channel "data/webfinger/pleroma.json" Ezjsonm.value_from_channel in
  let q = j |> As2_vocab.Decode.Webfinger.query_result |> Result.get_ok in
  q.subject |> Assrt.equals_string __LOC__ "acct:gabek@social.gabekangas.com";
  assert true

let test_sift () =
  Logr.debug (fun m -> m "webfinger_test.test_webfinger_sift");
  let base = Uri.of_string "https://example.com/sub/" in
  let p = Webfinger.make (Auth.Uid "usr", base) in
  p.links
  |> As2_vocab.Types.Webfinger.profile_page
  |> Option.get
  |> Uri.to_string
  |> Assrt.equals_string __LOC__ ".";
  p.links
  |> As2_vocab.Types.Webfinger.self_link
  |> Option.get
  |> Uri.to_string
  |> Assrt.equals_string __LOC__ "activitypub/actor.jsa";
  p  
  |> As2_vocab.Encode.Webfinger.query_result ~base
  |> Ezjsonm.value_to_string ~minify:false
  |> Assrt.equals_string __LOC__ {|{
  "subject": "acct:usr@example.com",
  "links": [
    {
      "href": "https://example.com/sub/activitypub/actor.jsa",
      "rel": "self",
      "type": "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
    },
    {
      "href": "https://example.com/sub/",
      "rel": "http://webfinger.net/rel/profile-page",
      "type": "text/html"
    },
    {
      "href": "https://example.com/sub/o/p/",
      "rel": "alternate",
      "type": "application/atom+xml"
    },
    {
      "rel": "http://ostatus.org/schema/1.0/subscribe",
      "template": "https://example.com/sub/seppo.cgi/activitypub/actor.xml?id={uri}"
    }
  ]
}|}

let () =
  Unix.chdir "../../../test/";
  test_uri_from_string ();
  test_handle ();
  test_webfinger ();
  test_sift ();
  test_decode ();
  assert true

