#lang racket
(require gigls/unsafe)
;;; Procedure:
;;;  image-series
;;; Parameters:
;;;   n, an integer
;;;   width, width of image
;;;   height, height of image
;;; Purpose:
;;;   Creates an interesting, reproducable image
;;; Produces:
;;;   image, an image
;;; Preconditions:
;;;   n is between 0 and 999.
;;;   width is a positive integer.
;;;   height is a positive integer.
;;; Postconditions:
;;;   Different values of n will produce different interesting images.
;;;   Each interesting image is noticably different from other images produced with different
;;;    values of n.
(define image-series
  (λ (n width height)
    ;Creates a canvas with a width of width and a height of height    
    (define canvas (image-new width height))
    ;Places turtles on canvas    
    (define frankie (turtle-new canvas))
    (define norma (turtle-new canvas))
    ;Sets initial background color to a color in the list, dependant on n mod 9.    
    (context-set-bgcolor! (list-ref (list "darkblue" "darkcyan" "indigo" "darkslateblue"
                                          "olivedrab" "slategrey" "teal" "steelblue"
                                          "darkmagenta")
                                    (mod n 9))) 
    ;Image-redo! takes the background color and shades it darker as you go along the horizontal axis
    ;The code for image-redo was adapted from Sam Rebelsky (given to me in an email from professor Weinman)
    ; and the problems turned in for the lab "Building Images by Iterating over Positions".
    (image-redo! canvas 
                 (lambda (col row color)
                   (irgb (+ (irgb-red color) (* (/ (- 0 (irgb-red color)) width) col)) 
                         (+ (irgb-green color) (* (/ (- 0 (irgb-green color)) width) col)) 
                         (+ (irgb-blue color) (* (/ (- 0 (irgb-blue color)) width) col)))))
    ;Sets the color of the turtles' brushes, dependant on n.
    (for-each (r-s turtle-set-color! 
                   (list-ref (list "chartreuse" "crimson" "lightseagreen"
                                   "mediumvioletred" "orangered" "springgreen"
                                   "dodgerblue" "blue" "aqua" "deeppink"
                                   "red" "blueviolet" "yellow") (mod n 13))) 
              (list frankie norma))
    ;Teleports turtles without making any marks to their starting points on canvas
    (turtle-teleport! frankie 0 (* .4 height))
    (turtle-teleport! norma (* .3 width) 0)
    ;Places turtles at an angle that, if going forward, will make an isoscelese triangles. That is,
    ; both turtles are facing 45 degrees from the left.        
    (turtle-face! frankie -45)
    (turtle-face! norma 135)
    ;A let* is used here because we needed to define some things to keep the code as clean as possible.
    ; The let* also needs to contain procedures, which it is used as opposed to let. I had help from Professor Weinman
    ; on the let* statements.
    (let* 
        ;fdistance is the distance frankie is from the left edge of canvas, divided by seven.
        ;  The distance is derived from the pathagorean theorem.   
        ([fdistance (if (zero? (mod n 11))
                        0
                        (/ (sqrt (+ (expt (* .4 width) 2) (expt (* .4 height) 2))) 7))]
         ;ndistance is the distance norma is from the top edge of canvas, deivided by six.
         ;  The distance is also derived from the pathagorean theorem.           
         [ndistance (if (zero? (mod n 11))
                        0
                        (/ (sqrt (+ (expt (* .3 width) 2) (expt (* .3 height) 2))) 6))]
         ;action1! is called for its side-effect. It turns the turtle 10 degrees to the right, then
         ; moves forward .5% of width. action1! is based off of code for a circle found in the reading
         ; "Turtle graphics".
         [action1! (lambda (turtle)
                     (turtle-turn! turtle 10)
                     (turtle-forward! turtle (* .005 width)))]
         ;circle-tail! is called for its side-effects. It moves the turtle forward a distance, then
         ; repeats action1! 36 times to make a complete circle. The turtle faces its original direction.         
         [circle-tail! (lambda (turtle distance)
                         (turtle-forward! turtle distance)
                         (repeat 36 action1! turtle))])
      ;This determines how many times frankie completes circle-tail!. Frankie completes circle-tail!
      ; either n mod 11 times, or 6 times. We add 1 to the ammount of times frankie completes a circle-tail!
      ; so that there is more than one circle at certain different n values (as a circle is not necessarily an
      ; interesting image by itself.  
      (when (>= (mod n 11) 0)
        (repeat (min 6 (+ (mod n 11) 1)) 
                circle-tail! frankie fdistance))
      ;Norma completes circle-tail! only when n mod 11 is greater than 6, at which point frankie stops moving.
      ; Norma can move at most 4 times.      
      (when (>= (mod n 11) 6)
        (repeat (- (mod n 11) 6) 
                circle-tail! norma ndistance)))
    ;Now fgcolor is set depending on the same list of colors that the turtles use, but the first color is placed
    ; last. I use lists of the same size to pair colors that I think look good together. This is also dependent on n mod 13.    
    (context-set-fgcolor! (list-ref (list "crimson" "lightseagreen"
                                          "mediumvioletred" "orangered" "springgreen"
                                          "dodgerblue" "blue" "aqua" "deeppink"
                                          "red" "blueviolet" "yellow" "chartreuse") (mod n 13)))
    ;Depending on n mod 8, shapes are selected. First is a large circle/ellipse at .55 width and .8 height.
    ; This circle/ellipse will be in every image, though in different colors.   
    (when 
        (>= (mod n 8) 0)
      (image-select-ellipse! canvas ADD 
                             (* .55 width) (* .8 height) (* .1 width) (* .1 height)))
    ;If n mod 8 is 1, a large square/rectangle is selected. It is the same size as the circle already selected.
    ; It is added to the previous selection. 
    (when 
        (>= (mod n 8) 1)
      (image-select-rectangle! canvas ADD 
                               (* .4 width) (* .7 height) (* .1 width) (* .1 height)))
    ; If n mod 8 is 2, two small circles/ellipses are selected. They are half the size 
    ;as the large circle and square. It is added to the previous selections
    (when
        (>= (mod n 8) 2)
      (image-select-ellipse! canvas ADD
                             (* .6 width) (* .6 height) (* .05 width) (* .05 height))
      (image-select-ellipse! canvas ADD
                             (* .4 width) (* .35 height) (* .05 width) (* .05 height)))
    ; If n mod 8 is 3, a large circle/ellipse is selected. It is the same size as the first circle.
    ;It is added to the previous selections
    (when
        (>= (mod n 8) 3)
      (image-select-ellipse! canvas ADD
                             (* .65 width) (* .45 height) (* .1 width) (* .1 height)))
    ;If n mod 8 is 4, a large circle/ellipse is selected. It is the same size as the first circle.
    ;It is added to the previous selections
    (when
        (>= (mod n 8) 4)
      (image-select-ellipse! canvas ADD
                             (* .3 width) (* .45 height) (* .1 width) (* .1 height)))
    ; If n mod 8 is 5, two small circles/ellipses are selected. They are half the size 
    ;as the large circle and square. It is added to the previous selections
    (when
        (>= (mod n 8) 5)
      (image-select-ellipse! canvas ADD
                             (* .4 width) (* .6 height) (* .05 width) (* .05 height))
      (image-select-ellipse! canvas ADD
                             (* .6 width) (* .35 height) (* .05 width) (* .05 height)))
    ;If n mod 8 is 6, a large square/rectangle is selected. It is the same size as the circle already selected.
    ; It is added to the previous selections. 
    (when 
        (>= (mod n 8) 6)
      (image-select-rectangle! canvas ADD 
                               (* .55 width) (* .2 height) (* .1 width) (* .1 height)))
    ; If n mod 8 is 7, a large square/rectangle is selected. It is the same size as the circle already selected.
    ; It is added to the previous selection. 
    (when
        (= (mod n 8) 7)
      (image-select-ellipse! canvas ADD 
                             (* .4 width) (* .1 height) (* .1 width) (* .1 height)))
    ;Fills the selection with the  fground color.
    (image-fill-selection! canvas)
    ;Removes selection, now the shapes will be left but the selection around them is gone. End of image-series.
    (image-select-nothing! canvas)))
;;; Examples of n: (Warning, the turtles make the program run really slowly.) 721, 887, 108
;;; Representative images used: 117,666,479
