#lang syndicate
;; Simple "shell" or REPL, used by the file-system demos.

(require (only-in racket/port read-bytes-line-evt))
(require (only-in racket/string string-trim string-split))

(require/activate syndicate/drivers/timer)
(require/activate "fs-protocol.rkt")

(define (sleep sec)
  (define timer-id (gensym 'sleep))
  (until (message (timer-expired timer-id _))
         (on-start (send! (set-timer timer-id (* sec 1000.0) 'relative)))))

;; Shell
(let ((e (read-bytes-line-evt (current-input-port) 'any)))
  (define (print-prompt)
    (printf "> ")
    (flush-output))
  (spawn (field [reader-count 0])
         (on-start (print-prompt))
         (stop-when (message (inbound (external-event e (list (? eof-object? _))))))
         (on (message (inbound (external-event e (list (? bytes? $bs)))))
             (match (string-split (string-trim (bytes->string/utf-8 bs)))
               [(list "open" name)
                (define reader-id (reader-count))
                (reader-count (+ (reader-count) 1))
                (spawn (on-start (printf "Reader ~a opening file ~v.\n" reader-id name))
                       (stop-when (message `(stop-watching ,name)))
                       (on (asserted (file name $contents))
                           (printf "Reader ~a sees that ~v contains: ~v\n"
                                   reader-id
                                   name
                                   contents))
                       (on-stop (printf "Reader ~a closing file ~v.\n" reader-id name)))]
               [(list "close" name)
                (send! `(stop-watching ,name))]
               [(list* "write" name words)
                (send! (save (file name words)))]
               [(list "delete" name)
                (send! (delete name))]
               [_
                (printf "I'm afraid I didn't understand that.\n")
                (printf "Try: open filename\n")
                (printf "     close filename\n")
                (printf "     write filename some text goes here\n")
                (printf "     delete filename\n")])
             (sleep 0.1)
             (print-prompt))))
