;;-*-Lisp-*-
(in-package goal)


;;

(defglobalconstant DEBUG_PAGE_ROWS #f)

(defconstant FONT_SIZE_HEADER 0.6) ;; font size for the decoration text
(defconstant FONT_SIZE_OPTION 0.5) ;; font size for regular options
(defconstant FONT_SIZE_OPTION_EXTRA 0.35) ;; font size for option sub-text
(defconstant HIGHLIGHT_SIZE 18) ;; default highlight size for options
(defconstant HIGHLIGHT_SIZE_LARGE 33)


;;


(defun draw-page-border ((hud-bounds hud-box) (alpha float))
  (let ((x-pos 70)
        (y-pos 112)
        (width 375)
        (background-height 200))
    (when (= (get-aspect-ratio) 'aspect16x9)
      (set! x-pos 79)
      (set! y-pos 86)
      (set! width 356)
      (set! background-height 255))
    (#when PC_PORT
      ;; added for better widescreen handling
      (when (not (-> *pc-settings* use-vis?))
        (set! x-pos (the int (adjust-game-x (the float x-pos))))
        (set! width (the int (* (-> *pc-settings* aspect-ratio-reciprocal) width)))))
    (set-vector! (-> hud-bounds color) 128 128 64 (the int (* 128.0 alpha)))
    ;; Top Line
    (set! (-> hud-bounds min x) (the float x-pos))
    (set! (-> hud-bounds max x) (the float (+ x-pos width)))
    (set! (-> hud-bounds min y) (the float y-pos))
    (set! (-> hud-bounds max y) (the float y-pos))
    (with-dma-buffer-add-bucket ((buffer-1 (-> *display* frames (-> *display* on-screen) global-buf))
                                 (bucket-id hud-draw-hud-alpha))
      (draw-box-prim-only hud-bounds buffer-1))
    ;; Bottom Line
    (set! (-> hud-bounds min x) (the float x-pos))
    (set! (-> hud-bounds max x) (the float (+ x-pos width)))
    (set! (-> hud-bounds min y) (the float (+ y-pos background-height)))
    (set! (-> hud-bounds max y) (the float (+ y-pos background-height)))
    (with-dma-buffer-add-bucket ((buffer-2 (-> *display* frames (-> *display* on-screen) global-buf))
                                 (bucket-id hud-draw-hud-alpha))
      (draw-box-prim-only hud-bounds buffer-2)))
  (none))

(defun draw-page-background ((alpha float))
  (let ((x-pos 70)
        (y-pos 112)
        (width 375)
        (background-height 200))
    (when (= (get-aspect-ratio) 'aspect16x9)
      (set! x-pos 79)
      (set! y-pos 86)
      (set! width 356)
      (set! background-height 256))
    (#when PC_PORT
      ;; added for better widescreen handling
      (when (not (-> *pc-settings* use-vis?))
        (set! x-pos (the int (adjust-game-x (the float x-pos))))
        (set! width (the int (* (-> *pc-settings* aspect-ratio-reciprocal) width)))))
    (with-dma-buffer-add-bucket ((buffer (-> *display* frames (-> *display* on-screen) global-buf))
                                 (bucket-id bucket7))
      (draw-sprite2d-xy buffer x-pos y-pos width background-height
        (new 'static 'rgba :r #x80 :g #x80 :b #x40 :a (the int (* 64.0 alpha))) #x3fffff)
        ))
  (none))

(defun draw-page-header ((font-ctx font-context) (text text-id) (alpha float))
  (let ((x-pos 70)
        (y-pos 82)
        (width 375))
    (when (= (get-aspect-ratio) 'aspect16x9)
      (set! x-pos 79)
      (set! y-pos 55)
      (set! width 356))
    ; (progress-method-42 (-> *progress-process*) (-> *progress-work* header) (* 64.0 alpha))
    ; (progress-method-41 (-> *progress-process*) (-> *progress-work* header) (* 128.0 alpha))
    (set-scale! font-ctx FONT_SIZE_HEADER)
    (set! (-> font-ctx origin y) (the float y-pos))
    (set-color! font-ctx (font-color font-color-32))
    (print-game-text (lookup-text! *common-text* text #f) font-ctx #f 44 (bucket-id hud-draw-hud-alpha)))
  (none))

(defun draw-scrolling-page-up-down-arrows ((font-ctx font-context) (draw-up? symbol) (draw-down? symbol))
  (let ((new-x-pos 250.0)
        (new-y-pos-up 100)
        (new-y-pos-down 211)
        (new-scale 0.5)
        (old-scale (-> font-ctx scale))
        (old-x-pos (-> font-ctx origin x))
        (old-y-pos (-> font-ctx origin y)))
    (when (= (get-aspect-ratio) 'aspect16x9)
      (set! new-x-pos 251.5)
      (set! new-y-pos-up 75)
      (set! new-y-pos-down 265))
    (set! (-> font-ctx scale) new-scale)
    (when draw-up?
      (set! (-> font-ctx origin x) (the float new-x-pos))
      (set! (-> font-ctx origin y) (the float new-y-pos-up))
      (let ((print-text-fn print-game-text))
        (format (clear *progress-generic-temp-string*) "~33L~C" 160)
        (print-text-fn *progress-generic-temp-string* font-ctx #f 44 (bucket-id hud-draw-hud-alpha))))
    (when draw-down?
      (set! (-> font-ctx origin x) (the float new-x-pos))
      (set! (-> font-ctx origin y) (the float (+ new-y-pos-up new-y-pos-down)))
      (let ((print-text-fn-1 print-game-text))
        (format (clear *progress-generic-temp-string*) "~33L~C" 162)
        (print-text-fn-1 *progress-generic-temp-string* font-ctx #f 44 (bucket-id hud-draw-hud-alpha))))
    (set! (-> font-ctx origin x) old-x-pos)
    (set! (-> font-ctx origin y) old-y-pos)
    (set! (-> font-ctx scale) old-scale))
  (none))

;; The boundary info could be moved to the menu-option, every one of these is duplicate code
(defun begin-scissor-scrolling-page ((hud-bounds hud-box))
  (cond
    ((= (get-aspect-ratio) 'aspect16x9)
     (set! (-> hud-bounds min x) 19.0)
     (set! (-> hud-bounds min y) 86.0)
     (set! (-> hud-bounds max x) 494.0)
     (set! (-> hud-bounds max y) 340.0))
    (else
     (set! (-> hud-bounds min x) 70.0)
     (set! (-> hud-bounds min y) 112.0)
     (set! (-> hud-bounds max x) 444.0)
     (set! (-> hud-bounds max y) 312.0)))
  (#when PC_PORT
    (set! (-> hud-bounds min x) (the float (the int (adjust-game-x (-> hud-bounds min x)))))
    (set! (-> hud-bounds max x) (the float (the int (adjust-game-x (-> hud-bounds max x))))))
  (with-dma-buffer-add-bucket ((buffer (-> *display* frames (-> *display* on-screen) global-buf))
                               (bucket-id hud-draw-hud-alpha))
    (setup-scissor hud-bounds buffer))
  (none))

(defun end-scissor-scrolling-page ((hud-bounds hud-box) (arg1 float))
  (with-dma-buffer-add-bucket ((buffer (-> *display* frames (-> *display* on-screen) global-buf))
                               (bucket-id hud-draw-hud-alpha)
                               )
    (restore-scissor hud-bounds buffer))
  (none))

(defun-debug draw-generic-page-row-line ((y-coord int))
  (#when DEBUG_PAGE_ROWS
    (with-dma-buffer-add-bucket ((buf (-> *display* frames (-> *display* on-screen) global-buf))
                                (bucket-id debug-no-zbuf2))
      (draw-sprite2d-xy buf 0 y-coord 512 1 (static-rgba #xff #xff #xff #x40) #x3fffff)))
  0)

(defmethod draw-option ((obj menu-generic-scrolling-page) (progress progress) (font-ctx font-context) (arg3 int) (arg4 symbol))
  (when (or (zero? (-> obj mounted?)) (not (-> obj mounted?)))
    (on-mount! obj))
  ;; the list has a total of 200px of y-height
  ;; with 10px of margin at the top and bottom, that leaves 180 / 4 = 45px per item
  ;; it's the responsibility of each generic component to center itself within these 45px lines
  (when (not (-> *progress-pc-generic-store* clear-screen?))
    (let* ((font-alpha (fmax 0.0 (* 2.0 (- 0.5 (-> progress menu-transition)))))
           (hud-bounds (new 'stack-no-clear 'hud-box))
           (max-page-size (if (= (get-aspect-ratio) 'aspect16x9) 7 5))
           (margin-top-bottom 0.0)
           (line-height (/ (if (= (get-aspect-ratio) 'aspect16x9) 253.0 200.0) max-page-size)))
    (set! (-> font-ctx alpha) font-alpha)
    (set-color! font-ctx (font-color font-color-32))
    ;; header
    (draw-page-header font-ctx (-> obj name) font-alpha)
    ;; background borders
    (draw-page-border (-> obj box 0) font-alpha)
    ;; background
    (draw-page-background font-alpha)
    (begin-scissor-scrolling-page hud-bounds)
    (if (= (get-aspect-ratio) 'aspect16x9)
        (set! (-> font-ctx origin y) (+ 86.0 margin-top-bottom))
        (set! (-> font-ctx origin y) (+ 112.0 margin-top-bottom)))

    ;; do scrolling. if we notice we need to scroll too much, we just snap immediately instead of smoothly stepping.
    (cond
      ((> (-> *progress-pc-generic-store* current-menu-scroll-index) (-> *progress-pc-generic-store* current-menu-hover-index))
        (if (>= (fabs (- (-> *progress-pc-generic-store* current-menu-scroll-index) (the float (-> *progress-pc-generic-store* current-menu-hover-index)))) 2.0)
            (set! (-> *progress-pc-generic-store* current-menu-scroll-index) (the float (-> *progress-pc-generic-store* current-menu-hover-index)))
            (seek-ease! (-> *progress-pc-generic-store* current-menu-scroll-index) (the float (-> *progress-pc-generic-store* current-menu-hover-index)) (* 0.125 (-> PP clock time-adjust-ratio)) 0.3 (* 0.00125 (-> PP clock time-adjust-ratio)))))
      ((< (+ (-> *progress-pc-generic-store* current-menu-scroll-index) (1- max-page-size)) (-> *progress-pc-generic-store* current-menu-hover-index))
        (if (>= (fabs (- (-> *progress-pc-generic-store* current-menu-scroll-index) (the float (- (-> *progress-pc-generic-store* current-menu-hover-index) (1- max-page-size))))) 2.0)
            (set! (-> *progress-pc-generic-store* current-menu-scroll-index) (the float (- (-> *progress-pc-generic-store* current-menu-hover-index) (1- max-page-size))))
            (seek-ease! (-> *progress-pc-generic-store* current-menu-scroll-index) (the float (- (-> *progress-pc-generic-store* current-menu-hover-index) (1- max-page-size))) (* 0.125 (-> PP clock time-adjust-ratio)) 0.3 (* 0.00125 (-> PP clock time-adjust-ratio)))))
      )

    ;; render items
    (let* ((start-index (the int (-> *progress-pc-generic-store* current-menu-scroll-index)))
            ;; we add 1 because the scroll effect will reveal 1 extra
           (end-index (min (-> obj menu-options length) (+ start-index max-page-size 1))))
      ;; scroll adjust
      (-! (-> font-ctx origin y) (* line-height (fabs (- (-> *progress-pc-generic-store* current-menu-scroll-index) start-index))))
      (while (< start-index end-index)
        (let ((menu-option (-> obj menu-options start-index)))
          (when (nonzero? menu-option)
            ;; save the y,x position as who knows where it will end up after the component finishes rendering
            (let ((old-y-pos (-> font-ctx origin y))
                  (old-x-pos (-> font-ctx origin x)))
              (draw-option menu-option progress font-ctx start-index
                           (= (-> obj selected-option-index) start-index))
              ;; move to the next line
              (set! (-> font-ctx origin y) (+ old-y-pos line-height))
              ;; - debugging, draw the dividing lines to make centering new items easier
              (draw-generic-page-row-line (the int (-> font-ctx origin y)))
              (set! (-> font-ctx origin x) old-x-pos)
              ;; reset the font color
              (set-color! font-ctx (font-color font-color-32)))))
        (+! start-index 1)))
    ;; end
    (end-scissor-scrolling-page hud-bounds 1.0)
    (set-flags! font-ctx (font-flags kerning large))
    (let ((draw-up-arrow? (< 0 (-> *progress-pc-generic-store* current-menu-hover-index)))
          (draw-down-arrow? (< (-> *progress-pc-generic-store* current-menu-hover-index) (1- (-> obj menu-options length)))))
      (draw-scrolling-page-up-down-arrows font-ctx draw-up-arrow? draw-down-arrow?))))
  (none))

(defun draw-generic-highlight ((y-pos int) (height int) (alpha float))
  (let ((x-pos (if (= (get-aspect-ratio) 'aspect4x3)
                   70
                   50))
        (width (if (= (get-aspect-ratio) 'aspect4x3)
                   374
                   500)))
    (when (not (-> *pc-settings* use-vis?))
      (set! x-pos (the int (adjust-game-x (the float x-pos))))
      (set! width (the int (* (-> *pc-settings* aspect-ratio-reciprocal) width))))
    (with-dma-buffer-add-bucket ((buffer (-> *display* frames (-> *display* on-screen) global-buf))
                                 (bucket-id hud-draw-hud-alpha)
                                 )
      (draw-sprite2d-xy buffer x-pos y-pos width height
        (new 'static 'rgba :r #x80 :g #x80 :b #x40 :a (the int (* 64.0 alpha))) #x3fffff))))

(defmethod draw-option ((obj menu-generic-boolean-option) (arg0 progress) (font-ctx font-context) (option-index int) (selected? symbol))
  (when (not (-> obj mounted?))
    (on-mount! obj))
  (let ((alpha (* 2.0 (- 0.5 (-> arg0 menu-transition))))
        (line-height 18.0))
    (fmax! alpha 0.0)
    (set! (-> font-ctx alpha) alpha)
    (set-flags! font-ctx (font-flags kerning middle large))
    (set-scale! font-ctx FONT_SIZE_OPTION)
    (+! (-> font-ctx origin y) (if (= (get-aspect-ratio) 'aspect4x3) 7.0 5.0))
    (cond
      (selected?
        (set-color! font-ctx (font-color font-color-34))
        (draw-generic-highlight (the int (- (-> font-ctx origin y) 2.0)) HIGHLIGHT_SIZE_LARGE alpha)
        (print-game-text (lookup-text! *common-text* (-> obj name) #f) font-ctx #f 44 (bucket-id hud-draw-hud-alpha))
        (+! (-> font-ctx origin y) line-height)
        (set! *progress-generic-temp-string* (clear *progress-generic-temp-string*))
        (if (-> obj value)
            (format *progress-generic-temp-string* "~33L~S~44L ~S" (lookup-text! *common-text* (-> obj truthy-text) #f) (lookup-text! *common-text* (-> obj falsey-text) #f))
            (format *progress-generic-temp-string* "~44L~S ~33L~S~1L" (lookup-text! *common-text* (-> obj truthy-text) #f) (lookup-text! *common-text* (-> obj falsey-text) #f))))
      ;; hover case
      (else
        (cond
          ((and (nonzero? (-> obj should-disable?))
                (-> obj should-disable?)
                ((-> obj should-disable?)))
           (set-color! font-ctx (font-color font-color-44))
           (when (= option-index (-> *progress-pc-generic-store* current-menu-hover-index))
            (draw-generic-highlight (the int (+ -2.0 (-> font-ctx origin y))) HIGHLIGHT_SIZE (* 0.5 alpha))))
          ((= option-index (-> *progress-pc-generic-store* current-menu-hover-index))
            (set-color! font-ctx (font-color font-color-33))
            (draw-generic-highlight (the int (+ -2.0 (-> font-ctx origin y))) HIGHLIGHT_SIZE alpha))
          (else
            (set-color! font-ctx (font-color font-color-32))))
        (print-game-text (lookup-text! *common-text* (-> obj name) #f) font-ctx #f 44 (bucket-id hud-draw-hud-alpha))
        (+! (-> font-ctx origin y) line-height)
        (set! *progress-generic-temp-string* (clear *progress-generic-temp-string*))
        (let ((actual-value (call-get-value-fn obj)))
          (if actual-value
            (format *progress-generic-temp-string* "~1L~S~44L ~S" (lookup-text! *common-text* (-> obj truthy-text) #f) (lookup-text! *common-text* (-> obj falsey-text) #f))
            (format *progress-generic-temp-string* "~44L~S ~1L~S~1L" (lookup-text! *common-text* (-> obj truthy-text) #f) (lookup-text! *common-text* (-> obj falsey-text) #f))))))
    (set-scale! font-ctx FONT_SIZE_OPTION_EXTRA)
    (print-game-text *progress-generic-temp-string* font-ctx #f 44 (bucket-id hud-draw-hud-alpha)))
  (none))

(defmethod draw-option ((obj menu-generic-carousel-option)
                        (progress progress)
                        (font-ctx font-context)
                        (option-index int)
                        (selected? symbol))
  (when (not (-> obj mounted?))
    (on-mount! obj))
  (let ((alpha (fmax (* 2.0 (- 0.5 (-> progress menu-transition))) 0.0)))
    (set! (-> font-ctx scale) 0.45)
    (set! (-> font-ctx alpha) alpha)
    (+! (-> font-ctx origin y) 5.0)
    (set-flags! font-ctx (font-flags kerning middle large))
    ;; the item label
    (cond
      (selected?
       (set! (-> font-ctx color) (font-color font-color-34))
       (draw-generic-highlight (the int (- (-> font-ctx origin y) 2.0)) HIGHLIGHT_SIZE_LARGE alpha))
      ((and (nonzero? (-> obj should-disable?))
            (!= (-> obj should-disable?) #f)
            ((-> obj should-disable?)))
       (set-color! font-ctx (font-color font-color-32))
       (when (= option-index (-> *progress-pc-generic-store* current-menu-hover-index))
         (draw-generic-highlight (the int (+ -2.0 (-> font-ctx origin y))) HIGHLIGHT_SIZE (* 0.5 alpha))))
      ((= option-index (-> *progress-pc-generic-store* current-menu-hover-index))
       (set! (-> font-ctx color) (font-color font-color-33))
       (draw-generic-highlight (the int (- (-> font-ctx origin y) 2.0)) HIGHLIGHT_SIZE alpha)))
    (print-game-text (lookup-text! *common-text* (-> obj name) #f) font-ctx #f 44 (bucket-id hud-draw-hud-alpha))
    (+! (-> font-ctx origin y) 18.0)
    (set! (-> font-ctx scale) 0.35)
    (set! (-> font-ctx color) (font-color font-color-34))
    ;; the value
    (cond
      ((or (< (-> obj item-index) 0) (> (-> obj item-index) (num-items obj)))
       (print-game-text (lookup-text! *common-text* (text-id progress-multiselect-no-items-found) #f) font-ctx #f 44 (bucket-id hud-draw-hud-alpha)))
      ((and selected? (>= (-> obj item-index) 0) (< (-> obj item-index) (num-items obj)))
        (format (clear *progress-generic-temp-string*) "~33L~C ~S ~33L~C" 163 (get-item-label obj (-> obj item-index)) 161)
        (print-game-text *progress-generic-temp-string* font-ctx #f 44 (bucket-id hud-draw-hud-alpha)))
      (else
        (let ((actual-index (call-get-item-index-fn obj)))
          (print-game-text (get-item-label obj actual-index) font-ctx #f 44 (bucket-id hud-draw-hud-alpha))))))
  (none))

(defun draw-generic-simple-string-option ((option menu-generic-option) (progress progress) (font-ctx font-context) (option-index int) (str string))
  (let ((alpha (* 2.0 (- 0.5 (-> progress menu-transition))))
        (line-height 23.0))
    (fmax! alpha 0.0)
    (set! (-> font-ctx alpha) alpha)
    (set-flags! font-ctx (font-flags kerning middle large))
    (set-scale! font-ctx FONT_SIZE_OPTION)
    (+! (-> font-ctx origin y) (if (= (get-aspect-ratio) 'aspect4x3) 14.0 11.0))
    (cond
      ((and (nonzero? (-> option should-disable?))
            (!= (-> option should-disable?) #f)
            ((-> option should-disable?)))
      (set-color! font-ctx (font-color font-color-44))
      (when (= option-index (-> *progress-pc-generic-store* current-menu-hover-index))
        (draw-generic-highlight (the int (+ -2.0 (-> font-ctx origin y))) HIGHLIGHT_SIZE (* 0.5 alpha))))
      ((= option-index (-> *progress-pc-generic-store* current-menu-hover-index))
        (set-color! font-ctx (font-color font-color-33))
        (draw-generic-highlight (the int (+ -2.0 (-> font-ctx origin y))) HIGHLIGHT_SIZE alpha))
      (else
        (set-color! font-ctx (font-color font-color-32))))
    (print-game-text str font-ctx #f 44 (bucket-id hud-draw-hud-alpha)))
  (none))

(defmethod draw-option ((obj menu-generic-link-option) (progress progress) (font-ctx font-context) (option-index int) (selected? symbol))
  (when (not (-> obj mounted?))
    (on-mount! obj))
  (draw-generic-simple-string-option obj progress font-ctx option-index (lookup-text! *common-text* (-> obj name) #f))
  (none))

(defmethod draw-option ((obj menu-generic-button-option) (progress progress) (font-ctx font-context) (option-index int) (selected? symbol))
  (when (not (-> obj mounted?))
    (on-mount! obj))
  (draw-generic-simple-string-option obj progress font-ctx option-index (lookup-text! *common-text* (-> obj name) #f))
  (none))

(defmethod draw-option ((obj menu-generic-confirm-option) (progress progress) (font-ctx font-context) (option-index int) (selected? symbol))
  (when (not (-> obj mounted?))
    (on-mount! obj))
  ;; drawn different depending on whether or not the confirmation prompt is open
  (cond
    (selected?
     ;; TODO - this is duplicate code with the boolean option, but i ran out of arguments, make a struct or something later
     (let ((alpha (* 2.0 (- 0.5 (-> progress menu-transition))))
           (line-height 18.0))
       (fmax! alpha 0.0)
       (set! (-> font-ctx alpha) alpha)
       (set-flags! font-ctx (font-flags kerning middle large))
       (set-scale! font-ctx FONT_SIZE_OPTION)
       (+! (-> font-ctx origin y) (if (= (get-aspect-ratio) 'aspect4x3) 7.0 5.0))
       (cond
         (selected?
           (set-color! font-ctx (font-color font-color-33))
           (draw-generic-highlight (the int (- (-> font-ctx origin y) 2.0)) HIGHLIGHT_SIZE_LARGE alpha)
           (print-game-text (lookup-text! *common-text* (-> obj name) #f) font-ctx #f 44 (bucket-id hud-draw-hud-alpha))
           (+! (-> font-ctx origin y) line-height)
           (set! *progress-generic-temp-string* (clear *progress-generic-temp-string*))
           (if (-> obj confirmed?)
               (format *progress-generic-temp-string* "~33L~S~35L ~S" (lookup-text! *common-text* (text-id progress-yes) #f) (lookup-text! *common-text* (text-id progress-no) #f))
               (format *progress-generic-temp-string* "~35L~S ~33L~S~1L" (lookup-text! *common-text* (text-id progress-yes) #f) (lookup-text! *common-text* (text-id progress-no) #f))))
         ;; hover case
         (else
           (cond
             ((and (nonzero? (-> obj should-disable?))
                   (!= (-> obj should-disable?) #f)
                   ((-> obj should-disable?)))
              (set-color! font-ctx (font-color font-color-32))
              (when (= option-index (-> *progress-pc-generic-store* current-menu-hover-index))
                (draw-generic-highlight (the int (+ -1.0 (-> font-ctx origin y))) HIGHLIGHT_SIZE (* 0.5 alpha))))
             ((= option-index (-> *progress-pc-generic-store* current-menu-hover-index))
               (set-color! font-ctx (font-color font-color-33))
               (draw-generic-highlight (the int (+ -1.0 (-> font-ctx origin y))) HIGHLIGHT_SIZE alpha))
             (else
               (set-color! font-ctx (font-color font-color-34))))
           (print-game-text (lookup-text! *common-text* (-> obj name) #f) font-ctx #f 44 (bucket-id hud-draw-hud-alpha))
           (+! (-> font-ctx origin y) line-height)
           (set! *progress-generic-temp-string* (clear *progress-generic-temp-string*))
           (if (-> obj confirmed?)
               (format *progress-generic-temp-string* "~1L~S~35L ~S" (lookup-text! *common-text* (text-id progress-yes) #f) (lookup-text! *common-text* (text-id progress-no) #f))
               (format *progress-generic-temp-string* "~35L~S ~1L~S~1L" (lookup-text! *common-text* (text-id progress-yes) #f) (lookup-text! *common-text* (text-id progress-no) #f)))))
       (set-scale! font-ctx FONT_SIZE_OPTION_EXTRA)
       (print-game-text *progress-generic-temp-string* font-ctx #f 44 (bucket-id hud-draw-hud-alpha))))
    (else
     (draw-generic-simple-string-option obj progress font-ctx option-index (lookup-text! *common-text* (-> obj name) #f))))
  (none))

(defmethod draw-option ((obj menu-generic-slider-option) (arg0 progress) (font-ctx font-context) (option-index int) (selected? symbol))
  (when (not (-> obj mounted?))
    (on-mount! obj))
  (let ((alpha (fmax 0.0 (* 2.0 (- 0.5 (-> arg0 menu-transition)))))
        (slider-value (if selected? (-> obj value) (call-get-value-fn obj))))
    (set! (-> font-ctx alpha) alpha)
    (set-scale! font-ctx FONT_SIZE_OPTION)
    (+! (-> font-ctx origin y) 20.0)
    (case (get-aspect-ratio)
      (('aspect4x3))
      (('aspect16x9)))
    (set-flags! font-ctx (font-flags kerning middle large))
    (cond
      (selected?
        (set-scale! font-ctx FONT_SIZE_OPTION_EXTRA)
        (+! (-> font-ctx origin y) (if (= (get-aspect-ratio) 'aspect4x3) -15.0 -15.0))
        (set-color! font-ctx (font-color font-color-33))
        (draw-generic-highlight (the int (+ -2.0 (-> font-ctx origin y))) HIGHLIGHT_SIZE_LARGE alpha)
        (if (= (-> obj show-decimal?) #t)
          (print-game-text (string-format "~S: ~,,2f" (lookup-text! *common-text* (-> obj name) #f) slider-value) font-ctx #f 44 (bucket-id hud-draw-hud-alpha))
          (print-game-text (string-format "~S: ~D" (lookup-text! *common-text* (-> obj name) #f) slider-value) font-ctx #f 44 (bucket-id hud-draw-hud-alpha)))
        (set! (-> obj bar-sprite tex) (get-texture hud-sliderbackground progress-minimap))
        (set! (-> obj bar-sprite scale-x) 2.0)
        (set! (-> obj bar-sprite scale-y) 0.5)
        (let ((sprite-color-0 (-> obj bar-sprite color-ptr)))
          (set! (-> sprite-color-0 0) 128)
          (set! (-> sprite-color-0 1) 128)
          (set! (-> sprite-color-0 2) 128)
          (set! (-> sprite-color-0 3) 128)
          )
        (set! (-> obj bar-sprite pos z) #x3fffff)
        (set! (-> obj bar-sprite pos w) 0)
        (set! (-> obj bar-cursor-sprite tex) (get-texture hud-sliderframe progress-minimap))
        (set! (-> obj bar-cursor-sprite scale-x) 0.2)
        (set! (-> obj bar-cursor-sprite scale-y) 1.0)
        (let ((sprite-color-1 (-> obj bar-cursor-sprite color-ptr)))
          (set! (-> sprite-color-1 0) 128)
          (set! (-> sprite-color-1 1) 128)
          (set! (-> sprite-color-1 2) 128)
          (set! (-> sprite-color-1 3) 128)
          )
        (set! (-> obj bar-cursor-sprite pos z) #x3fffff)
        (set! (-> obj bar-cursor-sprite pos w) 0)
        ;; bar
        (set-hud-piece-position! (-> obj bar-sprite) (the int (adjust-game-x 135.0)) (+ (the int (-> font-ctx origin y)) (if (= (get-aspect-ratio) 'aspect4x3) 18 15)))
        ;; calculate the percentage of the bar based on the range
        ;; (actual + abs(range-min)) / (range-max + abs(range-min)) = percentage
        (let* ((percentage (/ (+ slider-value (fabs (-> obj min-value)))
                              (+ (-> obj max-value) (fabs (-> obj min-value)))))
               ;; cursor (135 -> 365) = 230 pixels
               (cursor-x-pos (adjust-game-x-int (+ 135 (* (if (= (get-aspect-ratio) 'aspect4x3) 230.0 231.0) percentage))))
               (bar-remainder (- (adjust-game-x-int 365) cursor-x-pos)))
          ;; cursor position
          (set-hud-piece-position! (-> obj bar-cursor-sprite) cursor-x-pos (+ (the int (-> font-ctx origin y)) (if (= (get-aspect-ratio) 'aspect4x3) 14 11)))
          (with-dma-buffer-add-bucket ((buffer (-> *display* frames (-> *display* on-screen) global-buf))
                                     (bucket-id hud-draw-hud-alpha))
            (draw (-> obj bar-sprite) buffer (-> *level* level-default) #t)
            ;; bar mask
            ;; TODO - bar remainder isnt correct on custom aspect ratios since those internally still return `aspect4x3` for (get-aspect-ratio), this is a larger issue though
            ;; perhaps just standardize menu size in general and ditch aspect ratio differences.
            (draw-sprite2d-xy buffer (+ cursor-x-pos 10) (+ (the int (-> font-ctx origin y)) (if (= (get-aspect-ratio) 'aspect4x3) 23 20)) (+ bar-remainder (if (= (get-aspect-ratio) 'aspect4x3) 9 6)) 6
              (new 'static 'rgba :r (the int (* 0.0 alpha slider-value))
                                :g (the int (* 0.0 alpha slider-value))
                                :b (the int (* 0.0 alpha slider-value))
                                :a (the int (* 128.0 alpha)))
                                #x3fffff)
            (draw (-> obj bar-cursor-sprite) buffer (-> *level* level-default) #t))))
      (else
        (+! (-> font-ctx origin y) -8.0)
        (cond
          ((and (nonzero? (-> obj should-disable?))
                (!= (-> obj should-disable?) #f)
                ((-> obj should-disable?)))
          (set-color! font-ctx (font-color font-color-44))
          (when (= option-index (-> *progress-pc-generic-store* current-menu-hover-index))
            (draw-generic-highlight (the int (+ -1.0 (-> font-ctx origin y))) HIGHLIGHT_SIZE (* 0.5 alpha))))
          ((= option-index (-> *progress-pc-generic-store* current-menu-hover-index))
            (set-color! font-ctx (font-color font-color-33))
            (draw-generic-highlight (the int (+ -2.0 (-> font-ctx origin y))) HIGHLIGHT_SIZE alpha))
          (else
            (set-color! font-ctx (font-color font-color-32))))
        (if (= (-> obj show-decimal?) #t)
          (print-game-text (string-format "~S: ~,,2f" (lookup-text! *common-text* (-> obj name) #f) slider-value) font-ctx #f 44 (bucket-id hud-draw-hud-alpha))
          (print-game-text (string-format "~S: ~D" (lookup-text! *common-text* (-> obj name) #f) slider-value) font-ctx #f 44 (bucket-id hud-draw-hud-alpha)))))
    )
  (none))

(defmethod draw-option ((obj menu-generic-details-page) (progress progress) (font-ctx font-context) (option-index int) (selected? symbol))
  (when (or (zero? (-> obj mounted?)) (not (-> obj mounted?)))
    (on-mount! obj))
  ;; the list has a total of 200px of y-height
  ;; with 10px of margin at the top and bottom, that leaves 180 / 4 = 45px per item
  ;; it's the responsibility of each generic component to center itself within these 45px lines
  (when (not (-> *progress-pc-generic-store* clear-screen?))
    (let* ((font-alpha (fmax 0.0 (* 2.0 (- 0.5 (-> progress menu-transition)))))
           (hud-bounds (new 'stack-no-clear 'hud-box))
           (max-page-size (if (= (get-aspect-ratio) 'aspect16x9) 12 10))
           (margin-top-bottom 0.0)
           (line-height (/ (if (= (get-aspect-ratio) 'aspect16x9) 253.0 200.0) max-page-size)))
    (set! (-> font-ctx alpha) font-alpha)
    (set-color! font-ctx (font-color font-color-32))
    ;; header
    (draw-page-header font-ctx (-> obj name) font-alpha)
    ;; background borders
    (draw-page-border (-> obj box 0) font-alpha)
    ;; background
    (draw-page-background font-alpha)
    (begin-scissor-scrolling-page hud-bounds)
    (if (= (get-aspect-ratio) 'aspect16x9)
      (set! (-> font-ctx origin y) (+ 86.0 margin-top-bottom))
      (set! (-> font-ctx origin y) (+ 112.0 margin-top-bottom)))
    ;; render items
    (let* ((entry-index (max 0 (* (/ (-> *progress-pc-generic-store* current-menu-hover-index) max-page-size) max-page-size)))
           (end-index (min (-> obj entries length) (+ entry-index max-page-size))))
      (while (< entry-index end-index)
        (let ((entry (-> obj entries entry-index)))
          (when (nonzero? entry)
            ;; save the y,x position as who knows where it will end up after the component finishes rendering
            (let ((old-y-pos (-> font-ctx origin y))
                  (old-x-pos (-> font-ctx origin x)))
              (draw-option entry progress font-ctx entry-index
                           (= (-> obj selected-entry-index) entry-index))
              ;; move to the next line
              (set! (-> font-ctx origin y) (+ old-y-pos line-height))
              ;; - debugging, draw the dividing lines to make center new items easier
              (draw-generic-page-row-line (the int (-> font-ctx origin y)))
              (set! (-> font-ctx origin x) old-x-pos)
              ;; reset the font color
              (set-color! font-ctx (font-color font-color-32)))))
        (+! entry-index 1)))
    ;; end
    (end-scissor-scrolling-page hud-bounds 1.0)
    (set-flags! font-ctx (font-flags kerning large))
    (let* ((draw-up-arrow? (and (not (zero? (-> *progress-pc-generic-store* current-menu-hover-index)))
                                (>= (-> *progress-pc-generic-store* current-menu-hover-index) max-page-size)))
           (last-page-remainder (mod (-> obj entries length) max-page-size))
           (last-page-starting-index (if (zero? last-page-remainder)
                                         (- (-> obj entries length) max-page-size)
                                         (- (-> obj entries length) last-page-remainder)))
           (draw-down-arrow? (and (> (-> obj entries length) max-page-size)
                                  (< (-> *progress-pc-generic-store* current-menu-hover-index) last-page-starting-index))))
      (draw-scrolling-page-up-down-arrows font-ctx draw-up-arrow? draw-down-arrow?))))
  (none))

(defmethod draw-option ((obj menu-generic-details-keybind-entry) (progress progress) (font-ctx font-context) (option-index int) (selected? symbol))
  (when (or (zero? (-> obj mounted?)) (not (-> obj mounted?)))
    (on-mount! obj))
  ;; TODO - implement `should-disable?` if it's ever relevant (its not right now)
  (let ((alpha (* 2.0 (- 0.5 (-> progress menu-transition))))
        (line-height 23.0))
    (fmax! alpha 0.0)
    (set! (-> font-ctx alpha) alpha)
    (set-scale! font-ctx 0.40)
    (cond
      ((= option-index (-> *progress-pc-generic-store* current-menu-hover-index))
        (set-color! font-ctx (font-color font-color-33))
        (draw-generic-highlight (the int (+ 2.0 (-> font-ctx origin y))) 18 alpha))
      (else
        (set-color! font-ctx (font-color font-color-32))))
    ;; Print left aligned text
    (set-flags! font-ctx (font-flags kerning middle-vert large))
    (-! (-> font-ctx origin y) 1.0)
    (set! (-> font-ctx origin x) (the float (adjust-game-x (if (= (get-aspect-ratio) 'aspect16x9) 25.0 80.0))))
    (print-game-text (get-keybind-string obj) font-ctx #f 44 (bucket-id hud-draw-hud-alpha))
    ;; Now print the right aligned text
    (set! (-> font-ctx origin x) (the float (adjust-game-x (if (= (get-aspect-ratio) 'aspect16x9) 490.0 438.0))))
    (+! (-> font-ctx origin y) 6.0)
    (set-flags! font-ctx (font-flags kerning right large))
    (let ((bind (pc-get-current-bind (-> obj bind-info) *pc-cpp-temp-string*)))
      (cond
        (selected?
         (print-game-text (string-format "~S...(~Ds)" (lookup-text! *common-text* (text-id progress-keybinds-waiting-for-bind) #f)
                                                      (inc (/ (- (seconds 5) (- (current-time) (-> *progress-pc-generic-store* keybind-select-time))) TICKS_PER_SECOND)))
                          font-ctx #f 44 (bucket-id hud-draw-hud-alpha)))
        ((not bind)
         (print-game-text (lookup-text! *common-text* (text-id progress-keybinds-unset) #f) font-ctx #f 44 (bucket-id hud-draw-hud-alpha)))
        ((string= *pc-cpp-temp-string* "unknown")
         (print-game-text (lookup-text! *common-text* (text-id progress-unknown-option) #f) font-ctx #f 44 (bucket-id hud-draw-hud-alpha)))
        (else
         (print-game-text *pc-cpp-temp-string* font-ctx #f 44 (bucket-id hud-draw-hud-alpha))))))
  (none))

(defmethod draw-option ((obj menu-generic-details-confirm-entry) (progress progress) (font-ctx font-context) (option-index int) (selected? symbol))
  (when (or (zero? (-> obj mounted?)) (not (-> obj mounted?)))
    (on-mount! obj))
  ;; TODO - implement `should-disable?` if it's ever relevant (its not right now)
  (let ((alpha (* 2.0 (- 0.5 (-> progress menu-transition))))
        (line-height 23.0))
    (fmax! alpha 0.0)
    (set! (-> font-ctx alpha) alpha)
    (set-scale! font-ctx 0.40)
    (cond
      ((= option-index (-> *progress-pc-generic-store* current-menu-hover-index))
        (set-color! font-ctx (font-color font-color-33))
        (draw-generic-highlight (the int (+ 2.0 (-> font-ctx origin y))) 18 alpha))
      (else
        (set-color! font-ctx (font-color font-color-32))))
    ;; Print left aligned text
    (set-flags! font-ctx (font-flags kerning middle-vert large))
    (-! (-> font-ctx origin y) 1.0)
    (set! (-> font-ctx origin x) (the float (adjust-game-x (if (= (get-aspect-ratio) 'aspect16x9) 25.0 80.0))))
    (print-game-text (lookup-text! *common-text* (-> obj name) #f) font-ctx #f 44 (bucket-id hud-draw-hud-alpha))
    (when selected?
      ;; Now print the right aligned text, if the option is selected
      (set! (-> font-ctx origin x) (the float (adjust-game-x (if (= (get-aspect-ratio) 'aspect16x9) 430.0 438.0))))
      (+! (-> font-ctx origin y) 6.0)
      (set-flags! font-ctx (font-flags kerning right large))
      (clear *progress-generic-temp-string*)
      (if (-> obj confirmed?)
        (format *progress-generic-temp-string* "~33L~S~35L ~S" (lookup-text! *common-text* (text-id progress-yes) #f) (lookup-text! *common-text* (text-id progress-no) #f))
        (format *progress-generic-temp-string* "~35L~S ~33L~S~1L" (lookup-text! *common-text* (text-id progress-yes) #f) (lookup-text! *common-text* (text-id progress-no) #f)))
      (print-game-text *progress-generic-temp-string* font-ctx #f 44 (bucket-id hud-draw-hud-alpha))))
  (none))


(defmethod draw-option ((obj menu-generic-to-resolutions-option) (progress progress) (font-ctx font-context) (option-index int) (selected? symbol))
  ;; change the name depending on whether we're fullscreen or not
  (cond
    ((and (= (-> obj name) (text-id progress-window-size)) (fullscreen?))
      (set! (-> obj name) (text-id progress-game-res)))
    ((and (= (-> obj name) (text-id progress-game-res)) (not (fullscreen?)))
      (set! (-> obj name) (text-id progress-window-size))))
  (call-parent-method obj progress font-ctx option-index selected?))

