;;-*-Lisp-*-
(in-package goal)
(bundles "ENGINE.CGO" "GAME.CGO")
(require "kernel/gkernel-h.gc")
(require "engine/engine/connect.gc")

;; The settings system manages the state of settings like volume, language, and some other game state.
;; There are two special features of settings:
;; - To avoid changing a setting and forgetting to restore it, all changes must have an associated process. When that process dies, the settings is reverted.
;; - If there are no processes trying to set a setting, it will go to a "default" setting.
;; - We must catch the actual changing of settings once per frame, and possibly call functions for certains settings.

;; DECOMP BEGINS

;; The full setting state.
(deftype setting-data (structure)
  ((border-mode          symbol)
   (sfx-volume           float)
   (music-volume         float)
   (dialog-volume        float)
   (process-mask         process-mask)
   (common-page          int32)
   (language             language-enum)
   (screenx              int32)
   (screeny              int32)
   (vibration            symbol)
   (play-hints           symbol)
   (movie                (pointer process))
   (talking              (pointer process))
   (spooling             (pointer process))
   (hint                 (pointer process))
   (ambient              (pointer process))
   (video-mode           symbol)
   (aspect-ratio         symbol)
   (sound-flava          uint8)
   (auto-save            symbol)
   (music-volume-movie   float)
   (sfx-volume-movie     float)
   (music                symbol)
   (bg-r                 float)
   (bg-g                 float)
   (bg-b                 float)
   (bg-a                 float)
   (bg-a-speed           float)
   (bg-a-force           float)
   (allow-progress       symbol)
   (allow-pause          symbol)
   (sound-flava-priority float)
   (ocean-off            symbol)
   (allow-look-around    symbol)
   (ambient-volume       float)
   (ambient-volume-movie float)
   (dialog-volume-hint   float)
   (dummy                uint32 11))
  (:methods
   (update-from-engine (_type_ engine) setting-data)))

;; There are three copies of setting data:
;;  - default - if nothing is requesting a setting to be set, you end up with this value.
;;  - target  - the default settings, plus the changes from all processes
;;  - current - the actual settings. gets set to target on each frame.

;; The setting-control manages the current/target/default system.
;; The setting requests are managed by the engine.
(deftype setting-control (basic)
  ((current setting-data :inline)
   (target  setting-data :inline)
   (default setting-data :inline)
   (engine  engine))
  (:methods
   (new (symbol type int) _type_)
   (add-setting (_type_ process symbol object object object) none)
   (set-setting (_type_ process symbol object object object) none)
   (remove-setting (_type_ process symbol) none)
   (apply-settings (_type_) setting-data)
   (update (_type_) setting-data)))

(defmethod new setting-control ((allocation symbol) (type-to-make type) (max-connections int))
  "Allocate a new setting-control and its engine"
  (let ((s4-0 (object-new allocation type-to-make (the-as int (-> type-to-make size)))))
    (set! (-> s4-0 engine) ((method-of-type engine new) allocation engine 'setting-control max-connections))
    s4-0))

(defmacro setting-control-func! (func s &rest args)
  (let ((argb #f)
        (argi 0)
        (argf 0.0)
        (setting (car s)))
    (cond
      ;; ((or (eq? setting 'border-mode)
      ;;      (eq? setting 'allow-look-around)
      ;;      (eq? setting 'ocean-off)
      ;;      (eq? setting 'music)
      ;;      (eq? setting 'vibration)
      ;;      (eq? setting 'auto-save)
      ;;      (eq? setting 'allow-pause)
      ;;      (eq? setting 'allow-progress)
      ;;      (eq? setting 'play-hints)
      ;;      (eq? setting 'movie)
      ;;      (eq? setting 'talking)
      ;;      (eq? setting 'spooling)
      ;;      (eq? setting 'hint)
      ;;      (eq? setting 'ambient)
      ;;      )
      ;;   (set! argb (car args))
      ;;   )
      ;; ((or (eq? setting 'bg-r)
      ;;      (eq? setting 'bg-g)
      ;;      (eq? setting 'bg-b)
      ;;      (eq? setting 'bg-a)
      ;;      (eq? setting 'bg-a-speed)
      ;;      (eq? setting 'bg-a-force)
      ;;      )
      ;;   (set! argf (car args))
      ;;   )
      ;; ((or (eq? setting 'language)
      ;;      )
      ;;   (set! argi (car args))
      ;;   )
      ;; ((or (eq? setting 'sound-flava)
      ;;      )
      ;;   (set! argi (car args))
      ;;   (set! argf (cadr args))
      ;;   )
      ;; ((or (eq? setting 'process-mask)
      ;;      (eq? setting 'common-page)
      ;;      )
      ;;   (set! argb (car args))
      ;;   (set! argi (cadr args))
      ;;   )
      ;; ((or (eq? setting 'sfx-volume)
      ;;      (eq? setting 'music-volume)
      ;;      (eq? setting 'ambient-volume)
      ;;      (eq? setting 'dialog-volume)
      ;;      (eq? setting 'sfx-volume-movie)
      ;;      (eq? setting 'music-volume-movie)
      ;;      (eq? setting 'ambient-volume-movie)
      ;;      (eq? setting 'dialog-volume-hint)
      ;;      )
      ;;   (set! argb (car args))
      ;;   (set! argf (cadr args))
      ;;   )
      (#t (set! argb (car args)) (set! argf (cadr args)) (set! argi (caddr args))))
    `(,func *setting-control* (with-pp pp) ,s ,argb ,argf ,argi)))

(defmacro add-setting! (s &rest args)
  `(setting-control-func! add-setting ,s ,@args))

(defmacro set-setting! (s &rest args)
  `(setting-control-func! set-setting ,s ,@args))

(defmacro remove-setting! (s)
  `(remove-setting *setting-control* (with-pp pp) ,s))

;; used for memory card time information
(deftype scf-time (structure)
  ((stat   uint8)
   (second uint8)
   (minute uint8)
   (hour   uint8)
   (week   uint8)
   (day    uint8)
   (month  uint8)
   (year   uint8)))

(define-extern *setting-control* setting-control)
