#lang scheme

;;Ensayo para definir un tipo de datos: Frame, Script
;; Lo llamaré "escena"
;; Una escena tiene: un lugar típico, un tiempo típico
;; predomina un hacer: lo hecho, para y porque, y con qué
;; tiene actores típicos

;; Una escena es un tipo de estructura
;;Estructuras de datos
(define-struct escena
  (;fields
   id 
   lugar
;   lo-hecho
;   para-que
;   por-que
;   con-que
   rol-actor
   accion-actor
;   rol-actor2
   )
  #:transparent)

(define guion-en-ascensor
  (list
   (make-escena 'ascensor-primera
                'un-ascensor
                'protagonista
                (lambda (a) 
                  (printf "Al entrar, el actor como ~a dice: ~a~n" a
                  (saludo 'inicial))))
   (make-escena 'ascensor-continuacion
                'un-ascensor
                'secundario
                (lambda (a) 
                  (printf "Otro hombre abandona el ascensor y el actor como ~a contesta: ~a~n" a
                  (saludo 'intermedia))))
   (make-escena 'ascensor-ultima
                'un-ascensor
                'protagonista
                (lambda (a) (printf "El actor como ~a abandona el ascensor y dice: ~a~n" a
                  (saludo 'final))))))

(define saludo
  (lambda (escena)
    (let ((saludos-verbales-iniciales '("hola" "buenos días" "buenas tardes"))
          (saludos-verbales-despedida '("adiós" "buen día" "hasta luego"))
          )
      (cond
        ((eq? escena 'inicial) (list-ref saludos-verbales-iniciales (random 3)))
        ((eq? escena 'final) (list-ref saludos-verbales-despedida (random 3)))
        ((eq? escena 'intermedia) (list-ref saludos-verbales-despedida (random 3)))
        )
      )
    ))

(define guion%
  (class object%
    (init-field
     (id 'identificador-del-guion))
    (field
     (aplicable? #t)
     (escenas 'lista-ordenada-de-escenas)
     (actores 'lista-de-actores-requeridos);p. ej. protagonista y antagonista
     )
    (define/public restriccion
      (lambda (booleano)
        (set! aplicable? booleano)
        ))
    (define/public set-escenas
      (lambda (secuencia)
        (set! escenas secuencia)
        ))
    (define/public set-actores
      (lambda (lista)
        (set! actores lista)
        ))
    (define/private make-escena
      (lambda (escena)
        (let ((rol-actor (escena-rol-actor escena))
              (accion-actor (escena-accion-actor escena))
              )
          (accion-actor rol-actor)
          )
        ))
    (define/public accion!
      (lambda ()
        (if aplicable?
            (let itera ((curso-accion escenas)
                        )
              (if (null? curso-accion)
                  'hecho
                  (begin
                    (make-escena (first curso-accion))
                    (itera (rest curso-accion))
                    )
                  )
              )
            "No se puede aplicar el guión")
        )
      )
    (super-new)
    ))
                       
(define en-el-ascensor
  (make-object guion% 'guion-en-ascensor))

(send en-el-ascensor set-escenas guion-en-ascensor)

(send en-el-ascensor accion!)

(send en-el-ascensor restriccion #f)

(send en-el-ascensor accion!)