;;
;; ==========================================================
;; GUI code (requires gui.ss teachpack)
;;
;; create a gui that displays a list of numbers to the user
;; list is displayed as a single message


;; mylist is the actual list to display

(define mylist '(18 22 3 4 19 1919 272 27 2929 ))


;; list-to-string list -> string
;;
;; (list-to-string alist) generates a single
;;    string that includes all of the numbers found in 
;;    the list with ', ' between each.
;; sample: (list-to-string '(1 3 5 6)) => "1, 3, 5, 6"

(define (list-to-string alist)
  (cond
   [(empty? alist) ""]
   [else
	(string-append 
	 (number->string (first alist))
	 ;; if this is the last number, don't add a comma after it
	 (cond
	  [(empty? (rest alist)) ""]
	  [else  ", "])
	 (list-to-string (rest alist)))]))


;;
;; updates the message in the variable list-message to
;;  be the sring representation of the list alist
(define (update-list-message alist)
  (draw-message list-message
				(list-to-string alist)))
;;
;; create a message that will hold the entire list
;; also initializes the message to be the original list (mylist)
(define list-message
  (make-message (list-to-string mylist)))

;; button handler function for ascending
;; updates the message with the sorted list
(define (asc e)
  (update-list-message
   (quicksort mylist <)))

;; button handler function for descending
;; updates the message with the sorted list
(define (desc e)
  (update-list-message
   (quicksort mylist >)))


;;
;; create a window that holds the message list-message and
;;  two buttons
(create-window
 (list
  (list
   (make-message "List: ")
   list-message)
  (list (make-button "ASCENDING" asc)
		(make-button "DESCENDING" desc))))

;; ===========================================================
;; Harder version - vertical list uses a message gui object for
;;   each number in the list.


;; create-messagelist list > list of lists
;;
;; (create-messagelist alon) creates a list of 
;;  message gui objects, each in it's own list 
;;   (so it will be displayed in it's own row).
;;
;;  (create-messagelist '(1 3 5)) =>
;;  (list
;;     (list (make-message (number->string 1)))
;;     (list (make-message (number->string 3)))
;;     (list (make-message (number->string 5))))

(define (create-messagelist alon )
  (cond
   [(empty? alon) empty]
   [else
    (cons (list (make-message (number->string (first alon))))
      (create-messagelist (rest alon)))]))


;;
;; create a window that displays the list vertically and 
;; allows the user to modify the order by clicking some
;;  buttons.
(create-window
 (local
  ;; local definitions - create list of messages that will be
  ;; part of the window. Putting this here means that other functions
  ;; defined below have access to this list as the variable ml
  ((define ml (create-messagelist mylist))
   ;; update-messages draws the elements in alon 
   ;;   (a list of numbers) by changing the message objects in
   ;;   ml (which are in the order they appear in the window).
   (define (update-messages alon)
     (local
      ((define (um-helper lnums lmsgs)
		 (cond
		  [(empty? lnums) true]
		  [(draw-message (first (first lmsgs)) 
						 (number->string (first lnums)))
		   (um-helper (rest lnums) (rest lmsgs))])))
      (um-helper alon ml)))
   ;; button handlers update message list 
   ;; with sorted lists
   (define (desc e) 
     (update-messages (quicksort mylist >)))
   (define (asc e) 
     (update-messages (quicksort mylist <))))
  ;; create list of lists of gui objects for the window
  ;; ml is the list of lists of message objects
  (append
   (list (list (make-message "List of numbers")))
   ml
   (list
    (list (make-button "ASCENDING" asc)
	  (make-button "DESCENDING" desc))))))



;; ===========================================================
;; Display a student record using GUI objects
;; 

(define-struct student
  (name email rid test1 test2 hw1 hw2))

;;
;; make-student-guilist student -> list of lists of gui objects
;; Creates a list of lists of gui objects that corresponds to
;; the student structure.

(define (make-student-guilist stu)
  (list 
   (list (make-message "Name: ") 
		 (make-message (student-name stu)))
   (list (make-message "Email: ")
		 (make-message (student-email stu)))
   (list (make-message "RID: ")
		 (make-message (number->string (student-rid stu))))

   (list (make-message "Test1: ")
		 (make-message (number->string (student-test1 stu)))
		 (make-message "Test2: ")
		 (make-message (number->string (student-test2 stu))))

   (list (make-message "HW1: ")
		 (make-message (number->string (student-hw1 stu)))
		 (make-message "HW2: ")
		 (make-message (number->string (student-hw2 stu))))))


;;
;; function that creates a student record window
(define (create-student-window stu)
  (create-window (make-student-guilist stu)))

;; sample student
(define joe
  (make-student "Joe Student" "stuj@rpi.edu" 12345 62 87 98 23))


(create-student-window joe)


;; ===========================================================
;; list of student records
;;

(define los
  (list
   (make-student "Joe Student" "stuj@rpi.edu" 12345 62 87 98 23)
   (make-student "John Doe"    "doej@rpi.edu" 22222 44 88 99 100)
   (make-student "Jane Smith"  "smithj@rpi.edu" 33333 88 77 66 55)
   (make-student "John Kerry"  "kerryj@rpi.edu" 87654 90 90 90 90)
   (make-student "George Bush" "gw@rpi.edu" 76946 40 30 20 10)))


(define (create-student-list-window lst)
  (local
   ((define (csl-helper l)
	  (cond
	   [(empty? l) empty]
	   [else
		(append (make-student-guilist (first l)) 
				(list (list (make-message "-------------------------------")))
				(csl-helper (rest l)))])))
   (create-window (csl-helper lst))))

(create-student-list-window los)