#!/usr/bin/env bash
: <<!
-------------------------------------------------------------------------------
 Yazi httm-bowie previewer + toggle — pure Lua (preview pane, toggleable modes)
 Cycles through: none (default preview) → last diff → all diffs
 Requires: httm, diff, tree (for dirs), realpath
-------------------------------------------------------------------------------
!
set -euo pipefail

DEST=${1:-/etc/skel/}

YAZI_HOME="${DEST}/.config/yazi"
YAZI_PLUGIN_HOME="${YAZI_HOME}/plugins"
BOWIE_PLUGIN_HOME="${YAZI_PLUGIN_HOME}/httm-bowie.yazi"

mkdir -p "${BOWIE_PLUGIN_HOME}"

#----------------------------------------------------------------

conf_print_bowie_previewer() {
  cat <<'EOF'
-- httm-bowie.yazi/init.lua
-- Custom previewer: shows bowie diff based on global mode (none/last/all)

local M = {}

-- Shared state via ya.sync (initial: "none")
local mode_get = ya.sync(function() return _G.BOWIE_MODE or "none" end)

function M:peek(job)
  local mode = mode_get()
  if mode == "none" then
    return  -- skip to default previewer
  end

  local path = tostring(job.url)
  local is_file = os.execute("test -f " .. ya.quote(path)) == 0 or os.execute("test -h " .. ya.quote(path)) == 0

  local real_cmd = Command("realpath"):arg(path):stdout(Command.PIPED):spawn()
  if real_cmd then
    real_cmd:wait()
    path = real_cmd:read_line() or path
    path = path:gsub("\n$", "")
  end

  local content = ""
  local function add_header(txt) content = content .. txt .. "\n__\n\n" end
  local function add_diff(prev, curr, is_dir)
    if is_dir then
      local tree_prev = Command("tree"):arg("-RDsa"):arg(prev):stdout(Command.PIPED):spawn()
      local tree_curr = Command("tree"):arg("-RDsa"):arg(curr):stdout(Command.PIPED):spawn()
      if not tree_prev or not tree_curr then return end
      tree_prev:wait()
      tree_curr:wait()
      local p_out = tree_prev:read_all() or ""
      local c_out = tree_curr:read_all() or ""
      p_out = p_out:gsub("^.*\n", "", 1):gsub("\n$", "")  -- skip first line
      c_out = c_out:gsub("^.*\n", "", 1):gsub("\n$", "")
      local diff_cmd = Command("diff"):arg("--color=always"):arg("-T"):arg("--label=" .. prev):arg("--label=" .. curr):stdout(Command.PIPED)
      diff_cmd:stdin(Command.PIPED):write(p_out .. "\n" .. c_out):spawn()  -- hacky, but diff from strings
      diff_cmd:wait()
      content = content .. (diff_cmd:read_all() or "") .. "\n"
    else
      local diff = Command("diff"):arg("--color=always"):arg("-T"):arg(prev):arg(curr):stdout(Command.PIPED):spawn()
      if diff then
        diff:wait()
        content = content .. (diff:read_all() or "No diff") .. "\n"
      end
    end
  end

  local function get_last_snap(p)
    local cmd = Command("httm"):arg("-n"):arg("--dedup-by=contents"):arg("--omit-ditto"):arg("--last-snap"):arg(p):stdout(Command.PIPED):spawn()
    if not cmd then return nil end
    cmd:wait()
    return cmd:read_line():gsub("\n$", "")
  end

  local function get_all_snaps(p)
    local dedup = is_file and "contents" or "disable"
    local cmd = Command("httm"):arg("-n"):arg("--dedup-by=" .. dedup):arg("--omit-ditto"):arg(p):stdout(Command.PIPED):spawn()
    if not cmd then return {} end
    cmd:wait()
    local snaps = {}
    for line in cmd:read_lines() do
      line = line:gsub("\n$", "")
      if line ~= "" then table.insert(snaps, line) end
    end
    return snaps
  end

  if mode == "last" then
    local snap = get_last_snap(path)
    if not snap or snap == "" or snap == path then
      content = "No previous snapshot or identical to live."
    else
      add_header(path .. " (last snapshot diff)")
      add_diff(snap, path, not is_file)
    end
  elseif mode == "all" then
    local snaps = get_all_snaps(path)
    if #snaps == 0 then
      content = "No snapshots found."
    else
      add_header(path .. " (all changes)")
      local prev = snaps[1]
      for i = 2, #snaps do
        local curr = snaps[i]
        content = content .. "-- " .. prev .. " → " .. curr .. " --\n"
        add_diff(prev, curr, not is_file)
        prev = curr
      end
      content = content .. "-- " .. prev .. " → LIVE (" .. path .. ") --\n"
      add_diff(prev, path, not is_file)
    end
  end

  if content == "" then content = "No content generated." end

  ya.preview_code({
    area = job.area,
    hup = false,  -- don't update on hover change
    content = content,
    filetype = "diff",  -- for syntax highlight
  })
end

function M:seek(job)
  self:peek(job)  -- simple, no complex seeking
end

return M
EOF
}

conf_print_bowie_previewer | tee "${BOWIE_PLUGIN_HOME}/init.lua"

