;; Add MELPA package repo
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)

;; Install use-package if not already installed
(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

(require 'use-package)
(setq use-package-always-ensure t)  ;; Auto-install packages

;; autosave everything!!
(use-package super-save
  :config
  (super-save-mode +1))


;;
;; UI enhancements
;;
(setq ring-bell-function 'ignore)
(setq visible-bell t)

;; Set Font
(set-face-attribute 'default nil
                    :family "Hurmit Nerd Font Mono"
                    :foundry "PfEd"
                    :height 140
                    :background "#000000"
                    :foreground "#ffffff")

;; Disable splash screen (typo fixed)
(setq inhibit-startup-message t)

;; UI elements - these are fast, keep them early
(menu-bar-mode 1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(global-display-line-numbers-mode 1)

(use-package beacon
  :defer 2
  :config
  (beacon-mode 1))

(use-package dashboard
  :config
  (dashboard-setup-startup-hook)

  (setq dashboard-projects-backend 'projectile)
  (setq dashboard-items '((recents   . 5)
                          (bookmarks . 5)
                          (projects  . 5)
                          (agenda    . 5)
                          (registers . 5)))
  ;; (use-package nerd-icons)
  ;; (setq dashboard-display-icons-p t)     ; display icons on both GUI and terminal
  ;; (setq dashboard-icon-type 'nerd-icons) ; use `nerd-icons' package
  ;; (setq dashboard-set-heading-icons t)
  ;; (setq dashboard-set-file-icons t)
  (use-package page-break-lines))

(use-package git-gutter
  :defer 2
  :config
  (global-git-gutter-mode +1))

(use-package catppuccin-theme
  :config
  (setq catppuccin-flavor 'macchiato)
  (load-theme 'catppuccin t)
  (add-hook 'after-init-hook (lambda () (run-with-timer 0.5 nil #'catppuccin-reload)))
  )

(use-package which-key
  :defer 1
  :config
  (setq which-key-idle-delay 0
        which-key-idle-secondary-delay 0)
  (which-key-setup-side-window-right-bottom)
  (which-key-mode))

;; cleaner modeline
(use-package mood-line
  :config
  (mood-line-mode)
  ;:custom ()
  )

;;
;; MEOW!!
;;
(use-package meow
  :config
  ;; Add selection back after using meow-save
  (defun my/after-meow-save (&rest _args)
    "Reactivate the selection after saving."
    (let ((selection (meow--make-selection
		      'select
		      (region-beginning)
		      (region-end))))
      (meow--select selection)))

  (advice-add 'meow-save :after #'my/after-meow-save)
  (advice-add 'meow-clipboard-save :after #'my/after-meow-save)
 
  (defvar meow-lsp-keymap
    (let ((keymap (make-sparse-keymap)))
      (define-key keymap (kbd "d") #'xref-find-definitions)
      (define-key keymap (kbd "D") #'eglot-find-implementation)
      (define-key keymap (kbd "r") #'xref-find-references)
      (define-key keymap (kbd "t") #'eglot-find-typeDefinition)
      (define-key keymap (kbd "h") #'eglot-help-at-point)
      (define-key keymap (kbd "a") #'eglot-code-actions)
      (define-key keymap (kbd "R") #'eglot-rename)
      (define-key keymap (kbd "f") #'eglot-format)
      (define-key keymap (kbd "o") #'eglot-code-action-organize-imports)
      keymap)
    "Keymap for LSP navigation commands in Meow normal mode.")

  (defun meow-lsp-keymap-fn ()
    "Access the LSP keymap."
    (interactive)
    (set-transient-map meow-lsp-keymap))

  (defun meow-setup ()
    (setq meow-cheatsheet-layout meow-cheatsheet-layout-colemak-dh)
    (meow-leader-define-key
     '("?" . helm-apropos)
     '("B" . meow-cheatsheet)
     '("1" . meow-digit-argument)
     '("2" . meow-digit-argument)
     '("3" . meow-digit-argument)
     '("4" . meow-digit-argument)
     '("5" . meow-digit-argument)
     '("6" . meow-digit-argument)
     '("7" . meow-digit-argument)
     '("8" . meow-digit-argument)
     '("9" . meow-digit-argument)
     '("0" . meow-digit-argument)
     '("/" . projectile-ripgrep)
     '("a" . eglot-code-actions)
     '("b" . helm-mini)
     '("f" . projectile-find-file)
     '("d" . helm-find-files))
    (meow-normal-define-key
     '("0" . meow-expand-0)
     '("1" . meow-expand-1)
     '("2" . meow-expand-2)
     '("3" . meow-expand-3)
     '("4" . meow-expand-4)
     '("5" . meow-expand-5)
     '("6" . meow-expand-6)
     '("7" . meow-expand-7)
     '("8" . meow-expand-8)
     '("9" . meow-expand-9)
     '("-" . negative-argument)
     '(":" . helm-M-x)
     '(";" . meow-reverse)
     '("'" . meow-inner-of-thing)
     '("," . meow-bounds-of-thing)
     '("[" . meow-beginning-of-thing)
     '("]" . meow-end-of-thing)
     '("/" . meow-visit)
     '(">" . meow-indent)
     '("<" . meow-indent)
     '("%" . mark-whole-buffer)
     '("a" . meow-append)
     '("A" . meow-open-below)
     '("b" . meow-back-word)
     '("B" . meow-back-symbol)
     '("c" . meow-change)
     '("C" . meow-grab)
     '("d" . meow-delete)
     '("D" . meow-backward-delete)
     '("e" . meow-prev)
     '("E" . meow-prev-expand)
     '("f" . meow-find)
     '("g" . meow-lsp-keymap-fn)
     '("G" . meow-goto-line)
     '("h" . meow-insert)
     '("H" . meow-open-above)
     '("i" . meow-next)
     '("I" . meow-next-expand)
     '("j" . meow-join)
     '("K" . meow-kill)
     '("k" . meow-clipboard-kill)
     '("l" . meow-line)
     '("m" . meow-mark-word)
     '("M" . meow-mark-symbol)
     '("n" . meow-left)
     '("N" . meow-left-expand)
     '("o" . meow-right)
     '("O" . meow-right-expand)
     '("p" . meow-yank)
     '("P" . meow-clipboard-yank)
     '("q" . meow-quit)
     '("r" . meow-replace)
     '("t" . meow-till)
     '("u" . meow-undo)
     '("U" . undo-redo)
     '("v" . meow-search)
     '("w" . meow-next-word)
     '("W" . meow-next-symbol)
     '("y" . meow-save)
     '("Y" . meow-clipboard-save)
     '("z" . meow-pop-selection)
     '("." . repeat)
     '("~" . upcase-region)
     '("`" . downcase-region)
     '("<up>" . windmove-up)
     '("<down>" . windmove-down)
     '("<left>" . windmove-left)
     '("<right>" . windmove-right)
     '("<escape>" . ignore)))
  (meow-setup)
  (meow-global-mode 1))

;;
;; Other goodies
;;

(use-package magit
  :defer t)

(use-package projectile
  :defer t
  :config
  (use-package helm
    :defer t
    :bind (("M-x" . helm-M-x)
	   ("C-c h" . helm-command-prefix))
    :config
    (global-unset-key (kbd "C-x c"))
    (define-key helm-map (kbd "<tab>") 'helm-execute-persistent-action)
    (define-key helm-map (kbd "C-i") 'helm-execute-persistent-action)
    (define-key helm-map (kbd "C-z") 'helm-select-action)
    (when (executable-find "curl")
      (setq helm-google-suggest-use-curl-p t))
    (setq helm-split-window-in-side-p t
	  helm-move-to-line-cycle-in-source t
	  helm-ff-search-library-in-sexp t
	  helm-scroll-amount 8
	  helm-ff-file-name-history-use-recentf t
	  helm-echo-input-in-header-line t
	  helm-autoresize-max-height 0
	  helm-autoresize-min-height 20)
    (helm-autoresize-mode 1)
    (helm-mode 1))
  (use-package helm-projectile
    :defer t)
  (use-package helm-rg
    :defer t)
  (use-package ripgrep
    :defer t)
  )


;;
;; LSP
;;
(use-package eglot
  :defer t
  :hook (prog-mode . eglot-ensure) ; hook eglot for any programming-mode-derived mode
  )

(use-package company
  :defer t
  :hook (eglot-managed-mode . company-mode)
  :config
  (setq company-idle-delay 0.1
        company-minimum-prefix-length 1))

;; Coding Specific
(use-package yaml-mode
  :defer t)
(use-package markdown-mode
  :defer t)
(use-package go-mode
  :defer t)
(use-package dockerfile-mode
  :defer t)
(use-package docker-compose-mode
  :defer t)
(use-package cider
  :defer t)
(use-package rainbow-delimiters
  :hook (prog-mode . rainbow-delimiters-mode)
  :defer t)
(use-package hl-todo
  :hook (prog-mode . hl-todo-mode)
  :config
  (setq hl-todo-keyword-faces
      '(("TODO"   . "#FF0000")
        ("FIXME"  . "#FF0000")
        ("DEBUG"  . "#A020F0")
        ("GOTCHA" . "#FF4500")
        ("STUB"   . "#1E90FF"))))


;; LLM
(use-package gptel
  :defer t
  :config
  (setq
   gptel-model 'claude-3-5-haiku-20241022
   gptel-backend (gptel-make-anthropic "Claude"
                   :stream t :key gptel-api-key)))

;; vterm
(use-package vterm
  :defer t)

;;
;; Startup
;;
(add-hook 'emacs-startup-hook
          (lambda ()
            (message "Emacs loaded in %s seconds"
                     (float-time (time-subtract after-init-time before-init-time)))))
(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(package-selected-packages
   '(beacon catppuccin-theme cider company dashboard docker-compose-mode
	    dockerfile-mode eglot-inactive-regions git-gutter go-mode
	    gptel helm-projectile helm-rg hl-todo magit markdown-mode
	    meow mood-line nerd-icons page-break-lines
	    rainbow-delimiters ripgrep super-save use-package-hydra
	    vterm which-key yaml-mode)))
(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 )