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

(defun ennum-link-find (type path info)
  "Find link of TYPE and PATH in post object stored in :ennum-posts of
property list INFO."
  (seq-find (lambda (link)
              (and (eq (ennum-link-type link) type)
                   (string= (ennum-link-path link) path)))
            (ennum-post-links (plist-get info :ennum-post))))

(defmacro ennum-link-follow (path)
  `(ennum-with-current-directory (ennum-setting :working-directory)
     (find-file ,path)))

(defun ennum-link-export-gemini (path desc backend info)
  (let ((url (format "gemini:%s" path)))
    (pcase backend
      ((or 'ennum-html 'html)
       (xmlgen `(a :href ,url
                   ,(or desc url))))
      ((or 'ennum-gemini 'gemini)
       (format "=> %s %s" url desc)))))

(defun ennum-link-follow-gemini (path)
  (browse-url (format "gemini:%s" path)))

;; TODO: Pass title through org-export-data-with-backend or something
;; similar in order to export org syntax in title
;; See fist-2017 post
(defun ennum-link-export-post (path desc backend info)
  (let ((post-url (url-encode-url
                   (expand-file-name* path (ennum-setting :posts-directory)))))
    (pcase backend
      ((or 'ennum-html 'html)
       (xmlgen `(a :href ,post-url
                   ,desc)))
      ((or 'ennum-gemini 'gemini)
       (format "=> %s.gmi %s" post-url desc)))))

(defun ennum-link-follow-post (path)
  (ennum-link-follow (expand-file-name (concat path ".org")
                                       (ennum-setting :posts-directory))))

(defun ennum-link-export-image (path desc backend info)
  (let ((image-url (url-encode-url
                    (expand-file-name*
                     (ennum-image-output-filename
                      path (ennum-setting :image-width))
                     (ennum-setting :images-directory))))
        (image-link-url (expand-file-name*
                         (ennum-image-output-filename
                          path (ennum-setting :image-link-width))
                         (ennum-setting :images-directory))))
    (pcase backend
      ((or 'ennum-html 'html)
       (xmlgen `(a :href ,image-link-url
                   (img :src ,image-url))))
      ((or 'ennum-gemini 'gemini)
       (format "=> %s" image-link-url)))))

(defun ennum-link-follow-image (path)
  (ennum-link-follow (expand-file-name path (ennum-setting :images-directory))))

(defun ennum-link-export-thumbnail (path _desc backend info)
  (let ((image-url (url-encode-url
                    (expand-file-name*
                     (ennum-image-output-filename
                      path (ennum-setting :image-thumbnail-width))
                     (ennum-setting :images-directory)))))
    (pcase backend
      ((or 'ennum-html 'html)
       (xmlgen `(img :src ,image-url)))
      ((or 'ennum-gemini 'gemini)
       (format "=> %s" image-url)))))

(defun ennum-link-export-video (path desc backend info)
  (let ((video-url (url-encode-url
                    (expand-file-name* path (ennum-setting :videos-directory)))))
    (pcase backend
      ((or 'ennum-html 'html)
       (xmlgen
        `(video :src ,video-url
                :poster ,(url-encode-url
                          (expand-file-name*
                           (ennum-video-link-poster
                            (ennum-link-find 'video path info))
                           (ennum-setting :images-directory)))
                :preload "none"
                :controls "")))
      ((or 'ennum-gemini 'gemini)
       (format "=> %s" video-url)))))

(defun ennum-link-follow-video (path)
  (ennum-link-follow (expand-file-name path
                                       (ennum-setting :videos-directory))))

(defun ennum-link-export-pdf (path desc backend info)
  (let ((link-path (url-encode-url
                    (expand-file-name* path (ennum-setting :static-directory)))))
    (pcase backend
      ((or 'ennum-html 'html)
       (xmlgen `(object :data ,link-path
                        :type "application/pdf"
                        :width ,(ennum-setting :pdf-width)
                        :height ,(ennum-setting :pdf-height)
                        "Download " (a :href ,link-path ,path))))
      ((or 'ennum-gemini 'gemini)
       (format "=> %s" link-path)))))

(defun ennum-link-export-static (path desc backend info)
  (let ((file-url (url-encode-url
                   (expand-file-name* path (ennum-setting :static-directory)))))
    (pcase backend
      ((or 'ennum-html 'html)
       (xmlgen `(a :href ,file-url ,desc)))
      ((or 'ennum-gemini 'gemini)
       (format "=> %s %s" file-url desc)))))

(defun ennum-link-export-tag (tag desc backend info)
  (let ((tag-url (url-encode-url
                  (expand-file-name* tag (ennum-setting :tag-directory)))))
    (pcase backend
      ((or 'ennum-html 'html)
       (xmlgen `(a :href ,tag-url ,(or desc tag))))
      ((or 'ennum-gemini 'gemini)
       (format "=> %s.gmi %s" tag-url (or desc tag))))))

(org-link-set-parameters
 "gemini"
 :export 'ennum-link-export-gemini
 :follow 'ennum-link-follow-gemini)

(org-link-set-parameters
 "post"
 :export 'ennum-link-export-post
 :follow 'ennum-link-follow-post)

(org-link-set-parameters
 "image"
 :export 'ennum-link-export-image
 :follow 'ennum-link-follow-image)

(org-link-set-parameters
 "thumbnail"
 :export 'ennum-link-export-thumbnail
 :follow 'ennum-link-follow-image)

(org-link-set-parameters
 "video"
 :export 'ennum-link-export-video
 :follow 'ennum-link-follow-video)

(org-link-set-parameters
 "pdf" :export 'ennum-link-export-pdf)

(org-link-set-parameters
 "static" :export 'ennum-link-export-static)

(org-link-set-parameters
 "tangle" :export 'ennum-link-export-static)

(org-link-set-parameters
 "tag" :export 'ennum-link-export-tag)

(provide 'ennum-link)
