#lang racket/gui
(require (planet williams/animated-canvas/animated-canvas)
         (planet williams/science/histogram))
(define histogram-widget%
  (class vertical-panel%
        (init-field label)
    (init-field n)
    (init-field min-range)
    (init-field max-range)
    (init parent)
    (init (font normal-control-font))
        (super-instantiate (parent))
        (define message
      (instantiate message%
        (label this)))
    (define canvas 
      (instantiate animated-canvas%
        (this)
        (style '(border))))
        (send this reflow-container)
        (define histogram
      (make-histogram-with-ranges-uniform n min-range max-range))
        (define (draw-histogram (scale 1))
      (let* ((dc (send canvas get-dc))
             (width (exact->inexact (send canvas get-width)))
             (height (exact->inexact (send canvas get-height)))
             (bin-width (/ width n))
             (bin-delta (/ (exact->inexact (- max-range min-range)) n))
             (half-bin-delta (/ bin-delta 2))
             (max-value (histogram-max histogram))
             (sum-value (histogram-sum histogram))
             (mean (histogram-mean histogram))
             (sigma (histogram-sigma histogram))
             (cum-value 0))
        (when (> sum-value 0.0)
          (send dc set-pen "White" 1 'solid)
          (for ((i (in-range n)))
            (let ((bin-center (+ min-range (* i bin-delta) half-bin-delta))
                  (bin-value (histogram-get histogram i)))
              (set! cum-value (+ cum-value bin-value))
              (unless (= bin-value 0)
                (let ((x1 (* i bin-width))
                      (bin-height (* scale (/  bin-value max-value) height))
                      (color
                       (cond ((<= bin-center (- mean (* 2.0 sigma))) "Red")
                             ((<= bin-center (- mean sigma)) "Yellow")
                             ((< bin-center (+ mean sigma)) "Green")
                             ((< bin-center (+ mean (* 2.0 sigma))) "Yellow")
                             (else "Red"))))
                  (send dc set-brush color 'solid)
                  (send dc draw-rectangle
                        x1 (- height bin-height)
                        bin-width height)))))
          (send dc set-pen "Blue" 1 'solid)
          (let ((x (* (/ (- mean min-range) (- max-range min-range)) width)))
            (send dc draw-line x 0.0 x height)))
        (send canvas swap-bitmaps)))
        (define/public (reset)
      (set! histogram
            (make-histogram-with-ranges-uniform n min-range max-range))
      (draw-histogram))
        (define/public (set-value value)
      (histogram-increment! histogram value)
      (draw-histogram))))
(provide (all-defined-out))