(in-package 3harder)

(defvar *posts* (list))

(when (probe-file #p"posts.txt")
 (let ((*read-eval* nil))
   (with-open-file (in #p"posts.txt")
     (loop for post = (read in nil nil)
           while post
           do (push post *posts*)))))

(defun serve ()
 (let ((socket (usocket:socket-listen "127.0.0.1" 12345)) (connection nil))
   (loop
     (ignore-errors
         (unwind-protect
              (setf connection (usocket:socket-accept socket :element-type 'character))
           (usocket:wait-for-input connection)
           (let* ((*read-eval* nil) (stream (usocket:socket-stream connection)))
             (loop initially (format *terminal-io* "Connected at ~d~%" (get-universal-time))
                   for item-type = (ignore-errors (read-char stream))
                   for alist = (ignore-errors (read stream))
                   for message = (ignore-errors (read stream))
                   do (princ (list item-type alist message))
                   do (terpri)
                   do (assert (or (null alist) (consp alist)))
                   do (unless (or (null message))
                        (with-open-file (s #p"posts.txt" :direction :output :if-exists :append :if-does-not-exist :create)
                          (prin1 (cons alist message) s) (terpri s)))
                   do (if (null message)
                          (format stream "~{~s~%~}"
                                  (mapcan
                                   (lambda (post) (if (subsetp alist (car post) :test 'equalp) (list post) nil)) *posts*))
                          (format stream "~{~s~%~}~%"
                                  (mapcan
                                   (lambda (post) (if (subsetp alist (car post) :test 'equalp) (list post) nil))
                                   (push (cons alist message) *posts*))))
                   do (return))

             (format *terminal-io* "finished message")
             (terpri stream)
             (force-output stream) (sleep 1))
           (progn (format *terminal-io* "Connection closing at ~D~%" (get-universal-time))
                  (usocket:socket-close connection)))))))

(serve)