;;; my-cgit.el -- cgit helper functions -*- lexical-binding: t -*-

;; Copyright (C) 2023 Free Software Foundation.

;; Author: Yuchen Pei <id@ypei.org>
;; Package-Requires: ((emacs "28.2"))

;; This file is part of dotted.

;; dotted is free software: you can redistribute it and/or modify it under
;; the terms of the GNU Affero General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; dotted is distributed in the hope that it will be useful, but WITHOUT
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General
;; Public License for more details.

;; You should have received a copy of the GNU Affero General Public
;; License along with dotted.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;; cgit helper functions.

;;; Code:
(require 'vc-git)
(defun my-cgit-revision-url (revision file remote)
  "Returns the REMOTE cgit instance url of REVISION for FILE.

https://g.ypei.me/dotted.git/commit/?id=851b8f5fac389364c579aabb8e8fba344a3f6929"
  (let ((repo-url (vc-git-repository-url file remote)))
    (format "%s/commit/?id=%s" repo-url revision)))

(defun my-cgit-revision-url-default (&optional revision file remote)
  "Returns the REMOTE cgit instance url of REVISION for FILE.

Same as `my-cgit-revision-url', but all params can be nil, and
sensible defaults are set first."
  (setq file (or file (buffer-file-name) default-directory)
        revision (or revision (vc-working-revision file)))
  (my-cgit-revision-url revision file remote))

(defun my-cgit-branch-url (branch file remote)
  "Returns the REMOTE cgit instance url of BRANCH containing FILE.

https://g.ypei.me/librejs.git/?h=noscript-toggle"
  (let ((repo-url (vc-git-repository-url file remote)))
    (format "%s/?h=%s" repo-url branch)))

(defun my-cgit-branch-url-default (&optional branch file remote)
  "Returns the REMOTE cgit instance url of BRANCH containing FILE.

Same as `my-cgit-branch-url', but all params can be nil, and
sensible defaults are set first."
  (setq file (or file (buffer-file-name) default-directory)
        branch (or branch (car (vc-git-branches))))
  (my-cgit-branch-url branch file remote))

(defun my-cgit-file-url (file line-no revision remote)
  "Returns the REMOTE cgit instance url of the FILE at LINE-NO at REVISION.

https://g.ypei.me/librejs.git/tree/main_background.js?id=e2230c23e4aa7a74ea34825856acf7edd8a61e04#n78"
  (let* ((repo-root (vc-git-root file))
         (path (file-relative-name file repo-root))
         (repo-url (vc-git-repository-url file remote)))
    (format "%s/tree/%s?id=%s%s" repo-url path revision
            (if line-no (format "#n%d" line-no) ""))))

(defun my-cgit-file-url-default (&optional file line-no revision remote)
  "Returns the REMOTE cgit instance url of the FILE at LINE-NO at REVISION.

Same as `my-cgit-file-url', but all params can be nil, and
sensible defaults are set first."
  (unless (setq file (or file (buffer-file-name)))
    (error "Please supply a file"))
  (setq revision (or revision (vc-working-revision file)))
  (my-cgit-file-url file line-no revision remote))

(defun my-cgit-raw-file-url (file revision remote)
  "Returns the REMOTE cgit instance url of the raw FILE at REVISION.

https://g.ypei.me/librejs.git/plain/main_background.js?id=e2230c23e4aa7a74ea34825856acf7edd8a61e04"
  (let* ((repo-root (vc-git-root file))
         (path (file-relative-name file repo-root))
         (repo-url (vc-git-repository-url file remote)))
    (format "%s/plain/%s?id=%s" repo-url path revision)))

(defun my-cgit-raw-file-url-default (&optional file revision remote)
  "Returns the REMOTE cgit instance url of the raw FILE at REVISION.

Same as `my-cgit-raw-file-url', but all params can be nil, and
sensible defaults are set first."
  (unless (setq file (or file (buffer-file-name)))
    (error "Please supply a file"))
  (setq (revision (or revision (vc-working-revision file))))
  (my-cgit-raw-file-url file revision remote))

(defun my-cgit-revision-to-url (revision)
  "Returns the remote cgit instance url of REVISION.

Uses default remote."
  (let ((file (or (buffer-file-name) default-directory)))
    (my-cgit-revision-url revision file nil)))

(defun my-cgit-branch-to-url (branch)
  "Returns the remote cgit instance url of REVISION.

Uses default remote."
  (let ((file (or (buffer-file-name) default-directory)))
    (my-cgit-branch-url branch file nil)))

(defun my-cgit-file-to-url (file)
  "Returns the remote cgit instance url of FILE.

Uses default remote and currently checked out revision."
  (let ((revision (vc-working-revision file)))
    (my-cgit-file-url file nil revision nil)))

(defun my-cgit-current-file-to-url ()
  "Returns the remote cgit instance url of the current buffer file-loc.

Uses default remote and currently checked out revision."
  (let ((file (buffer-file-name))
        (line-no (1+ (current-line)))
        (revision (vc-working-revision file)))
    (unless file (error "Current buffer is not associated with any file"))
    (my-cgit-file-url file line-no revision nil)))

(defun my-cgit-file-to-raw-url (file)
  "Returns the remote cgit instance url of FILE.

Uses default remote and currently checked out revision."
  (let ((revision (vc-working-revision file)))
    (my-cgit-raw-file-url file revision nil)))

(defun my-cgit-current-file-to-raw-url ()
  "Returns the remote cgit instance url of the current buffer file.

Uses default remote and currently checked out revision."
  (let ((file (buffer-file-name))
        (revision (vc-working-revision file)))
    (unless file (error "Current buffer is not associated with any file"))
    (my-cgit-file-url file revision nil)))

(provide 'my-cgit)
;;; my-cgit.el ends here