; MIT License
; Copyright (C) 2022 Shintaro Mukai.
; https://mukai.systems/articles/ul1f05i2anhx83np0e2rjwxulsrp3weh/

; make file.

(import :datetime)
(import :html)
(import :markdown)
(import :xml)

(<- $root (path "../mukai.systems/")
    $now (.unix-time (datetime.now))
    $make-all? nil
    $article-index nil)

(function make? (file)
  (|| $make-all? (< $now (+ (.mtime file) (* 24 60 60)))))

(function tag->a (tag)
  `(a (href ,(str "/articles/?tag=" tag)) ,(str tag)))

(function tag->checkbox (tag)
  `((input (type "checkbox" id ,tag name ,tag))
    (label (for ,tag) ,tag)))

(function meta-article (p)
  (select1 (f (x) (= p (cadr x)))
           $article-index))

(function list-join (lis elt)
  (let (acc nil)
    (push! (car lis) acc)
    (dolist (x (cdr lis))
      (push! elt acc)
      (push! x acc))
    (reverse! acc)))

(function make-article-html (dir)
  (let (md (.resolve dir "index.md") html (.resolve dir "index.html"))
    (when (make? md)
      (write-line (.to-s dir))
      (with-open ($out html :write)
        (with-open ($in md :read)
          (let ((last-updated path title tags) (meta-article (.name dir)))
            (html.write (make-html
                          `((article ()
                                     ,@(collect (partial .read (.new MarkdownReader)))
                                     (div (class "footer")
                                          (div () "Tags: " ,@(list-join (map tag->a tags) ", "))
                                          (div () ,(str "Last updated: " last-updated)))))
                          :page :article
                          :title title))))))))

(function articles-template (args)
  `((section ()
             (h1 () "Articles")
             (details ()
                      (summary () "Tags")
                      (fieldset ()
                                (ul ()
                                    (li ()
                                        ,@(tag->checkbox "Writing"))
                                    (li ()
                                        ,@(tag->checkbox "Programming")
                                        (ul ()
                                            (li () ,@(tag->checkbox "Java"))
                                            (li () ,@(tag->checkbox "JavaScript"))
                                            (li () ,@(tag->checkbox "Lisp"))
                                            (li () ,@(tag->checkbox "Paren"))
                                            (li () ,@(tag->checkbox "Python")
                                                (li () ,@(tag->checkbox "Vim"))))))))
             (table ()
                    (thead () (tr () (th () "Page") (th (style "white-space:pre") "Last updated")))
                    (tbody () ,@(map (f (x)
                                       (let ((last-updated path title tags) x)
                                         `(tr (class ,(join (map str tags) " "))
                                              (td () (a (href ,(str "/articles/" path "/")) ,title))
                                              (td () ,last-updated))))
                                     args))))
    (script (src "/resources/scripts/article-index.js?v=1"))))

(function make-html (body :key page title)
  `(html (lang "ja")
         (head ()
               (meta (charset "UTF-8"))
               (meta (content "initial-scale=1, minimum-scale=1, user-scalable=no, width=device-width" name "viewport"))
               (meta (http-equiv "Cache-Control" content "no-cache"))
               (link (href "/favicon.ico" rel "shortcut icon"))
               (link (href "/resources/styles/application.css?v=1" rel "stylesheet"))
               ,(if (== page :ld) '(link (href "/resources/styles/ld.css?v=1" rel "stylesheet"))
                    (== page :article) '(link (href "/resources/styles/article.css?v=1" rel "stylesheet"))
                    (== page :article-index) '(link (href "/resources/styles/article-index.css?v=1" rel "stylesheet")))
               (title () ,(if title (format "%s - Mukai Systems" title) "Mukai Systems"))
               (script (src "https://www.googletagmanager.com/gtag/js?id=G-77100RSJCZ" async))
               (script (src "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML" async))
               (script (src "/resources/scripts/ga.js?v=1" type "text/javascript")))
         (body ()
               (header ()
                       (h1 () (a (href "/") "Mukai Systems"))
                       (nav ()
                            (ul ()
                                (li () (a (href "/about") "ABOUT"))
                                (li () (a (href "/articles") "BLOG"))
                                (li () (a (href "/services") "SERVICES"))
                                (li () (a (href "/contact") "CONTACT")))))
               (main (id "main") ,@body)
               (footer ()
                       (p () "Copyright 2020-2022 Mukai Systems.")))))

(function make-index-html (dir :key page)
  (let (p (.resolve dir "index.p") html (.resolve dir "index.html"))
    (when (|| (make? p) (= page :article-index))
      (write-line (.to-s p))
      (with-open ($out html :write)
        (with-open ($in p :read)
          (let (body (collect read))
            (when (== page :article-index)
              (<- body (reverse body)
                  $article-index body
                  body (articles-template body)))
            (html.write (make-html body :page page))))))))

(function make-sitemap ()
  (let (sitemap (.resolve $root "sitemap.xml"))
    (write-line (.to-s sitemap))
    (with-open ($out sitemap :write)
      (xml.write `(urlset (xmlns "http://www.sitemaps.org/schemas/sitemap/0.9")
                          (url () (loc () "https://mukai.systems/") (changefreq () "monthly"))
                          (url () (loc () "https://mukai.systems/about/") (changefreq () "weekly"))
                          (url () (loc () "https://mukai.systems/articles/") (changefreq () "weekly"))
                          (url () (loc () "https://mukai.systems/services/") (changefreq () "monthly"))
                          (url () (loc () "https://mukai.systems/contact/") (changefreq () "monthly"))
                          ,@(map (f (x)
                                   (let ((last-updated path title tags) x)
                                     `(url ()
                                           (loc () ,(str "https://mukai.systems/articles/" path "/"))
                                           (lastmod () ,last-updated))))
                                 $article-index))))))

(function! main (args)
  (<- $make-all? (car args))
  (make-index-html $root :page :ld)
  (make-index-html (.resolve $root "about"))
  (make-index-html (.resolve $root "articles") :page :article-index)
  (make-index-html (.resolve $root "services"))
  (make-index-html (.resolve $root "contact"))
  (dolist (dir (.children (.resolve $root "articles")))
    (if (.dir? dir) (make-article-html dir)))
  (make-sitemap))
