;; -*- lexical-binding: t -*-

;;; Vars and setup
(use-package htmlize :ensure t)

(defvar jao-blog-base-dir (expand-file-name "www" jao-doc-dir))
(defvar jao-blog-publish-dir (expand-file-name "jao.io" jao-blog-base-dir))
(defun jao-blog-dir (p) (expand-file-name p jao-blog-base-dir))
(defun jao-blog-publish-dir (p) (expand-file-name p jao-blog-publish-dir))


(defvar jao-org-blog-tag-files
  (seq-difference (directory-files (jao-blog-publish-dir "blog") nil "tag-.*")
                  "tag-norss.html"))

(defvar jao-org-blog-tags
  (mapcar (lambda (f)
            (string-match "tag-\\(.+\\)\\.html" f)
            (format "<a href=\"/blog/%s\">%s</a>"
                    f (match-string 1 f)))
          jao-org-blog-tag-files))

(defvar jao-org-blog-tag-rss
  (mapcar (lambda (f)
            (string-match "\\(.+\\)-rss\\.xml" f)
            (format "<a href=\"/blog/%s\">%s</a>"
                    f (match-string 1 f)))
          (directory-files (jao-blog-publish-dir "blog") nil ".*-rss.xml")))

(defvar jao-org-blog-tag-names
  (mapcar (lambda (f)
            (string-match "tag-\\(.+\\)\\.html" f)
            (match-string 1 f))
          jao-org-blog-tag-files))

