;;
;; quiz 4 code 
;;

;; Here are the structure definitions for the animation entities supported by draw-anim-entity

;; circle : 
;;     center is a posn
;;     radius is a number
;;     color is a symbol. 'Clear mean clear the circle!

(define-struct circle (center radius color))




;; square : 
;;     center is a posn (NOTE we use center, not topleft!)
;;     radius is a number
;;     color is a symbol. 'Clear means clear the circle

(define-struct square (center size color))

;; delay is just a time in seconds
(define-struct delay (time))



;; draw-anim-entity consumes an animation-entity (a struct that is either
;;    a circle, square or delay
;;
;; For square and circle, either draws or clears the entity (based on the color)
;; For delay, just waits for a while
; 
(define (draw-anim-entity s)
  (cond

    [(circle? s) 
	 ;; it's a circle - should we draw or clear?
	 (cond
	  [ (symbol=? (circle-color s) 'Clear)
		;; clear it
		(clear-circle (circle-center s) (circle-radius s))]

	  [ else
		;; draw it
		(draw-circle (circle-center s) (circle-radius s) (circle-color s)) ])]

    [(square? s) 
	 ;; it's a square - should we draw or clear?
	 (cond
	  [(symbol=? (square-color s) 'Clear)
	   ;; clear it - need to translate from center to topleft
	   (clear-solid-rect 
		(make-posn
		 (- (posn-x (square-center s)) (/ (square-size s) 2))
		 (- (posn-y (square-center s)) (/ (square-size s) 2)))
		(square-size s) (square-size s))]

	  [ else
		;; draw it
		(draw-solid-rect 
		 (make-posn
		  (- (posn-x (square-center s)) (/ (square-size s) 2))
		  (- (posn-y (square-center s)) (/ (square-size s) 2)))
		 (square-size s) (square-size s) (square-color s))])]

	[(delay? s)
	 ;; it's a delay - wait for a while
	 (sleep-for-a-while (delay-time s))]

	;; it's not anything we understand - report an error
    [else 
	 (error 'draw-anim-entity "I dont' know how to draw that (is it an animimation entity?)")]))

;;
;; ========= END OF QUIZ4 CODE 
;;

;;
;; play consumes a list and produces true
;;
;; (play plist) will play the animation entities one at a time,
;; using draw-anim-entity on each in order.
;;
;; sample usage:
;;  (play (cons (make-circle (make-posn 100 100) 20 'Red)
;;    (cons (make-delay 0.5)
;;       (cons (make-circle (make-posn 100 100) 30 'Red)
;;          (cons (make-delay 0.5)
;;             (cons (make-circle (make-posn 100 100) 40 'Red)
;;                (cons (make-delay 0.5)
;;                   (cons (make-circle (make-posn 100 100) 50 'Red) empty))))))))

(define (play plist)
  (cond
    [(empty? plist) true]
    [ else
      (and
       (draw-anim-entity (first plist))
       (play (rest plist)))]))

;;
;; create-draw-wait-clear-circle-animation consumes a circle structure
;;  and a number and produces a list of animation entity structures.
;;
;;  (create-draw-wait-clear-circle-animation c wait_time)
;;  produces a list of animation entities that represent the following
;;   drawing instructions:
;;       1. draw the circle c
;;       2. wait for wait_time seconds
;;       3. clear the circle c
;;
;; sample usage:
;;  (create-draw-wait-clear-circle-animation 
;;        (make-circle (make-posn 100 100) 50 'Red) .1)

(define (create-draw-wait-clear-circle-animation c wait_time)
  (cons c
		(cons 
		 (make-delay wait_time)
		 (cons
		  (make-circle (circle-center c) (circle-radius c) 'Clear)
		  empty))))

;;
;; create-draw-wait-clear-square-animation consumes a square structure
;;  and a number and produces a list of animation entity structures.
;;
;;  (create-draw-wait-clear-square-animation c wait_time)
;;  produces a list of animation entities that represent the following
;;   drawing instructions:
;;       1. draw the square c
;;       2. wait for wait_time seconds
;;       3. clear the square c
;;
;; sample usage:
;;  (create-draw-wait-clear-square-animation 
;;        (make-square (make-posn 100 100) 50 'Red) .1)

(define (create-draw-wait-clear-square-animation c wait_time)
  (cons c
		(cons 
		 (make-delay wait_time)
		 (cons
		  (make-square (square-center c) (square-size c) 'Clear)
		  empty))))

;;
;; create-move-circle-animation a circle structure and three numbers,
;;    and produces a list of animation entity structures.
;;
;;  (create-move-circle-animation c dx dy steps wait_time)
;;  produces a list of animation entities that describe the movement
;;  of a circle across the screen.
;;  c represents the original position of the circle as well as the
;;  color and radius.
;;  dx and dy are the change in x and y position at each step.
;;  steps is the total number of steps (each step corresponds to a new
;;    circle position).
;;  wait_time is the time delay between steps.
;;
;; sample usage:
;;  (create-move-circle-animation 
;;        (make-circle (make-posn 100 100) 50 'Red) 
;;        3 0 100 0.1)

(define (create-move-circle-animation acircle xchange ychange steps wait_time)
  (cond
    [(= steps 0) empty]
    [else
     (append
	  (create-draw-wait-clear-circle-animation acircle wait_time)
	  (create-move-circle-animation
	   (make-circle
		(make-posn
		 (+ xchange (posn-x (circle-center acircle)))
		 (+ ychange (posn-y (circle-center acircle))))
		(circle-radius acircle)
		(circle-color acircle))
	   xchange ychange (- steps 1) wait_time))]))


;;
;; create-move-square-animation a square structure and three numbers,
;;    and produces a list of animation entity structures.
;;
;;  (create-move-square-animation c dx dy steps wait_time)
;;  produces a list of animation entities that describe the movement
;;  of a square across the screen.
;;  c represents the original position of the square as well as the
;;  color and radius.
;;  dx and dy are the change in x and y position at each step.
;;  steps is the total number of steps (each step corresponds to a new
;;    square position).
;;  wait_time is the time delay between steps.
;;
;; sample usage:
;;  (create-move-square-animation 
;;        (make-square (make-posn 100 100) 50 'Red) 
;;        3 0 100 0.1)

(define (create-move-square-animation asquare xchange ychange steps wait_time)
  (cond
    [(= steps 0) empty]
    [else
     (append
	  (create-draw-wait-clear-square-animation asquare wait_time)
	  (create-move-square-animation
	   (make-square
		(make-posn
		 (+ xchange (posn-x (square-center asquare)))
		 (+ ychange (posn-y (square-center asquare))))
		(square-size asquare)
		(square-color asquare))
	   xchange ychange (- steps 1) wait_time))]))

;; some sample test code
;;
(start 500 500)

; (define anim (create-move-circle-animation
; 			  (make-circle (make-posn 100 100) 30 'Blue)
; 			  2 2 200 .01))

(define anim2 (create-move-square-animation
			  (make-square (make-posn 100 100) 30 'Blue)
			  2 2 200 .01))

(play anim2)