;;; ai-code-opencode.el --- Thin wrapper for Opencode  -*- lexical-binding: t; -*-

;; Author: Kang Tu <tninja@gmail.com>
;; SPDX-License-Identifier: Apache-2.0

;;; Commentary:
;;
;; Thin wrapper that reuses `ai-code-backends-infra' to run Opencode.
;; Provides interactive commands and aliases for the AI Code suite.
;;
;; Opencode is an open-source alternative to Claude Code that provides
;; HTTP server APIs and customization features (LSP, custom LLM providers, etc.)
;; See: https://opencode.ai/
;;
;;; Code:

(require 'ai-code-backends)
(require 'ai-code-backends-infra)


(defgroup ai-code-opencode nil
  "Opencode integration via `ai-code-backends-infra.el'."
  :group 'tools
  :prefix "ai-code-opencode-")

(defcustom ai-code-opencode-program "opencode"
  "Path to the Opencode executable."
  :type 'string
  :group 'ai-code-opencode)

(defcustom ai-code-opencode-program-switches nil
  "Command line switches to pass to Opencode on startup."
  :type '(repeat string)
  :group 'ai-code-opencode)

(defcustom ai-code-opencode-extra-env-vars
  '("OTUI_USE_ALTERNATE_SCREEN=main-screen")
  "Extra environment variables passed to the Opencode terminal session.
`OTUI_USE_ALTERNATE_SCREEN=main-screen' avoids the alternate screen
buffer so that terminal scrollback is partially preserved."
  :type '(repeat string)
  :group 'ai-code-opencode)

(defconst ai-code-opencode--session-prefix "opencode"
  "Session prefix used in Opencode buffer names.")

(defvar ai-code-opencode--processes (make-hash-table :test 'equal)
  "Hash table mapping Opencode session keys to processes.")

;;;###autoload
(defun ai-code-opencode (&optional arg)
  "Start Opencode using `ai-code-backends-infra' logic.
With prefix ARG, prompt for CLI args using
`ai-code-opencode-program-switches' as the default input."
  (interactive "P")
  (ai-code-backends-infra--start-cli-session
   (list :program ai-code-opencode-program
         :switches ai-code-opencode-program-switches
         :label "Opencode"
         :process-table ai-code-opencode--processes
         :session-prefix ai-code-opencode--session-prefix
         :env-vars ai-code-opencode-extra-env-vars)
   arg))

;;;###autoload
(defun ai-code-opencode-switch-to-buffer (&optional force-prompt)
  "Switch to the Opencode buffer.
When FORCE-PROMPT is non-nil, prompt to select a session."
  (interactive "P")
  (ai-code-backends-infra--cli-switch-to-buffer
   "Opencode" ai-code-opencode--session-prefix force-prompt))

;;;###autoload
(defun ai-code-opencode-send-command (line)
  "Send LINE to Opencode.
When called interactively, prompts for the command."
  (interactive "sOpencode> ")
  (ai-code-backends-infra--cli-send-command
   "Opencode" ai-code-opencode--session-prefix line))

;;;###autoload
(defun ai-code-opencode-resume (&optional arg)
  "Resume a previous Opencode session.

This command starts Opencode with the --resume flag to resume
a specific past session.  The CLI will present an interactive list of past
sessions to choose from.

If current buffer belongs to a project, start in the project's root
directory.  Otherwise start in the directory of the current buffer file,
or the current value of `default-directory' if no project and no buffer file.

With prefix ARG (\\[universal-argument]), keep the existing CLI-args prompt
and then prompt for the working directory."
  (interactive "P")
  (let ((ai-code-opencode-program-switches
         (append ai-code-opencode-program-switches '("--continue"))))
    (ai-code-opencode arg)
    (ai-code-backends-infra--cli-show-resume-picker
     ai-code-opencode--session-prefix)))

(provide 'ai-code-opencode)

;;; ai-code-opencode.el ends here
