;;; init-evil.el --- VIM dentro de emacs  -*- lexical-binding: t -*-

;; Author: kj <webmaster@outcontrol.net>
;; URL: https://git.kj2.me/kj/confi-emacs-actual

;;; Commentary:

;; En este archivo está toda la configuración relacionada
;; con el paquete Evil.
;;
;; Evil es un paquete para Emacs, que básicamente nos
;; permite tener VIM dentro de Emacs.

;;; Code:
(use-package evil
  :defer t
  :hook ((elpaca-after-init . evil-mode)
         (git-timemachine-mode . evil-emacs-state))
  :init
  (setq evil-want-keybinding nil)
  ;; Habilitar atajos de de tecla de emacs en insert state
  (setq evil-disable-insert-state-bindings t)
  :config
  ;; Configuraciones básicas
  ;; (setq evil-default-state 'emacs) ;; Modo por defecto en emacs
  ;; (setq evil-default-state 'insert) ;; Modo por defecto en emacs
  (setq evil-emacs-state-cursor 'bar) ;; Cursor de emacs state en bar
  ;; (setq evil-normal-state-cursor 'bar) ;; Cursor de normal state en bar en lugar de box
  (evil-set-leader 'motion (kbd "SPC")) ;; Leader key
  (evil-set-undo-system 'undo-redo)

  ;; Arreglar el problemita con corfu-quit y el cambio de modos
  (evil-define-key 'emacs 'global (kbd "<escape>") '(lambda ()
                                                      "Call `corfu-quit' and then return to Normal State."
                                                      (interactive)
                                                      (call-interactively 'corfu-quit)
                                                      (evil-normal-state)))

  ;; (evil-define-key 'normal 'global (kbd "<escape>") 'corfu-quit)
  ;; Cambiar a mode emacs con escape
  ;; (evil-define-key 'emacs 'global (kbd "<escape>") 'evil-normal-state)
  ;; Cambiar Insert state por emacs state.
  (defalias 'evil-insert-state 'evil-emacs-state)

  ;; Variales locales (todos los estados o solo los estados de VIM)
  (setq all-states '(normal insert visual replace operator motion emacs))
  (setq vim-states '(normal insert visual replace operator motion))

  ;; Cambiar entre modo emacs y evil (Mi pripio evil toggle)
  ;; (evil-define-key vim-states 'global (kbd "C-'") 'evil-emacs-state)
  ;; (evil-define-key 'emacs 'global (kbd "C-'") 'evil-normal-state)

  ;; Cambiar C-z a deshacer
  (evil-define-key all-states 'global (kbd "C-z") 'undo)

  ;; Cambiar U para hacer redo
  (evil-define-key 'normal 'global (kbd "U") 'undo-redo)
  (evil-define-key 'normal 'global (kbd "C-S-z") 'undo-redo)
  (evil-define-key 'normal 'global (kbd "M-.") 'xref-find-definitions)

  ;; Arreglar yank-pop en normal mode
  (evil-define-key 'normal 'global (kbd "M-y") 'consult-yank-pop)

  ;; Re-bindear keys a como funcionan en emacs.
  (evil-define-key 'normal 'global (kbd "C-p") 'previous-line)
  (evil-define-key 'normal 'global (kbd "C-n") 'next-line)
  (evil-define-key 'normal 'global (kbd "C-e") 'move-end-of-line)

  ;; Navegación entre frames
  (evil-define-key 'motion 'global (kbd "<leader>o") 'other-window)

  ;; Habilitar el scrolear con C-v como en emacs en evil
  (evil-define-key 'motion 'global (kbd "C-v") 'scroll-up-command)

  ;; Añadir nueva linea sin salir del modo normal
  (evil-define-key 'motion 'global (kbd "<leader><RET>") 'newline)

  ;; Abrir historial del kill-ring/portapapeles
  (evil-define-key vim-states 'global (kbd "<leader>y") 'consult-yank-pop)

  ;; Expand region desde motion states
  (evil-define-key 'motion 'global (kbd "<leader>+") 'er/expand-region)

  ;; Identado en motion modes.
  (evil-define-key 'motion 'global (kbd "<tab>") 'indent-for-tab-command)

  ;; Atajos con leader key para frames
  (evil-define-key 'motion 'global (kbd "<leader>0") 'delete-window)
  (evil-define-key 'motion 'global (kbd "<leader>1") 'delete-other-windows)
  (evil-define-key 'motion 'global (kbd "<leader>2") 'split-window-below)
  (evil-define-key 'motion 'global (kbd "<leader>3") 'split-window-right)
  (evil-define-key 'motion 'global (kbd "<leader>k") 'kill-buffer)
  (evil-define-key 'motion 'global (kbd "<leader>wu") 'winner-undo)
  (evil-define-key 'motion 'global (kbd "<leader>wr") 'winner-redo)

  ;; Cambios de modos
  (evil-define-key 'normal 'global (kbd "<leader>mh") 'html-mode)
  (evil-define-key 'normal 'global (kbd "<leader>mj") 'js-mode)
  (evil-define-key 'normal 'global (kbd "<leader>mp") 'php-ts-mode)
  (evil-define-key 'normal 'global (kbd "<leader>mr") 'rust-mode)
  (evil-define-key 'normal 'global (kbd "<leader>mw") 'web-mode)

  ;; Otros atajos
  (evil-define-key 'motion 'global (kbd "<leader>b") 'consult-buffer)             ;; Cambiar de buffer
  (evil-define-key 'motion 'global (kbd "<leader>p") 'consult-project-extra-find) ;; Archivos del proyecto (o abrir proyecto si no hay alguno)
  (evil-define-key 'motion 'global (kbd "<leader>cp") 'project-switch-project)     ;; Cambiar proyecto
  (evil-define-key 'motion 'global (kbd "<leader>f") 'find-file)                  ;; Abrir archivo
  (evil-define-key 'motion 'global (kbd "<leader>xr") 'consult-recent-file)        ;; Lista de archivos recientes
  (evil-define-key 'motion 'global (kbd "<leader>rg") 'consult-ripgrep)            ;; Búsqueda rápida con ripgrep
  (evil-define-key 'motion 'global (kbd "<leader>gi") 'imenu)                      ;; imenu

  ;; Iniciar en normal state solo en modos específicos
  (setq evil-default-state 'emacs) ;; Modo por defecto en emacs
  (evil-set-initial-state 'prog-mode 'normal)
  (evil-set-initial-state 'org-mode 'normal)
  (evil-set-initial-state 'text-mode 'normal)
  (evil-set-initial-state 'csv-mode 'normal)
  (evil-set-initial-state 'fundamental-mode 'normal)
  (evil-set-initial-state 'dashboard-mode 'normal)
  (evil-set-initial-state 'dired 'normal)
  (evil-set-initial-state 'vterm-mode 'emacs)
  (evil-set-initial-state 'magit-mode 'emacs)
  (evil-set-initial-state 'git-commit-mode 'emacs)
  )

;; Funciones y atajos de teclas especiales para evil cuando estamo en org-mode.
;; Por ejemplo, para que evil-open-below funcione similar a org-return cuando
;; estamos dentro de una lista.
(use-package evil-org
  :ensure t
  :defer t
  :after org
  :hook (org-mode . evil-org-mode))

;; Similar a Vimtutor, pero para evil.
(use-package evil-tutor
  :defer t
  :ensure t)

(provide 'init-evil)
;;; init-evil.el ends here