--- === Spellspoon ===
---
--- A macOS tool built using Hammerspoon for Audio Recording and Transcription
---
--- SpellSpoon provides hotkey-driven audio recording, transcription, and prompting functionality.
--- A configurable shell script pipeline is used to handle the recording, transcription, and prompting.
---
--- Features:
--- - Hotkey control for recording.
--- - Customizable shell script pipelines for recording, transcribing, and prompting.
--- - Flexible prompt-based text transformation.
--- - Clipboard and direct pasting support.
--- - Tracks transcription stats (duration, word count, character count).
--- - Customization of scripts allows for custom prompts, transcription, recording, and services used.

--- Configuration:
---
--- local spellspoon = hs.loadSpoon("spellspoon")
--- spellspoon:setConfig({
---     promptsDirectory = "~/.spellspoon/prompts",
---     transcriptionStatsDatabase = "~/.spellspoon/transcription_stats.sqlite",
---     transcribingScript = "~/.spellspoon/handle_transcribing.sh",
---     recordingScript = "~/.spellspoon/handle_recording.sh",
---     promptingScript = "~/.spellspoon/handle_prompting.sh",
---     logLevel = "debug"
--- })
--- spellspoon:bindHotkeys({
---     recordWithDefaultPrompt = {{"cmd", "alt", "ctrl", "shift"}, "]"},
---     recordWithPromptSelection = {{"cmd", "alt", "ctrl", "shift"}, "["},
---     recordWithoutPrompt = {{"cmd", "alt", "ctrl", "shift"}, ";"},
---     useSelectedTextWithPromptSelection = {{"cmd", "alt", "ctrl", "shift"}, "="},
---     showStatsModal = {{"cmd", "alt", "ctrl", "shift"}, "-"}
--- })
---
--- Download: https://github.com/kevinjalbert/spellspoon

local M = {}

-- Metadata
M.name = "Spellspoon"
M.version = "0.1.0"
M.author = "Kevin Jalbert <kevin.j.jalbert@gmail.com>"
M.homepage = "https://github.com/kevinjalbert/spellspoon"
M.license = "MIT - https://opensource.org/licenses/MIT"

-- Load modules from the Spoon's modules directory
local spoonPath = debug.getinfo(1, "S").source:sub(2):match("(.*/)")
package.path = spoonPath .. "modules/?.lua;" .. package.path

local Logger = require("utils.logger")

-- Load configuration module first
local Config = require("utils.config")

-- Allow setting configuration before initialization
function M:setConfig(config)
    -- Expand any paths that use ~
    local expandedConfig = {}
    for k, v in pairs(config) do
        if type(v) == "string" and v:match("^~") then
            expandedConfig[k] = v:gsub("^~", os.getenv("HOME"))
        else
            expandedConfig[k] = v
        end
    end

    -- Set the config using the proxy's function directly
    Config.setConfig(expandedConfig)
end

local Recording = require("record.recording")
local Indicator = require("ui.indicator")
local Menu = require("menu.menu")
local StatsModal = require("ui.stats_modal")

function M:recordWithDefaultPrompt()
    Indicator:cleanup()
    if not Recording.isRecording then
        Recording:startRecording(Recording.RecordingMode.DEFAULT_PROMPT)
    else
        Recording:stopRecording(false, Recording.RecordingMode.DEFAULT_PROMPT)
    end
end

function M:recordWithPromptSelection()
    Indicator:cleanup()
    if not Recording.isRecording then
        Recording:startRecording(Recording.RecordingMode.WITH_PROMPT)
    else
        Recording:stopRecording(false, Recording.RecordingMode.WITH_PROMPT)
    end
end

function M:useSelectedTextWithPromptSelection()
    Indicator:cleanup()
    -- Get the currently focused element
    local element = hs.uielement.focusedElement()
    if element then
        -- Get selected text directly from the element
        local selectedText = element:selectedText()
        if selectedText then
            -- Show menu directly with the selected text
            Menu:showMenu(selectedText)
        end
    end
end

function M:showStatsModal()
    StatsModal:toggleStatsModal()
end

function M:recordWithoutPrompt()
    Indicator:cleanup()
    if not Recording.isRecording then
        Recording:startRecording(Recording.RecordingMode.NO_PROMPT)
    else
        Recording:stopRecording(false, Recording.RecordingMode.NO_PROMPT)
    end
end

function M:bindHotkeys(mapping)
    local def = {
        recordWithDefaultPrompt = {{"cmd", "alt", "ctrl"}, "["},
        recordWithPromptSelection= {{"cmd", "alt", "ctrl"}, "]"},
        recordWithoutPrompt = {{"cmd", "alt", "ctrl"}, ";"},
        useSelectedTextWithPromptSelection = {{"cmd", "alt", "ctrl"}, "="},
        showStatsModal = {{"cmd", "alt", "ctrl"}, "-"}
    }
    if mapping then
        for k,v in pairs(mapping) do
            def[k] = v
        end
    end

    for k,v in pairs(def) do
        if v[1] and v[2] then
            if k == "recordWithDefaultPrompt" then
                hs.hotkey.bind(v[1], v[2], function() self:recordWithDefaultPrompt() end)
            elseif k == "recordWithPromptSelection" then
                hs.hotkey.bind(v[1], v[2], function() self:recordWithPromptSelection() end)
            elseif k == "recordWithoutPrompt" then
                hs.hotkey.bind(v[1], v[2], function() self:recordWithoutPrompt() end)
            elseif k == "useSelectedTextWithPromptSelection" then
                hs.hotkey.bind(v[1], v[2], function() self:useSelectedTextWithPromptSelection() end)
            elseif k == "showStatsModal" then
                hs.hotkey.bind(v[1], v[2], function() self:showStatsModal() end)
            end
        end
    end
end

return M
