(*
 *    _  _   ____                         _  
 *  _| || |_/ ___|  ___ _ __  _ __   ___ | | 
 * |_  ..  _\___ \ / _ \ '_ \| '_ \ / _ \| | 
 * |_      _|___) |  __/ |_) | |_) | (_) |_| 
 *   |_||_| |____/ \___| .__/| .__/ \___/(_) 
 *                     |_|   |_|             
 *
 * 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/>.
 *)

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

open Astring

(** Assets packed into the binary and to be unpacked and used as they are *)
module Const = struct

  let delete_restore_marker = "delete-me-to-restore-missing"

  let mutabl =
    [
      Cfg.Urlcleaner.fn;
    ]

  let f_cdb (Mapcdb.Cdb v) = v

  let all =
    [
      ".htaccess";
    (*
      ".well-known/nodeinfo/.htaccess";  (* dot dir missing *)
      ".well-known/nodeinfo/README.txt"; (* dot dir missing *)
      ".well-known/nodeinfo/index.json"; (* dot dir missing *)
      Webfinger.Server.target;           (* dot dir missing *)
     *)
      "README.txt";
      "activitypub/blocked/0.jsa";
      "activitypub/blocked/0.xml";
      Ap.Following.Blocked.Atom.target ;
      Ap.Following.Blocked.Json.target ;
      "activitypub/liked/0.jsa";
      "activitypub/liked/0.xml";
      "activitypub/liked/index.jsa";
      "activitypub/liked/index.xml";
      "activitypub/outbox/0.jsa";
      "activitypub/outbox/0.xml";
      "activitypub/outbox/index.jsa";
      "activitypub/outbox/index.xml";
      "activitypub/subscribed_to/0.jsa";
      "activitypub/subscribed_to/0.xml";
      Ap.Following.Subscribed_to.Atom.target ;
      Ap.Following.Subscribed_to.Json.target ;
      "activitypub/subscribers/0.jsa";
      "activitypub/subscribers/0.xml";
      Ap.Followers.Atom.target;
      Ap.Followers.Json.target;
      "activitypub/index.html";
      "activitypub/README.txt";
      "app/.htaccess";
      "app/README.txt";
      "app/etc/ban.s";
      "app/etc/profile.s";
      "app/i-must-be-403.svg";
      "app/var/README.txt";
      Ap.Note.ibc_dir ^ "cur/README.txt";
      Ap.Note.ibc_dir ^ "new/README.txt";
      Ap.Note.ibc_dir ^ "tmp/README.txt";
      Tag.cdb |> f_cdb;
      Ap.Followers.cdb |> f_cdb;
      Ap.Following.cdb |> f_cdb;
      "app/var/db/o/d/README.txt";
      "app/var/db/o/m/README.txt";
      "app/var/db/o/p/README.txt";
      "app/var/db/o/t/README.txt";
      Storage.fn_id_cdb  |> f_cdb;
      Storage.fn_url_cdb |> f_cdb;
      "app/var/log/seppo.log.0";
      "app/var/log/seppo.log";
      Ban.fn;
      "app/var/run/README.txt";
      "app/var/spool/job/cur/README.txt";
      "app/var/spool/job/err/README.txt";
      "app/var/spool/job/new/README.txt";
      "app/var/spool/job/run/README.txt";
      "app/var/spool/job/tmp/README.txt";
      "app/var/spool/job/wait/README.txt";
      "contrib/etc/apache2/sites-available/050-seppo.conf";
      "contrib/etc/lighttpd/conf-available/50-seppo.conf";
      "contrib/harden.sh";
      "contrib/README.txt";
      delete_restore_marker;
      "favicon.ico";
      "index.html";
      "me-avatar.jpg";
      "me-banner.jpg";
      (* "nodeinfo/2.1.json"; *)
      "o/d/README.txt";
      "o/p/index.xml";
      "o/t/index.json";
      "robots.txt";
      "seppo.pub.pem";
      "themes/current/404.html";
      "themes/current/actor.css";
      "themes/current/actor.js";
      "themes/current/actor.xsl";
      "themes/current/awesomplete.css";
      "themes/current/awesomplete.js";
      "themes/current/backoffice.js";
      "themes/current/backoffice.xsl";
      "themes/current/blocked.xsl";
      "themes/current/changepasswordform.xsl";
      "themes/current/configform.xsl";
      "themes/current/do=tools.xsl";
      "themes/current/feed-icon.svg";
      "themes/current/linkform.js";
      "themes/current/linkform.xsl";
      "themes/current/loginform.xsl";
      "themes/current/people.xsl";
      "themes/current/posts.css";
      "themes/current/posts.js";
      "themes/current/posts.xsl";
      "themes/current/README.txt";
      "themes/current/replies.css";
      "themes/current/replies.xsl";
      "themes/current/style.css";
      (* "themes/current/subscribed_to.js"; *)
      "themes/current/subscribed_to.xsl";
      (* "themes/current/subscribers.css"; *)
      "themes/current/subscribers.js";
      "themes/current/subscribers.xsl";
      "themes/current/tick.mp3";
      "themes/current/timeline.xsl";
      "themes/current/util.xsl";
      "themes/current/valid-atom.svg";
    ]
    @ mutabl

  (** evtl. restore packed files from inside the binary. *)
  let restore_if_nonex perm candidates =
    (* how to deal with IO erros? Let them fly! *)
    if not (File.exists delete_restore_marker)
    then candidates |> List.filter_map (File.restore_static ~perm)
    else []
end

(** Generated assets with local dependencies *)
module Gen = struct
  let make x =
    Result.bind
      Webfinger.Server.(make target)
      (fun _ -> Ok x)

  (* ready to be used in the handler. *)
  let make_cgi x =
    match make x with
    | Error msg ->
      Logr.err (fun m -> m "%s %s" E.e1003 msg);
      Http.s500
    | Ok _ as o -> o
end
