(yreq "Affordances/attestations-filter")
(yreq "Utilities/yenta-utils")

; a message is:
; (<interest-match> <responses> <centroid-spec> <sender-id> <unique-id-num>
;  <title> <text> <response-to-unique-id> <recipient-id> <signature>)

; in transit the first two are missing.

; <signature> signs (<sender-id> <title> <text> <response-to-id>)

(def-yenta-var *messages:message-list* '#(() () () () () () () ()))

(def-yenta-var *messages:filtered-message-list* '())

(def-yenta-var *messages:next-spot* 0)

(def-yenta-var *messages:accepted-message-list* 
  (integers 0 (- *messages:next-spot* 1)))

(define (messages:topic message)
  (list-ref message 2))

(define (messages:sender message)
  (list-ref message 3))

(define (messages:local-interest message)
  (list-ref message 0))

(define (messages:unique-id message)
  (list (list-ref message 3) (list-ref message 4)))

(define (messages:next-id)
  (let ((id *messages:next-id*))
    (set! *messages:next-id* (+ id 1))
    id))

(define (messages:title message)
  (list-ref message 5))

(define (messages:text message)
  (list-ref message 6))

(define (messages:response-to message)
  (list-ref message 7))

(define (messages:responses message)
  (list-ref message 1))

(define (messages:recipient message)
  (list-ref message 8))

(define (messages:make-message topic local-interest sender recipient id-num
			       title text response-to)
  ;; When you make a message, there aren't any responses yet. :)
  (list local-interest '() topic sender id-num title text response-to 
	recipient ""))

(define (messages:get-message index)
  (vector-ref *messages:message-list* index))

(define (messages:add-message message . skip)
  (cond ((identity:note-message-id (messages:unique-id message)
				   *messages:next-spot*)
	 (when (> *messages:next-spot* 
		  (- (vector-length *messages:message-list*) 1))
	   (vector-set-length! *messages:message-list* 
			       (* 2 *messages:next-spot*))
	   (do ((i (+ 1 *messages:next-spot*) (+ i 1)))
	       ((= i (* 2 *messages:next-spot*)))
	     (vector-set! *messages:message-list* i #f)))
	 (vector-set! *messages:message-list* *messages:next-spot* message)
	 (if (af:block-filter message)
	     (set! *messages:filtered-message-list* 
		   (cons *messages:next-spot* *messages:filtered-message-list*))
	     (set! *messages:accepted-message-list* (cons *messages:next-spot* *messages:accepted-message-list*)))
	 (when (messages:response-to message)
	   (let ((msg (identity:index-of-message 
		       (messages:response-to message))))
	     (when msg
	       (list-set! (vector-ref *messages:message-list* msg) 1
			  (cons (messages:unique-id message)
				(list-ref 
				 (vector-ref 
				  *messages:message-list* msg) 1))))))
	 (when (and (messages:recipient message)
		    (not (equal? (messages:recipient message) *local-yenta-id*)))
	   (let ((yid (messages:recipient message)))
	     (identity:add-message! yid *messages:next-spot*)
	     (iy:contact-yenta yid 'messages)))
	 ;; This if is the counter stuff.
	 (if (equal? (messages:sender message) *local-yenta-id*)
	     (if (messages:recipient message)
		 (begin
		   (inc! *ctr:ind-messages-sent*)
		   ;; %% count bytes here?
		   )
		 (begin
		   (inc! *ctr:cluster-messages-sent*)
		   ;; %% count bytes here?
		   ))
	     (begin
	       (if (equal? (messages:recipient message) 
			   *local-yenta-id*)
		   (begin
		     (inc! *ctr:ind-messages-received*)
		     ;; %% count bytes here?
		     ))
	       (if (not (messages:recipient message))
		   (begin
		     (inc! *ctr:cluster-messages-received*)
		     ;; %% count bytes here?
		     ))))
	 (when (and (not (messages:recipient message))
		    (messages:local-interest message))
	   (for-each (lambda (yid)
		       (identity:add-message! yid *messages:next-spot*)
		       (iy:contact-yenta yid 'messages))
		     (filter (lambda (elt)
			       (not (or (equal? elt *local-yenta-id*)
					(equal? elt (messages:sender message))
					(member elt skip))))
			     (interests:get-cluster-yids
			      (messages:local-interest message)))))
	 (inc! *messages:next-spot*)
	 #t)
	(t
	 #f)))

(def-yenta-var *messages:next-id* 0)

(define (messages:examine-message message)
  (let ((match (interests:match-interest-with-database 
		(compare:import-document (caddr message)))))
    (list-set! message 0
	       (if match
		   (cadr match)
		   match))
    match))

(define (messages:pack-for-transit message)
  (cddr message))

(define (messages:unpack packed)
  (let ((message (cons #f (cons '() packed))))
    (messages:examine-message message)
    message))
