(require 'common-lsp)
(require 'util-tree-sitter)

(defun js-format-buffer ()
  "Run prettier."
  (interactive)
  (run-command-on-buffer "prettier" "--stdin-filepath" buffer-file-name)
  )

(use-package json-ts-mode
  :ensure nil
  :pin manual
  :mode (
         ("\\.json\\'" . json-ts-mode)
         )
  :commands (json-ts-mode)
  :hook (
         (json-ts-mode . (lambda ()
                           (add-hook 'before-save-hook 'json-fmt-jq nil 'local)
                           ))
         )
  :init
  (add-to-list 'treesit-language-source-alist '(json "https://github.com/tree-sitter/tree-sitter-json"))
  (unless (treesit-ready-p 'json) (treesit-install-language-grammar 'json))
  )

(defun json-fmt-jq ()
  "Run jq."
  (run-command-on-buffer "jq" "--monochrome-output" ".")
  )

(defun configure-typescript-language-server ()
  "Configures the typescript language server."
  (when-linux
    ;; Either initializationOptions or workspace/didChangeConfiguration works.
    (setq eglot-workspace-configuration
          (list (cons ':typescript '(:inlayHints (:includeInlayParameterNameHints
                                                  "all"
                                                  :includeInlayParameterNameHintsWhenArgumentMatchesName
                                                  t
                                                  :includeInlayFunctionParameterTypeHints
                                                  t
                                                  :includeInlayVariableTypeHints
                                                  t
                                                  :includeInlayVariableTypeHintsWhenTypeMatchesName
                                                  t
                                                  :includeInlayPRopertyDeclarationTypeHints
                                                  t
                                                  :includeInlayFunctionLikeReturnTypeHints
                                                  t
                                                  :includeInlayEnumMemberValueHints
                                                  t)))))
    (eglot-ensure)
    ;; (defclass my/eglot-typescript (eglot-lsp-server) ()
    ;;   :documentation
    ;;   "Own eglot server class.")

    ;; (add-to-list 'eglot-server-programs
    ;;              '((js-mode js-ts-mode tsx-ts-mode typescript-ts-mode typescript-mode) . (my/eglot-typescript "typescript-language-server" "--stdio" :initializationOptions (:preferences (:includeInlayParameterNameHints
    ;;                                                                                                                                                                                        "all"
    ;;                                                                                                                                                                                        :includeInlayParameterNameHintsWhenArgumentMatchesName
    ;;                                                                                                                                                                                        t
    ;;                                                                                                                                                                                        :includeInlayFunctionParameterTypeHints
    ;;                                                                                                                                                                                        t
    ;;                                                                                                                                                                                        :includeInlayVariableTypeHints
    ;;                                                                                                                                                                                        t
    ;;                                                                                                                                                                                        :includeInlayVariableTypeHintsWhenTypeMatchesName
    ;;                                                                                                                                                                                        t
    ;;                                                                                                                                                                                        :includeInlayPRopertyDeclarationTypeHints
    ;;                                                                                                                                                                                        t
    ;;                                                                                                                                                                                        :includeInlayFunctionLikeReturnTypeHints
    ;;                                                                                                                                                                                        t
    ;;                                                                                                                                                                                        :includeInlayEnumMemberValueHints
    ;;                                                                                                                                                                                        t)))))
    )
  )

(use-package tsx-ts-mode
  :ensure nil
  :pin manual
  :mode (
         ("\\.tsx\\'" . tsx-ts-mode)
         )
  :commands (tsx-ts-mode)
  :hook (
         (tsx-ts-mode . (lambda ()
                          (when-linux
                            (configure-typescript-language-server)
                            )
                          ))
         )
  :init
  (add-to-list 'treesit-language-source-alist '(tsx . ("https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src")))
  (unless (treesit-ready-p 'tsx) (treesit-install-language-grammar 'tsx))
  )


(use-package typescript-ts-mode
  :ensure nil
  :pin manual
  :mode (
         ("\\.ts\\'" . typescript-ts-mode)
         )
  :commands (typescript-ts-mode)
  :hook (
         (typescript-ts-mode . (lambda ()
                                 (configure-typescript-language-server)
                                 ))
         )
  :init
  (add-to-list 'treesit-language-source-alist '(typescript . ("https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src")))
  (unless (treesit-ready-p 'typescript) (treesit-install-language-grammar 'typescript))
  )

(use-package js-ts-mode
  :ensure nil
  :pin manual
  :mode (
         ("\\.js\\'" . js-ts-mode)
         )
  :commands (js-ts-mode)
  :custom (
           (js-indent-level 2)
           )
  :hook (
         (js-ts-mode . (lambda ()
                                 (when-linux
                                   (eglot-ensure)
                                   (add-hook 'before-save-hook 'js-format-buffer nil 'local)
                                   )
                                 ))
         )
  :init
  (add-to-list 'treesit-language-source-alist '(javascript . ("https://github.com/tree-sitter/tree-sitter-javascript" "master" "src")))
  (unless (treesit-ready-p 'javascript) (treesit-install-language-grammar 'javascript))
  )

(defun prettier-fmt ()
  "Run prettier."
  (run-command-on-buffer "prettier" "--stdin-filepath" buffer-file-name)
  )


(use-package css-ts-mode
  :ensure nil
  :pin manual
  :mode (
         ("\\.css\\'" . css-ts-mode)
         )
  :commands (css-ts-mode)
  :custom (css-indent-offset 2)
  :init
  (add-to-list 'treesit-language-source-alist '(css "https://github.com/tree-sitter/tree-sitter-css"))
  (unless (treesit-ready-p 'css) (treesit-install-language-grammar 'css))
  :hook (
         (css-ts-mode . (lambda ()
                             (eglot-ensure)
                             (defclass my/eglot-css (eglot-lsp-server) ()
                               :documentation
                               "Own eglot server class.")

                             (add-to-list 'eglot-server-programs
                                          '(css-ts-mode . (my/eglot-css "vscode-css-language-server" "--stdio")))
                             ;; (add-hook 'before-save-hook 'eglot-format-buffer nil 'local)
                             (add-hook 'before-save-hook 'prettier-fmt nil 'local)
                             ))
         )
  )


(use-package web-mode
  :mode (("\\.dust\\'" . dust-mode)
         )
  :config
  (setq web-mode-markup-indent-offset 2)
  (setq web-mode-enable-current-element-highlight t)
  )

;; Define a custom mode for dust so that org-mode handle #+BEGIN_SRC dust blocks
(define-derived-mode dust-mode web-mode "WebDust"
  "Major mode for editing dust templates in web-mode."
  (web-mode)
  (web-mode-set-engine "dust")
  ;; (setq web-mode-content-type "html")
  )

(provide 'lang-javascript)
