(import (scheme base)
        (chicken port)
        (chicken irregex)
        (chicken time posix)
        srfi-123
        srfi-69
        srfi-48
        srfi-18
        intarweb
        spiffy
        awful
        (awful sse)
        sxml-transforms)

;; Game
(define games (make-hash-table))

(define (init-game-table)
  (let ((game (make-hash-table)))
    game))

;; Webserver stuff
 (define (add-sse-resource! sse-path sse-proc vhost-root-path client-path)
   (add-resource! sse-path
		              (or vhost-root-path (root-path))
		              (lambda (#!optional given-path)
		                (let ((accept (header-values 'accept
						                                     (request-headers (current-request)))))
		                  ;; If client's EventSource (JS code) requested SSE page...
		                  (if (memq 'text/event-stream accept)
			                    ;;...complete handshake & keep connection alive with 'sse-proc'.
                          (lambda ()
			                      (with-headers '((content-type text/event-stream)
					                                  (cache-control no-cache)
					                                  (connection keep-alive))
					                                (lambda ()
					                                  (write-logged-response)
					                                  (sse-proc))))
			                    (redirect-to client-path))))
		              'GET
		              #f))

(define (pagescript sse-path color)
  #<#EOF
  eventsource ssevent from #{sse-path}

    on unlockMessage as string
      if it is "#{color}"
        set #board.data-locked to 'false'
      end
    end

  end
EOF
  )

(define (render-sxml sxml)
  (with-output-to-string
    (lambda ()
      (SXML->HTML sxml))))

(define (board sse-path color)
  (let ()
      `(div (@ (id "content")
               (class "row"))
            (div (@ (id "leftbank")
                    (class "col-2 m-0")))
            (div (@ (id "board")
                    (data-locked ,(if (eqv? color "white") "true" "false"))
                    (class "col-8 m-0 p-0")))
            (div (@ (id "rightbank")
                    (class "col-2 m-0"))))))

(define (game-proc code)
  (print "Returning sse-proc")
  (lambda ()
    (let loop ()
      (send-sse-data (render-positions)
       id: (seconds->string) event: "boardChange")
      (thread-sleep! 2)
      (loop))))

(define (init-game code)
  (let ((game (or (and (hash-table-exists? games code)
                       (~ games code))
                  #f))
        (sse-path (string-append "/sse-" code))
        (sse-proc (game-proc code)))
    (print "Game:" game)
    (if game
        (board sse-path "white")
        (let ((game (init-game-table)))
          (print "Initialized game to " game ", adding SSE resource.")
          (set! (~ game 'sse-proc) (add-sse-resource! sse-path sse-proc #f sse-path))
          (set! (~ game 'code) code)
          (set! (~ games code) game)
          (board sse-path "yellow")))))

(define-page "/start-game"
  (lambda ()
    (let ((gamecode ($ 'gamecode as-string)))
      (init-game gamecode))))

(define-page "/"
  (lambda ()
    (lambda ()
      (send-static-file "resources/html/coinage.html")))
  no-template: #t)

(define-page "/css/coinage.css"
  (lambda ()
    (lambda ()
      (send-static-file "resources/css/coinage.css"))))

(define-page (irregex "/images/.*")
  (lambda (file)
    (print "Trying to fetch file " file "...")
    (lambda ()
      (print "Fetching " file "...")
      (send-static-file (string-append "resources" file)))))
