--- ==== Seal.plugins.pasteboard ====
---
--- Visual, searchable pasteboard (ie clipboard) history
local obj = {}
obj.__index = obj
obj.__name = "seal_pasteboard"
obj.timer = nil
obj.lastItem = nil
obj.itemBuffer = {}
obj.choices = {}

--- Seal.plugins.pasteboard.historySize
--- Variable
---
--- The number of history items to keep. Defaults to 50
obj.historySize = 50

--- Seal.plugins.pasteboard.saveHistory
--- Variable
---
--- A boolean, true if Seal should automatically load/save clipboard history. Defaults to true
obj.saveHistory = true

--- Seal.plugins.pasteboard.skipUTIs
--- Variable
---
--- An array of UTIs to skip when saving to the history. Defaults to:
--- ```
--- {
---   "de.petermaurer.TransientPasteboardType",
---   "com.typeit4me.clipping",
---   "Pasteboard generator type",
---   "com.agilebits.onepassword",
---   "org.nspasteboard.TransientType",
---   "org.nspasteboard.ConcealedType",
---   "org.nspasteboard.AutoGeneratedType"
--- }
--- ```
obj.skipUTIs = {
    "de.petermaurer.TransientPasteboardType",
    "com.typeit4me.clipping",
    "Pasteboard generator type",
    "com.agilebits.onepassword",
    "org.nspasteboard.TransientType",
    "org.nspasteboard.ConcealedType",
    "org.nspasteboard.AutoGeneratedType"
}

function obj:commands()
    return {
        pb = {
            cmd = "pb",
            fn = obj.choicesPasteboardCommand,
            name = "Pasteboard",
            description = "Pasteboard history",
            plugin = obj.__name
        }
    }
end

function obj:bare()
    return nil
end

function obj.choicesPasteboardCommand(query)
    -- Return the choices that match the query
    return hs.fnutils.filter(obj.choices, function(choice)
        return string.find(string.lower(choice["text"]), string.lower(query))
    end)
end

function obj.pasteboardToChoice(item)
    local choice = {}

    choice["uuid"] = item["uuid"]
    choice["name"] = item["text"]
    choice["text"] = item["text"]
    choice["kind"] = kind
    choice["plugin"] = obj.__name
    choice["type"] = "copy"
    choice["subText"] = ""

    if item["uti"] then
        choice["subText"] = item["uti"]
        if hs.application.defaultAppForUTI then
            local bundleID = hs.application.defaultAppForUTI(item["uti"])
            print("Default app for " .. item["uti"] .. " :: " .. (bundleID or "(null)"))
            if bundleID then
                choice["image"] = hs.image.imageFromAppBundle(bundleID)
            end
        end
    end
    if item["dateTime"] then
        choice["subText"] = choice["subText"] .. " :: " .. item["dateTime"]
    end

    return choice
end

function obj.completionCallback(rowInfo)
    if rowInfo["type"] == "copy" then
        hs.pasteboard.setContents(rowInfo["name"])
    end
end

function obj.checkPasteboard()
    local pasteboard = hs.pasteboard.getContents()
    local shouldSave = false

    if pasteboard == nil then
        return
    end

    if (#obj.itemBuffer == 0) or (pasteboard ~= obj.itemBuffer[#obj.itemBuffer]["text"]) then
        local currentTypes = hs.pasteboard.allContentTypes()[1]
        if currentTypes == nil then
            print("ERROR: NO PASTEBOARD CURRENT TYPES. Please file a bug so we can understand this:")
            print(hs.inspect(pasteboard))
            return
        end
        for _, aType in pairs(currentTypes) do
            for _, uti in pairs(obj.skipUTIs) do
                if uti == aType then
                    return
                end
            end
        end
        local item = {}
        item["uuid"] = hs.host.uuid()
        item["text"] = pasteboard
        item["uti"] = currentTypes[1]
        item["dateTime"] = os.date()

        table.insert(obj.itemBuffer, item)
        table.insert(obj.choices, obj.pasteboardToChoice(item))

        shouldSave = true
    end
    if #obj.itemBuffer > obj.historySize then
        table.remove(obj.itemBuffer, 1)
        table.remove(obj.choices, 1)

        shouldSave = true
    end

    if shouldSave then
        obj.save()
    end
end

function obj.save()
    local json = hs.json.encode(obj.itemBuffer)
    local file = io.open(os.getenv("HOME") .. "/.hammerspoon/pasteboard_history.json", "w")
    if file then
        file:write(json)
        file:close()
    end
end

function obj.load()
    local file = io.open(os.getenv("HOME") .. "/.hammerspoon/pasteboard_history.json", "r")
    if file then
        local json = hs.json.decode(file:read())
        if json then
            obj.itemBuffer = json

            -- Convert all the items to the choice buffer
            for _, v in ipairs(obj.itemBuffer) do
                table.insert(obj.choices, obj.pasteboardToChoice(v))
            end
        end
        file:close()
    end
end

obj.load()
if obj.timer == nil then
    obj.timer = hs.timer.doEvery(1, function() obj.checkPasteboard(obj) end)
    obj.timer:start()
end

return obj
