;;
;; drawing functions that eliminate the "it's not an integer" hassle
;; these all take the floor of all numbers used for drawing
;;   before calling the corresponding draw- function

(define (idraw-circle center radius color)
  (draw-circle
   (make-posn
    (floor (posn-x center))
    (floor (posn-y center)))
   (floor radius)
   color))

(define (iclear-solid-disk center radius)
  (clear-solid-disk
   (make-posn
    (floor (posn-x center))
    (floor (posn-y center)))
   (floor radius)))

(define (idraw-solid-disk center radius color)
  (draw-solid-disk
   (make-posn
    (floor (posn-x center))
    (floor (posn-y center)))
   (floor radius)
   color))

(define (idraw-solid-rect topleft width height color)
  (draw-solid-rect
   (make-posn (floor (posn-x topleft))
			  (floor (posn-y topleft)))
   (floor width)
   (floor height)
   color))

(define (iclear-solid-rect topleft width height)
  (clear-solid-rect
   (make-posn (floor (posn-x topleft))
			  (floor (posn-y topleft)))
   (floor width)
   (floor height)))

;===============================================================
; draw one eye with center and size specified.
;  an eye is a white circle with black border and
;   black pupil.
;;   direction can be 'left, 'center, or 'right
;;   and determines where the pupil is drawn.
;;   center is looking straight ahead, left looks to
;;    the left, etc.
(define (draw-eye center size direction)
  (and
   (idraw-solid-disk center (floor size) 'white)
   (idraw-circle center (floor size) 'black)
   (cond
     [(symbol=? direction 'left) 
      (idraw-solid-disk 
       (make-posn
        (- (posn-x center) (* size 0.75))
        (posn-y center))
        (* size 0.30) 'black)]

     [(symbol=? direction 'right) 
      (idraw-solid-disk 
       (make-posn
        (+ (posn-x center) (* size 0.75))
        (posn-y center))
	   (* size 0.30) 'black)]
     
     [else
      (idraw-solid-disk 
	   center
        (* size 0.30) 'black)]
	 )))
     

;;draw-kyle needs a posn, number and symbol
;;  posn is the center of kyle's head.
;;  number is the radius of kyle's head.
;;  symbol determines where kyle is looking:
;;    'left - he is looking to our left.
;;    'right - he is looking to our right.
;;    'center - he is looking at us.
;;    
;; sample: (draw-kyle (make-posn 100 100) 50 'center)
;; 
(define (draw-kyle center size look)
  (and
   ;;create face
   (idraw-solid-disk center size 'blanchedalmond)
   ;;create hat
   (idraw-solid-rect 
	(make-posn 
	 (- (posn-x center) (* size .8))
	 (- (posn-y center) (* size 1.2)))
	 (* size 1.6) 
	 (* size .6) 
	 'darkblue)

   (idraw-solid-rect 
	(make-posn 
	 (- (posn-x center) (* size .6)) 
	 (- (posn-y center) (* size .8))) 
	(* size 1.2) 
	(* size .2) 
	'darkred)
   ;; draw eyes
   (draw-eye 
	(make-posn 
	 (- (posn-x center) (* size .25))
	 (- (posn-y center) (* size .25)))
	 (* size .25) look)

   (draw-eye 
	(make-posn 
	 (+ (posn-x center) (* size .25))
	 (- (posn-y center) (* size .25)))
	 (* size .25) look)
   ;; draw mouth
   (draw-solid-disk 
	(make-posn 
	 (posn-x center) 
	 (+ (posn-y center) (* size .5))) 
	(* size 0.1) 
	'black)
))


;;clear-kyle needs a posn and a number
;;  posn is the center of kyle's head.
;;  number is the radius of kyle's head.

;; sample: (clear-kyle (make-posn 100 100) 50 )
;; 
(define (clear-kyle center size)
  (and
   ;;create face
   (iclear-solid-disk center size)
   ;;create hat
   (iclear-solid-rect 
	(make-posn 
	 (- (posn-x center) (* size .8))
	 (- (posn-y center) (* size 1.2)))
	 (* size 1.6) 
	 (* size .6) 
	 )))



;;test code - animated kyle looks around.
;; (start 400 400)
;; (define center (make-posn 200 200))
;; (draw-kyle center 50 'left)
;; (sleep-for-a-while 1)
;; (draw-kyle center 50 'center)
;; (sleep-for-a-while 1)
;; (draw-kyle center 50 'right)

;; ========================================================
;; My Solution
;;
;; definition of a structure that represents a "kyle"
;;  a kyle has a center (posn), a size (radius of head)
;;  and an indication of which direction he is looking
(define-struct kyle (center size facing))

;;
;; draw-a-kyle consumes a kyle structure and returns true
;; 
;; (draw-a-kyle k) calls draw-kyle giving it the 
;;   values extracted from the kyle structure k
;;
;; sample usage: 
;;    (draw-a-kyle (make-kyle (make-posn 100 100) 50 '

(define (draw-a-kyle k) 
  (draw-kyle (kyle-center k) (kyle-size k) (kyle-facing k)))


;; ========================================================
;;
;; draw-and-clear-kyle consumes a kyle structure and a number,
;;  and produces true.
;;
;; (draw-and-clear-kyle k dly) draws the kyle represented by
;;   the kyle structure k, then waits dly seconds and finally
;;   clears the kyle (erases it).
;;

(define (draw-and-clear-kyle k dly)
  (and
   (draw-kyle (kyle-center k) (kyle-size k) (kyle-facing k)) 
   (sleep-for-a-while dly) 
   (clear-kyle (kyle-center k) (kyle-size k))))

;;
;; translate-kyle consumes a kyle structure and 2 numbers, and produces
;;    a kyle structure.
;;
;; (translate-kyle k deltax deltay) will create a kyle-structure that
;;   is the same as k, except that the center of the kyle will be shifted
;;   deltax pixels to the right, and deltay pixels down.
;;
;;
(define (translate-kyle k deltax deltay)
  (make-kyle
   (make-posn
	( + deltax (posn-x (kyle-center k)))
	( + deltay (posn-y (kyle-center k))))
   (kyle-size k)
   (kyle-facing k)))


;; move-kyle consumes a kyle structure and two numbers, produces 
;;  a kyle structure.
;;
;; (move-kyle k x y) will draw the kyle defined by k, will wait 
;;   a while (.2 seconds), then will erase the kyle. THe function
;;   then produces (returns) a new kyle structure that is moved
;;   to the right x pixels and down y pixels.

(define (move-kyle k x y)
  (cond
    [(draw-and-clear-kyle k .2) (translate-kyle k x y)]
    [else k]))

;; move-kyle-eyes k consumes a kyle structure and returns
;;  a kyle structure. 
;; (move-kyle-eyes k) will create a new kyle structure that is
;; the same as k, except that the eyes will move (facing will change).
;;  If the eyes are originally facing left, they will move to center,
;;    center becomes right, and right becomes left.
;;
(define (move-kyle-eyes k)
  (make-kyle 
   (kyle-center k)
   (kyle-size k)
   ( cond
	 [(symbol=? (kyle-facing k) 'left) 'center]
	 [(symbol=? (kyle-facing k) 'center) 'right]
	 [(symbol=? (kyle-facing k) 'right) 'left])))



;; test code

; (define testk (make-kyle (make-posn 100 100) 50 'center))
; (start 400 400)
;  (draw-a-kyle 
;   (move-kyle-eyes 
;    (move-kyle
;     (move-kyle-eyes 
;  	(move-kyle
;  	 (move-kyle-eyes 
;  	  (move-kyle
;  	   (move-kyle-eyes 
;  		(move-kyle
;  		 (move-kyle-eyes 
;  		   (move-kyle testk 2 0)) 2 0)) 2 0)) 2 0)) 2 0)))



;; animate-kyle consumes a kyle structure and two numbers, and produces true.
;;
;; (animate-kyle k delta total) is a recursive function that will 
;;  create an animation by moving kyle across the screen while 
;;  changing his eyes. The argument total control how many different
;;  kyles (frames) are generates, each is move delta pixels horizontally
;;  from the previous kyle (frame).
;;
;;  sample usage: (animate 
;;                   (make-kyle (make-posn 100 100) 50 'center)
;;                    2 100)

(define (animate-kyle k delta  total)
  (cond
   [ (<= total 0) k]
   [ (draw-a-kyle k)
	 (animate-kyle 
	  (move-kyle-eyes
	   (move-kyle k delta 0)) delta (- total delta)) ]))


;; test for animate-kyle 
;; (animate-kyle testk 2 100)