;;;; Alerts.

;;; Alerts are random little warnings that pop up asynchronously to
;;; whatever the real page is supposed to be doing.  They get inserted
;;; by sk:page-preamble in some appropriate place.

;;; All functions that want to issue alerts should be edited into this
;;; one, which is the toplevel called by sk:page-preamble.  If we had
;;; more of these, I'd make it some sort of hook variable, but we don't,
;;; and we really shouldn't plan on a whole pile of them anyway.
(define (alerts:show)
  (let ((alerts (string-append 
		 (alerts:statefile-save-failure)
		 (alerts:expiration)
		 (alerts:no-interests-found)
		)))
    (if (equal? alerts "")
	""
	(string-append alerts "<hr><p>"))))

;;; Puts a bold version of the message in a standardized little box.
;;; If the message is any flavor of null, emits nothing; this makes
;;; it easier to write callers that don't produce any output in the
;;; normal case and hence are invisible unless something is wrong.
(define (alerts:box message)
  (cond ((or (not message)
	     (null? message)
	     (eq? message *unspecified*) ; Allow easy use of (when ...)
	     (equal? message ""))
	 "")
	(t
	 (format nil "<div align=\"center\"><table align=\"center\" bgcolor=\"cyan\" border=\"0\" cellspacing=\"5\" width=\"100%\">~
                      <tr><td><b>~A</b></td></tr></table></div><p>"
		 message))))

;;;; Warn the user if we were unable to checkpoint.

;;; If the last checkpoint failed, we try again immediately, on every page fetch,
;;; both so the complaint we have for the user is fresh, and to maximize the chances
;;; that we'll succeed soon.
(define (alerts:statefile-save-failure)
  (alerts:box
   (unless *vars:verification-succeeded?* ; This starts out #t in a brand-new Yenta, and gets set #f in any Yenta if a checkpoint fails.
     (vars:save-encrypted)		; Try again immediately.  Maybe whatever went wrong has since been fixed.
     (unless *vars:verification-succeeded?* ; Did we screw up -again-?  If so, bitch.
       (let* ((checkpoint (vars:vars-scm-crypt-pathname))
	      (additional
	       (cond ((file-exists? checkpoint)
		      (format nil "This failure is probably due to lack of disk space.~&~
                                   Please check that there is plenty of space in the filesystem~&~
                                   in which ~A resides.  Yenta will attempt to checkpoint again~&~
                                   the next time you fetch a page, and will also try again eventually~&~
                                   even if you don't follow any links.  Once it tries again and succeeds,~&~
                                   this alert will stop appearing.  (The last checkpoint that succeeded was at ~A.)"
			      (yenta-name "")
			      (date-string (vector-ref (stat checkpoint) 9))))
		     (t
		      (format nil "In fact, ~A, which is the~&~
                                   file Yenta uses to save its state, does not exist at all.~&~
                                   Something else must have deleted it.  Normally, Yenta's failure~&~
                                   to save state is due to lack of disk space, but something else~&~
                                   might be going on if this file is simply missing.  You should find~&~
                                   out what is going on immediately.  If you shut down Yenta or take a~&~
                                   crash now, you will lose all your keys, your identity, and all the~&~
                                   signed attestations that make up your reputation, unless you~&~
                                   can restore this file from a backup.  This is a very serious condition."
			      checkpoint)))))
	 (format nil "Yenta's last attempt to checkpoint its state to disk has failed.~&~
                      While the running Yenta is perfectly okay, if you were to take a crash~&~
                      or quit Yenta now, all of its state since the last time Yenta checkpointed~&
                      would be lost.<p>~A"
		 additional))))))

;;;; Give a warning when this Yenta expires.  Can be made arbitrarily obnoxious.

;;; When we want this version of Yenta to expire, in seconds since the UNIX epoch (00:00:00 GMT, January 1, 1970).
(define *yenta-expiration-date* (* 30	; Our development version currently expires around Jan 1 2000 GMT---Yenta needed a Y2K bug.
				   365.25
				   24 60 60))

(define *yenta-distribution-url* "http://yvette.www.media.mit.edu/projects/Yvette/Distribution/")

;;; The actual alert.
(define (alerts:expiration)
  (alerts:box
   (when (> (current-time) *yenta-expiration-date*)
     (format nil "This version of Yenta has expired.  While it will still run, there is no~&~
                  guarantee that it will continue to be able to communicate with the latest~&~
                  Yentas forever.  This is true, in part, because allowing very old versions~&~
                  to continue to run makes life much more difficult for Yenta's implementors.~&~
                  To receive the latest version of Yenta,~&~
                  start <a href=\"~A\">here</a>."
	     *yenta-distribution-url*))))

;;;; Warn the user if we weren't able to ever find -any- interests.

(define (alerts:no-interests-found)
  (alerts:box
   (when *interests:alert-about-no-interests?*
     (format nil "After scanning your documents, Yenta could not identify any~&~
                  interests of yours.  Perhaps it didn't actually find enough (or any)~&~
		  documents to scan; you should check the <a href=\"news.html\">news</a>~&~
		  page for details.<p>~2&~
		  In any event, Yenta can't do much for you if it can't identify your~&~
		  interests, so you should go to the <a href=\"interests.html\">interests</a>~&~
		  page and specify some more files for it to scan.  At the moment, Yenta~&~
		  is available and may be communicating with other Yentas, but it won't have~&~
		  much to say to them, and won't be in any clusters or suggest any introductions,~&~
		  until you specify some documents from which it can deduce your interests."))))

;;; End of file.
