#lang racket
(require gigls/unsafe)
;Agustin Molina and Jason Cho

;;; Procedure: new-colors
;;; Purpose: To construct 3 named colors from a single integer
;;; Parameters: n, a positive integer
;;; Produces: a list containing 3 named colors
;;; Preconditions: n is a positive integer 
;;; Postconditions: The three new colors are represented as strings and can be used to recolor drawings in GIMP.

(define new-colors
  (λ (n)
    (let*
        ([nrgb (modulo n 256)] ;converts n to an integer < 256 (irgb-compatible)
         [rgb-lst (make-list 3 (color->rgb-list (irgb-new nrgb nrgb nrgb)))] ;makes a list containing 3 copies of a list of 3 rgb components that correspond to a shade of gray
         [ured (list->vector (car rgb-lst))] ;the first rgb-list from rgb-lst will correspond to our red color
         [ugreen (list->vector (cadr rgb-lst))] ; the second rgb-list will be our green
         [ublue (list->vector (caddr rgb-lst))]) ; the third list will be our blue
      (when
        (< (vector-ref ured 0) 96) 
        (vector-set! ured 0 (+ nrgb 64))
        (vector-set! ugreen 1 (+ nrgb 64))
        (vector-set! ublue 2 (+ nrgb 64))) ;these when statements transforms the r, g and b components of ured, ugreen, and ublue respectively
      (when
          (> (vector-ref ured 0) 96) 
        (vector-set! ured 0 (+ nrgb 96))
        (vector-set! ugreen 1 (+ nrgb 96))
        (vector-set! ublue 2 (+ nrgb 96)))
      (list  ;makes a list of 3 named colors using the (color->color-name) procedure
       (color->color-name (rgb-list->irgb 
                           (vector->list ured)))
       (color->color-name (rgb-list->irgb 
                           (vector->list ugreen)))
       (color->color-name (rgb-list->irgb 
                           (vector->list ublue)))))))
      
       



;;; Procedures: v-lines, h-lines
;;; Parameters:
;;;     lines, an integer that determines the number of lines drawn on the image
;;;     image, the image on which the lines will be drawn
;;;     hdist/vdist, an integer corresponding to the horizontal/vertical distance between each line
;;;     col1/row1, the starting column/row for the first line
;;;     col2/row2, the ending column/row for the first line
;;; Purpose: draws vertical/horizontal lines on the image
;;; Produces: a modified version of the original image
;;;


(define v-lines
  (λ (lines image hdist col1 col2)
    (cond [(> lines 1)
      (image-draw-line! image col1 0 col2 (image-height image))
      (v-lines (- lines 1) image hdist (+ col1 hdist) (+ col2 hdist))]
          [else image])))
                

(define h-lines
  (λ (lines image vdist row1 row2)
    (cond [(> lines 1)
      (image-draw-line! image 0 row1 (image-height image) row2)
      (h-lines (- lines 1) image vdist (+ row1 vdist) (+ row2 vdist))]
          [else image])))

;;; Procedure: web
;;; Purpose: elaborate a web of horizontal and vertical lines
;;; Parameters:
;;;     n: a positive integer
;;;     lines: an integer corresponding to the number of lines to be drawn
;;;     height/width: an integer describing the width/height of the image
;;;     image: an image on which the web will be drawn
;;;     our-red: a named reddish tone

(define web
  (λ (lines width height image our-red)
    (let* ([line-dist (/ width (+ lines 2))])
      (if (> lines 6)
          (context-set-brush! "2. Block 02" (* (+ lines 1) 2)) ;depending on the number of lines, brush size will vary
          (context-set-brush! "2. Block 02" (* (+ lines 1) 4)))
      (context-set-fgcolor! our-red) ; set the foreground color to a hue derived from n
      (v-lines (+ lines 1) image line-dist (/ width (+ lines 2)) (/ width (+ lines 2)));draws horizontal lines on image using the h-lines procedure. Add 1 to n-lines to avoid case where n-line parameter is 0
      (h-lines (+ lines 1) image line-dist (/ width (+ lines 2)) (/ height (+ lines 2)))))) ;draws vertical lines on image using the h-lines procedure. Add 1 to n-lines to avoid case where n-line parameter is 0

;The following procedures for turtles were taken from Assignment 7
(define one-side!
  (λ (turtle side-length sides)
    (turtle-forward! turtle side-length)
                    (turtle-turn! turtle (/ 360 sides))))
(define turtle-polygon!
  (λ (turtle side-length sides)
    (repeat sides
            one-side! turtle side-length sides)))

