(define-module (tiedote-md-service)
  #:use-module (gnu services configuration)
  #:use-module (gnu services shepherd)
  #:use-module (gnu services base)
  #:use-module (gnu system shadow)
  #:use-module (gnu services)
  #:use-module (guix records)
  #:use-module (guix gexp)
  #:use-module (tiedote-md-package)
  #:use-module (gnu packages bash)
  #:export (tiedote.md-configuration
            tiedote.md-service-type))

(define-maybe string)

(define-configuration/no-serialization tiedote.md-configuration
  (email-address
    (string)
    "Email address to send messages as. Mail to this address must be routed to
the tiedote.md user on this system.")
  (sender-name
    (string)
    "Name to send messages as.")
  (remote-url
    (string)
    "URL of the Git repository to mirror.")
  (remote-branch
    maybe-string
    "Git branch to read messages from.")
  (sendmail-path
    (string "/run/privileged/bin/sendmail")
    "Path to a sendmail compatible mailing executable.")
  (port
    (integer 3000)
    "Port to listen on for webhook notifications.")
  (socket-path
    (string "/run/tiedote.md/acid.sock")
    "Socket on which tiedote.md should listen on.")
  (state-directory
    (string "/var/lib/tiedote.md")
    "Directory for persistent storage."))

(define (tiedote.md-accounts config)
  (match-record config <tiedote.md-configuration>
    (state-directory)
    (list (user-group
            (name "tiedote.md")
            (system? #t))
          (user-account
            (name "tiedote.md")
            (system? #t)
            (group "tiedote.md")
            (comment "Tiedote.md service user")
            (home-directory state-directory)
            (shell (file-append bash-minimal "/bin/bash"))))))

(define (tiedote.md-shepherd-service config)
  (match-record config <tiedote.md-configuration>
    (state-directory socket-path email-address sender-name port sendmail-path
     remote-branch remote-url)
    (list (shepherd-service
            (documentation "A simple mass email system")
            (requirement '(networking user-processes))
            (provision '(tiedote.md))
            (start #~(let* ((user (getpw "tiedote.md"))
                            (uid (passwd:uid user))
                            (gid (passwd:gid user))
                            (socket-directory (dirname #$socket-path))
                            (repo-path (string-append #$state-directory "/git-repo")))
                       (begin
                         (mkdir-p socket-directory)
                         (chown socket-directory uid gid)
                         (make-forkexec-constructor
                          (list #$(file-append tiedote-md "/bin/tiedote.md")
                            "--address" #$email-address
                            "--sender-name" #$sender-name
                            "--sendmail" #$sendmail-path
                            "--socket" #$socket-path
                            "--repository" repo-path
                            "--port" #$(number->string port)
                            "--remote-url" #$remote-url
                            ;,@(if #$(maybe-value-set? remote-branch)
                            ;    (list "--remote-branch" #$remote-branch)
                            ;    '())
                            "server")
                          #:user "tiedote.md"
                          #:group "tiedote.md"
                          #:directory #$state-directory))))
            (stop #~(make-kill-destructor))))))

(define (tiedote.md-activation config)
  (match-record config <tiedote.md-configuration>
    (state-directory email-address sender-name sendmail-path socket-path)
    (let* ((receive-exec (list (file-append tiedote-md "/bin/tiedote.md") ; file to exec
                               (file-append tiedote-md "/bin/tiedote.md") ; arg $0
                               "--address" email-address
                               "--sender-name" sender-name
                               "--sendmail" sendmail-path
                               "--socket" socket-path))
           (receive-script (program-file "tiedote.md-receive"
                                         #~(apply execl #$receive-exec)))
           (forward-file (mixed-text-file "dot-forward" "|" receive-script)))
      #~(symlink #$forward-file
                 (string-append #$state-directory "/.forward")))))

(define tiedote.md-service-type
  (service-type
    (name 'tiedote.md)
    (extensions
      (list (service-extension account-service-type tiedote.md-accounts)
            (service-extension activation-service-type tiedote.md-activation)
            (service-extension shepherd-root-service-type tiedote.md-shepherd-service)))
    (description "A simple mass email system")))