(define-module (dtao-guile configuration transform)
  #:use-module (srfi srfi-1)
  #:use-module (ice-9 match)
  #:use-module (ice-9 exceptions)
  #:use-module (dtao-guile utils)
  #:use-module (dtao-guile configuration)
  #:use-module (dtao-guile configuration blocks)
  #:export (
	    dtao-config->alist
	    configuration->alist))

;; Convert a render handler expression into a procedure sexp
(define (render->exp proc)
  (if
   (not proc)
   proc
   `(. (lambda () ,proc))))

;; Convert a click handler expression into a procedure sexp
(define (click->exp proc)
  (if
   (not proc)
   proc
   `(. (lambda (button) ,proc))))

(define*
  (configuration->alist
   #:key
   (transform-value #f)
   (type #f)
   (config '())
   (source '()))
  (remove
   ;; The %location field is autogenerated and is not needed.
   ;; Same goes for the modules. They are already imported once
   ;; the configuration is transformed.
   (lambda (pair) (let ((x (car pair)))
		    (or (equal? x "%location")
			(equal? x "modules"))))
   (fold-right
    (lambda (field acc)
      (append
       (let ((value ((record-accessor type field) config)))
	 `((,(remove-question-mark (symbol->string field))
	    . ,(if (not transform-value)
		   value
		   (transform-value field value source)))))
       acc))
    '()
    (record-type-fields type))))

(define (transform-block field value source)
  (match
      field
    ('render (render->exp value))
    ('click (click->exp value))
    (_ value)))

(define (transform-config field value source)
  (match
      field
    ('left-blocks (map (lambda (block) (dtao-block->alist block source)) value))
    ('center-blocks (map (lambda (block) (dtao-block->alist block source)) value))
    ('right-blocks (map (lambda (block) (dtao-block->alist block source)) value))
    (_ value)))

;; TODO: Add value transformer
(define (dtao-block->alist block source)
  (configuration->alist
   #:type <dtao-block>
   #:transform-value transform-block
   #:config block
   #:source source))

(define (dtao-config->alist config)
  (configuration->alist
   #:type <dtao-config>
   #:transform-value transform-config
   #:config config
   #:source config))
