base.ss
#lang scheme/base
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; SHP: Hypertext Processor
;;
;; a PHP like web framework for PLT Scheme
;;
;; Bonzai Lab, LLC.  All rights reserved.
;;
;; Licensed under LGPL.
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; base.ss - contains the base functionalities needed by the rest of the modules
;; yc 7/6/2010 - first version - refactored from handler.ss
(require "depend.ss"
         web-server/http/request-structs
         web-server/http/response-structs
         )

(define $chrome (make-parameter #f)) 

;; using a config object means that we will have more difficulty to retrieve the necessary
;; values if we are doing it as
;; what should shp hold?  it should hold a bunch of handlers...
;; where each handler basically maps to a single file...
;; different handler types can map to different extensions though!!!
;; this can get quite serious as a re-design!
;; one thing that it doesn't do yet is again to handle the continuations...
;; each handler should be mapped to a particular path so they can be used directly.
;; the path as currently defined starts from the root - i.e. it fully qualifies...
;; (we do not actually need to ensure that it fully qualifies when using it but it's
;; nice to store this way...

;; so far there are a few different types of scripts...
;; page scripts - these compiles down to pages (actually functions that return xexprs or request objects)
;; include scripts - they can be anything , but they cannot be called directly...
;; we want to introduce api scripts (and in the future we will introduce widget scripts).
;; each script should compile down to a script object, which should contain at least the following...
(define-struct shp (base config inner handlers namespace)
  #:property prop:procedure 
  (lambda ($struct request)
    ((shp-inner $struct) $struct request)))



;; what do I want to do??? it should be something like a reference!!!
;; that means we should be using a registry!
;; shp-config should be a registry... and then we use the registry-ref to retrieve the
;; values!!!
;;
(define (shp-config-ref shp key (default #f)) 
  (registry-ref (shp-config shp) key )) 

(define (shp-config-set! shp key val) 
  (registry-set! (shp-config shp) key val)) 

(define (shp-config-del! shp key) 
  (registry-del! (shp-config shp) key)) 

;; (define (shp-config-save! shp path)
;; (define (shp-config-load! shp path)


(define $server (make-parameter #f)) ;; this is the shp handler!??? no - but this is SHP.

(define __PATH__ (make-parameter #f))

(define (shp-default shp) 
  (shp-config-ref shp 'default "index"))

(define (shp-topfilter shp)
  (shp-config-ref shp 'topfilter))

(define (shp-required shp) 
  (shp-config-ref shp 'required))
;; htdocs
(define ($htdocs)
  (shp-config-ref ($server) 'htdocs))

(provide $htdocs)

(provide/contract
 ($chrome (parameter/c (or/c #f path-string?)))
 (struct shp ((base path-string?) 
              (config registry?)
              (inner (-> shp? request? response/c))
              (handlers registry?)
              (namespace namespace?)))
 (shp-config-ref (->* (shp? symbol?)
                      (any/c) 
                      any/c)) 
 (shp-config-set! (-> shp? symbol? any/c any)) 
 (shp-config-del! (-> shp? symbol? any)) 
 ($server (parameter/c any/c)) 
 (__PATH__ (parameter/c (or/c #f path-string?)))
 (shp-default (-> shp? path-string?))
 (shp-topfilter (-> shp? (or/c false/c path-string?)))
 (shp-required (-> shp? (or/c false/c path-string?)))
 )



;; these guys below should be moved elsewhere!
;; read all terms
(define (read-all in)
  (define (helper acc)
    (let ((term (read in)))
      (if (eof-object? term)
          (reverse acc)
          (helper (cons term acc)))))
  (helper '()))

;; convert file into complete terms
(define (file->values path)
  (call-with-input-file path read-all)) 

(provide read-all file->values)

(define (path-equiv? v)
  (or (path-string? v) (url? v)))


;; time to get the path mapping done correctly...
;; a path is consisted of the following:
;; a list of segments. (we are not using the segment values for now)...
;;
;; a partial will determine whether we want an exact match or not against the path.
;; each path will then be added against

(provide/contract 
 (path-equiv? (-> any/c any))
 )

;;