(define turtle-centered-polygon!
  (λ (turtle radius sides)
    (let ([interior-angle (/ (* 180 (- sides 2)) sides)])
      (turtle-up! turtle)
      (turtle-forward! turtle radius)
      (turtle-down! turtle)
      (turtle-turn! turtle (- 180 (/ interior-angle 2)))
      (turtle-polygon! turtle (* 2 radius (sin (/ pi sides))) sides)
      (turtle-turn! turtle (/ interior-angle 2))
      (turtle-up! turtle)
      (turtle-forward! turtle radius)
      (turtle-turn! turtle 180)
      (turtle-down! turtle))))   

(define turtle-spin2!
  (λ (turtle radius sides angle)
    (turtle-centered-polygon! turtle radius sides)
    (turtle-turn! turtle angle)))

(define turtle-spin-centered-polygon!
  (λ (turtle radius sides angle copies)
   (repeat copies turtle-spin2! turtle radius sides angle)
  (turtle-turn! turtle (- 360 (* copies angle)))
    (turtle-face! turtle 0)))

(define turtle-spin!
  (λ (turtle side-length sides angle)
    (turtle-polygon! turtle side-length sides)
    (turtle-turn! turtle angle)))

(define turtle-spin-polygon!
 (λ (turtle side-length sides angle copies)
   (repeat copies turtle-spin! turtle side-length sides angle)
  (turtle-turn! turtle (- 360 (* copies angle)))))

(define our-shape!
  (λ (turtle width height angle)
    (turtle-teleport! turtle (/ width 2) (/ height 2))
    (turtle-spin-centered-polygon! turtle (/ width 1.5) 5 angle 8)
    (turtle-spin-centered-polygon! turtle (/ width 2) 5 angle 8)
    (turtle-spin-centered-polygon! turtle (/ width 2.5) 5 angle 8)))

(define our-shape-2!
  (λ (turtle width height angle)
    (turtle-teleport! turtle (/ width 2) (/ height 2))
    (turtle-spin-polygon! turtle (/ width 8) 5 angle 20)))

;;; Procedure: image-select-x!
;;; Parameters: image, an image
;;; Purpose: uses image-select-polygon! to select an x shape
;;; Produces: nothing, called for its side effect
;;; Preconditions: image-select-x is applied to an image
;;; Postconditions: an x shape is selected on the image

(define image-select-x!
  (λ (image)
    (let* ([width (image-width image)]
           [height (image-height image)]
           [hw (/ width 2)]
           [hh (/ height 2)]
           [w10 (+ hw (/ width 10))]
           [w20 (+ hw (/ width 20))]
           [-w10 (- hw (/ width 10))]
           [-w20 (- hw (/ width 20))]
           [h10 (+ hh (/ height 10))]
           [h20 (+ hh (/ height 20))]
           [-h10 (- hh (/ height 10))]
           [-h20 (- hh (/ height 20))])
      (image-select-polygon! image ADD
                             (map position-new
                                  (list w10 w20 w10 hw -w10 -w20 -w10 hw)
                                  (list -h10 hh h10 h20 h10 hh -h10 -h20))))))
     

;;; Procedure: image-series
;;; Parameters:
;;;     n: a positive integer
;;;     width: a positive integer describing the width of the image
;;;     height: a positive integer describing the height of the image
;;; Purpose: to generate interesting images that differ from one another depending on the value of n
;;; Produces: an image
;;; Preconditions: none
;;; Postconditions: 
;;;     The colors of our composition vary with different values of n
;;;     The number of lines drawn on the image will depend on n
;;;     The shape drawn by the turtle will depend on n
;;;     Images produced by image-series scale, that is (image-series n 400 400) should be similar to (image-series n 200 200)

(define image-series
  (λ (n width height)
    (let*
        ([image (image-show (image-new width height))]
         [rgb-lst (new-colors n)]
         [our-red (car rgb-lst)]
         [our-green (cadr rgb-lst)]
         [our-blue (caddr rgb-lst)]
         [n1 (modulo n 100)] ;this number (10-99) will be used for variation in the angle used by the turtle, corresponds to angle parameter for our-shapes
         [n2 (modulo n 10)] ;this number (0-9) will be used for variation in our number of lines, corresponds to the lines parameter for h- and v-lines procedures
         [turtle (turtle-new image)])
      (context-set-bgcolor! our-blue)
      (web n2 width height image our-red)
      (turtle-set-color! turtle our-green)
      (turtle-set-brush! turtle "2. Block 01")
      (cond
        [(< n 200) (our-shape-2! turtle width height n1)]
        [else (our-shape! turtle width height n1)])
      (image-select-x! image)
      (context-set-fgcolor! "white")
      (image-fill-selection! image)
      (image-select-nothing! image))))