#----------------------------------------------------------------
# FIXME: Seems to be a separate plugin just to handle toggle/cycle behaiour:
conf_print_bowie_toggle() {
  cat <<'EOF'
-- httm-bowie-toggle.yazi/init.lua
-- Toggle mode: none → last → all → none

return {
  entry = function()
    local modes = { "none", "last", "all" }
    local current = _G.BOWIE_MODE or "none"
    local next_idx = 1
    for i, m in ipairs(modes) do
      if m == current then
        next_idx = (i % #modes) + 1
        break
      end
    end
    _G.BOWIE_MODE = modes[next_idx]
    ya.notify({ title = "Bowie", content = "Mode: " .. _G.BOWIE_MODE, timeout = 2 })

    -- Force preview refresh
    ya.manager_emit("peek", { cx.active.preview.skip or 0, only_if = tostring(cx.active.current.hovered.url), force = true })
  end,
}
EOF
}
# conf_print_bowie_toggle | tee "${HTTM_TOGGLE_HOME}/init.lua"

#----------------------------------------------------------------

conf_print_bowie_config() {
  cat <<'EOF'

# Add to ~/.config/yazi/yazi.toml
[plugin]
prepend_previewers = [
  { name = "*", run = "httm-bowie", sync = true },
]

EOF
}

#----------------------------------------------------------------

conf_print_bowie_keymap() {
  cat <<'EOF'
# Add to ~/.config/yazi/keymap.toml

[[manager.prepend_keymap]]
on   = [ "g", "d" ]
run  = "plugin httm-bowie-toggle"
desc = "Toggle Bowie preview mode (none/last/all)"

EOF
}

#----------------------------------------------------------------

conf_print_bowie_license() {
  cat <<EOF
MIT License

Copyright (c) 2026 ${AUTHOR_NAME}

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
EOF
}
conf_print_bowie_license | tee "${BOWIE_PLUGIN_HOME}/LICENSE"

#----------------------------------------------------------------

conf_print_bowie_README() {
  cat <<'EOF'
This is a specialized plugin for Yazi that integrates `httm` (the Interactive ZFS Snapshot Explorer) directly into your preview pane. It allows you to cycle through different "time-travel" views of your files and directories without leaving the file manager.

Below is a formatted `README.md` you can use for this project.

---

# httm-bowie.yazi

A high-performance **Yazi** plugin that brings `httm` snapshot diffs directly into your preview pane. Cycle through historical versions of files and directories with a single keybind.

## 🌟 Features

* **Three Preview Modes**:
* `none`: Standard Yazi preview (syntax highlighting, images, etc.).
* `last`: Shows a `diff` between the live file and its most recent snapshot.
* `all`: Shows a sequential `diff` chain of all historical changes found by `httm`.


* **Directory Support**: Uses `tree` to diff directory structures if a folder is hovered.
* **Smart Dedup**: Automatically handles `httm`'s deduplication to show only meaningful changes.
* **Native Feel**: Integrated with Yazi's `ya.preview_code` for smooth scrolling and `diff` syntax highlighting.

## 📋 Requirements

Ensure the following are installed and available in your `$PATH`:

* [httm](https://github.com/kimono-koans/httm)
* `diff` (usually pre-installed on Unix)
* `tree` (required for directory previews)
* `realpath`

## 🚀 Installation

### 1. Create the Plugin Folders

Yazi expects plugins in specific directories. Create them and place the `init.lua` files accordingly:

```bash
# Create directories
mkdir -p ~/.config/yazi/plugins/httm-bowie.yazi
mkdir -p ~/.config/yazi/plugins/httm-bowie-toggle.yazi

```

1. Save the **Previewer** code to `~/.config/yazi/plugins/httm-bowie.yazi/init.lua`.
2. Save the **Toggle** code to `~/.config/yazi/plugins/httm-bowie-toggle.yazi/init.lua`.

### 2. Configure `yazi.toml`

Add the previewer to the top of your `prepend_previewers` list so it can intercept the preview before the default handlers:

```toml
[plugin]
prepend_previewers = [
  { name = "*", run = "httm-bowie", sync = true },
]

```

### 3. Configure `keymap.toml`

Bind the toggle function to a key of your choice (e.g., `gd` for "Go Diff"):

```toml
[[manager.prepend_keymap]]
on   = [ "g", "d" ]
run  = "plugin httm-bowie-toggle"
desc = "Toggle Bowie preview mode (none/last/all)"

```

## 🛠️ Usage

1. **Navigate** to any file or directory inside a ZFS dataset (or any location monitored by `httm`).
2. **Press `gd**` to cycle through modes:
* **Notification: "Mode: last"** → The preview pane now shows the changes made since the last snapshot.
* **Notification: "Mode: all"** → The preview pane shows a scrollable history of all changes across all snapshots.
* **Notification: "Mode: none"** → Returns to standard Yazi behavior.


3. **Scroll** through the diffs using your standard Yazi preview scroll keys.

EOF
}
conf_print_bowie_README | tee "${BOWIE_PLUGIN_HOME}/README.md"

#----------------------------------------------------------------

cat <<EOF
httm-bowie previewer + toggle installed.
Previewer: ${BOWIE_PLUGIN_HOME}/init.lua
Toggle: ${BOWIE_TOGGLE_HOME}/init.lua

conf_print_bowie_config
conf_print_bowie_keymap

Add the above to yazi.toml and keymap.toml.
Restart yazi. Use 'gd' to cycle modes. When 'none', falls back to default preview.
EOF