;;; Header
(setq org-static-blog-page-header
      (concat
       "<meta name=\"author\" content=\"jao\">\n"
       "<meta name=\"referrer\" content=\"no-referrer\">\n"
       "<link rel=\"stylesheet\" href=\"/static/style.css\""
       "  type=\"text/css\">\n"
       "<link rel=\"apple-touch-icon\" sizes=\"180x180\""
       "  href=\"/static/apple-touch-icon.png\" >\n"
       "<link rel=\"icon\" type=\"image/png\""
       "  sizes=\"32x32\" href=\"/static/favicon-32x32.png\">\n"
       "<link rel=\"icon\" type=\"image/png\""
       "  sizes=\"16x16\" href=\"/static/favicon-16x16.png\">\n"
       "<link rel=\"icon\" href=\"/static/favicon.ico\">\n"
       "<link rel=\"manifest\" href=\"/static/site.webmanifest\">\n")

      org-static-blog-page-preamble
      (concat
       "<div class=\"header\">"
       "  <a href=\"https://jao.io\">programming (and other) musings</a>"
       "  <div class=\"sitelinks\">"
       "    <a href=\"/blog/about.html\">about</a>"
       "    | <a href=\"/blog/hacking.html\">hacking</a>"
       "    | <a href=\"/blog/archive.html\">archive</a>"
       "    | <div class=\"dropdown\">"
       "       <a href=\"/blog/tags.html\" class=\"dropbtn\">tags</a>"
       "       <div class=\"dropdown-content\">"
       (mapconcat #'identity jao-org-blog-tags "")
       "       </div>"
       "      </div>"
       "    | <div class=\"dropdown\">"
       "       <a href=\"/blog/rss.xml\" class=\"dropbtn\">rss</a>"
       "       <div class=\"dropdown-content\">"
       (mapconcat #'identity jao-org-blog-tag-rss "")
       "       </div>"
       "      </div>"
       "  </div>"
       "</div>"))

;;; Footer
(setq org-static-blog-page-postamble
      (with-temp-buffer
        (insert-file-contents "~/.emacs.d/commons.html")
        (buffer-string)))

;;; Package
(use-package org-static-blog
  :ensure t
  :init
  (setq org-static-blog-use-preview t
        org-static-blog-preview-link-p t
        org-static-blog-preview-start "<!-- preview-start -->"
        org-static-blog-preview-end "<!-- preview-end -->"
        org-static-blog-preview-date-first-p t
        org-static-blog-index-length 30
        org-static-blog-preview-convert-titles t
        org-static-blog-preview-ellipsis "more ..."
        org-static-blog-enable-tags t
        org-static-blog-tags-file "tags.html"
        org-static-blog-rss-file "rss.xml"
        org-static-blog-publish-url "https://jao.io/blog/"
        org-static-blog-publish-title "programming (and other) musings"
        org-static-blog-posts-directory (jao-blog-dir "posts/")
        org-static-blog-drafts-directory (jao-blog-dir "pages/")
        org-static-blog-publish-directory (jao-blog-publish-dir "blog/")
        org-static-blog-rss-extra "" ; "<author>mail@jao.io</author>\n"
        org-static-blog-rss-max-entries 30
        org-static-blog-rss-excluded-tag "norss"
        org-static-blog-enable-tag-rss t
        org-export-with-toc nil
        org-export-with-section-numbers nil)

  :config
  (defun jao-org-static-post-path (pf dt)
    (cond ((string-match-p "pages/.*\\|in-no-particular-order" pf)
           (file-name-nondirectory pf))
          ((string-match-p "drafts/.*" pf) pf)
          ((string-match-p "^[[:digit:]]+-.*" pf) pf)
          (t (concat (format-time-string "%Y-%m-%d-" dt)
                     (file-name-nondirectory pf)))))
  (advice-add 'org-static-blog-generate-post-path :override
              #'jao-org-static-post-path)

  :bind (:map org-mode-map (("C-c B" . jao-transient-org-blog))))

;;; New entries
(defun jao-org-blog-publish-file (fname)
  (interactive (list (read-file-name "Publish: " nil (buffer-file-name) t)))
  (let ((geiser-active-implementations '(guile))
        (geiser-default-implementation 'guile)
        (whitespace-style nil))
    (org-static-blog-publish-file fname)))

(defconst jao-org-static-blog--prev-beg "#+html: <!-- preview-start -->")

(defconst jao-org-static-blog--prev-end "#+html: <!-- preview-end -->")

(defun jao-org-static-blog-create-new-post (&optional draft)
  (interactive)
  (let* ((title (read-string "Title: "))
         (file (replace-regexp-in-string "\s" "-" (downcase title)))
         (tags (completing-read-multiple "Tags: " jao-org-blog-tag-names)))
    (find-file (expand-file-name (concat file ".org")
                                 (if draft
                                     org-static-blog-drafts-directory
                                   org-static-blog-posts-directory)))
    (insert "#+title: " title "\n"
            "#+date: " (format-time-string "<%Y-%m-%d %H:%M>") "\n"
            "#+filetags: "
            (mapconcat #'identity tags " ")
            "\n\n")
    (when (member "books" tags)
      (insert jao-org-static-blog--prev-beg "\n\n[[../img/" file ".jpg]]\n\n"))
    (save-excursion (insert jao-org-static-blog--prev-end "\n"))))

;;; Drafts
(defun jao-org-static-blog-update-date ()
  (interactive)
  (goto-char (point-min))
  (when (re-search-forward "^#\\+date: " nil t)
    (org-kill-line)
    (insert (format-time-string "<%Y-%m-%d %H:%M>"))
    (save-buffer)))

(defun jao-org-static-blog-create-new-draft ()
  (interactive)
  (jao-org-static-blog-create-new-post t))

(defun jao-org-static-blog-publish-draft ()
  (interactive)
  (let* ((from (read-file-name "Post: "
                               org-static-blog-drafts-directory
                               nil t))
         (to (expand-file-name (file-name-nondirectory from)
                               org-static-blog-posts-directory)))
    (rename-file from to)
    (when-let* ((b (get-buffer from)))
      (kill-buffer b))
    (find-file to)
    (jao-org-static-blog-update-date)
    (when (y-or-n-p "Generate HTML? ")
      (jao-org-blog-publish))))

(defun jao-org-static-blog-edit-draft ()
  (interactive)
  (find-file (read-file-name "Edit: "
                             org-static-blog-drafts-directory
                             nil
                             t)))

;;; Publish
(defun jao-org-blog-publish (&optional force)
    (interactive "P")
    (let ((geiser-active-implementations '(guile))
          (geiser-default-implementation 'guile)
          (whitespace-style nil))
      (org-static-blog-publish force)))

(defun jao-org-blog-republish ()
  (interactive)
  (jao-org-blog-publish t))

;;; Transient
(defun jao-org-static-prev-begin ()
  (interactive)
  (insert jao-org-static-blog--prev-beg))

(defun jao-org-static-prev-end ()
  (interactive)
  (insert jao-org-static-blog--prev-end))

(transient-define-prefix jao-transient-org-blog ()
  [["Insert blog snippet"
    ("s" "preview begin" jao-org-static-prev-begin)
    ("S" "preview end" jao-org-static-prev-end)
    ("T" "update date" jao-org-static-blog-update-date)]
   ["Edit blog"
    ("n" "create post" jao-org-static-blog-create-new-post)
    ("d" "create draft" jao-org-static-blog-create-new-draft)
    ("e" "edit draft" jao-org-static-blog-edit-draft)]
   ["Publish blog"
    ("D" "publish draft" jao-org-static-blog-publish-draft)
    ("f" "publish single file" jao-org-blog-publish-file)
    ("p" "publish all" jao-org-blog-publish)
    ("r" "republish" jao-org-blog-republish)]])

;;; .
(provide 'jao-custom-blog)
