(in-package harder)

(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" 8070)) (connection nil))
    (loop
      (handler-case
	  (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 = (read-char stream)
		    for alist = (read stream)
		    for message = (read-line stream)
		    do (assert (consp alist))
		    do (unless (or (string= message "") (string= message "/r
			 (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 (or (string= message "/r
			   (format stream "~{~a~%~}"
				   (mapcan 
				    (lambda (post) (if (subsetp alist (car post) :test 'equalp) (list post) nil)) *posts*))
			   (format stream "~{~a~%~}~%"
				   (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 0.5))
	    (progn (format *terminal-io* "Connection closing at ~D~%" (get-universal-time))
		   (usocket:socket-close connection)))
	(t (e) (format *terminal-io* "Serve error: ~a, quitting at ~d" e (get-universal-time)) (sleep (random 5)))))))

(serve)