#lang pollen/mode racket/base

;; Copyright (c) 2018 Joel Dueck.
;;
;; Licensed under the Apache License, Version 2.0 (the "License");
;; you may not use this file except in compliance with the License.
;; A copy of the License is included with this source code, in the
;; file "LICENSE.txt".
;; You may also obtain a copy of the License at
;;
;;       http://www.apache.org/licenses/LICENSE-2.0
;;
;; Unless required by applicable law or agreed to in writing, software
;; distributed under the License is distributed on an "AS IS" BASIS,
;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;; See the License for the specific language governing permissions and
;; limitations under the License.
;;
;; Author contact information:
;;   joel@jdueck.net
;;   https://joeldueck.com
;; -------------------------------------------------------------------------

;; Provides functions for fast preserving and fetching of article/series data.
;;  → Docs and metas go in (saved to SQLite database)
;;    HTML comes out →
;; Calling sites have no notion of the database or schema.

;; The functions provided by sqlite-tools.rkt are not safe for user-provided
;; data; a maliciously crafted input could bomb the database. This is acceptable
;; since the database is merely a disposable cache, and since all the input
;; will be coming from me.

(require pollen/setup
         pollen/core
         pollen/template
         pollen/pagetree
         racket/string
         "sqlite-tools.rkt"
         "template-html.rkt"
         "dates.rkt")

;; ~~~ Provides ~~~

(provide spell-of-summoning!
         crystalize-article!)

;; ~~~ Private use ~~~

(define DBFILE (build-path (current-project-root) "vitreous.sqlite"))

(define table_articles-fields
  '(pagenode
    title
    published
    updated
    doc_html
    author
    conceal
    series_pagenode
    noun_singular 
    note_count))

(define table_notes-fields
  '(pagenode
    note-id
    heading
    author
    date
    note_html))

(define table_series-fields
  '(pagenode
    title
    published
    noun_plural
    noun_singular))

(define table_articles (make-table-schema "articles" table_articles-fields))
(define table_notes (make-table-schema "notes" table_notes-fields #:primary-key-cols '(pagenode note-id)))
(define table_series (make-table-schema "series" table_series-fields))

(define (optional-meta m)
  (or (select-from-metas m (current-metas)) ""))

(define (series-noun)
  (define series-pagenode (->pagenode (or (select-from-metas 'series (current-metas)) "")))
  (case series-pagenode
    ['|| ""] ; no series specified
    [else (or (select-from-metas 'noun-singular series-pagenode) "")]))

;; ~~~ Provided functions: Initializing; Saving posts and notes

;; Initialize the database connection, creating the database if it doesn’t
;; exist, and executing the table schema queries
;;
(define (spell-of-summoning!)
  (init-db! DBFILE table_articles table_notes table_series))

;; Save an article (using current-doc and current-metas) and its notes (if any)
;; to the database, and return the rendered HTML.
;;
(define (crystalize-article! pagenode doc)
  (define header (html-article-header))
  (define footer (html-article-footer))
  (define body (->html (cdr doc)))
  ;; TK: store notes separately

  (define saving-query (make-insert/replace-query 'articles table_articles-fields))
  (query! saving-query
          (symbol->string pagenode)
          (optional-meta 'title)
          (select-from-metas 'published (current-metas))
          (optional-meta 'updated)
          (string-append header body footer)
          (optional-meta 'author)
          (optional-meta 'conceal)
          (optional-meta 'series)
          (series-noun)
          0) ; note_count
          
  `(@ ,header ,body ,footer))

