local M = {}
_VT_NS = vim.api.nvim_create_namespace("lsp_signature")

local prescript
local prescript_hi
local due_hi
local ft
local future
local future_hi
local date_hi
local pattern_start
local pattern_end

local use_clock_time
local default_due_time

-- local date_pattern
local datetime_pattern
local datetime_pattern_match

local function parseDue(due)
    local year = 31556926
    local month = 2629743
    local week = 604800
    local day = 86400
    local hour = 3600
    local minute = 60
    local res = ''

    if due >= year then
        res = res .. math.floor(due / year) .. 'y '
        due = due % year
    end

    if due >= month then
        res = res .. math.floor(due / month) .. 'm '
        due = due % month
    end

    if due >= week then
        res = res .. math.floor(due / week) .. 'w '
        due = due % week
    end

    if use_clock_time == true then
        if due >= day then
            res = res .. math.floor(due / day) .. 'd '
            due = due % day
        end

        if due >= hour then
            res = res .. math.floor(due / hour) .. 'h '
            due = due % hour
        end

        if due >= minute then
            res = res .. math.floor(due / minute) .. 'min '
            due = due % minute
        end
    else
        res = res .. math.floor(due / day) + 1 .. 'd '
    end

    return res
end

function M.setup(c)
    use_clock_time = c.use_clock_time or true
    default_due_time = c.default_due_time or 'midnight'
    prescript = c.prescript or 'has been: '
    prescript_hi = c.prescript_hi or 'Comment'
    due_hi = c.due_hi or 'String'
    ft = c.ft or '*.wiki'
    future = c.future or 'future'
    future_hi = c.future_hi or 'Error'
    date_hi = c.date_hi or 'Conceal'
    pattern_start = c.pattern_start or '('
    pattern_end = c.pattern_end or ')'

    local lua_start = pattern_start:gsub("[%(%)%.%%%+%-%*%?%[%^%$%]]", "%%%1")
    local lua_end = pattern_end:gsub("[%(%)%.%%%+%-%*%?%[%^%$%]]", "%%%1")

    local regex_start = pattern_start:gsub("\\%^%$%.%*~%[%]&", "\\%1")
    local regex_end = pattern_end:gsub("\\%^%$%.%*~%[%]&", "\\%1")

    datetime_pattern = lua_start .. '%d%d%d%d%-%d%d%-%d%d %d%d:%d%d' .. lua_end
    datetime_pattern_match = lua_start .. '(%d%d%d%d)%-(%d%d)%-(%d%d) (%d%d):(%d%d)' .. lua_end

    local regex_hi = '/' .. regex_start .. '\\d*-*\\d\\+-\\d\\+' .. regex_end ..
        '/'

    vim.api.nvim_command('autocmd BufEnter ' .. ft ..
        ' lua require("helpers.stale").draw(0)')
    vim.api.nvim_command('autocmd InsertLeave ' .. ft ..
        ' lua require("helpers.stale").redraw(0)')
    vim.api.nvim_command('autocmd TextChanged ' .. ft ..
        ' lua require("helpers.stale").redraw(0)')
    vim.api.nvim_command('autocmd TextChangedI ' .. ft ..
        ' lua require("helpers.stale").redraw(0)')

    vim.api.nvim_command('autocmd BufEnter ' .. ft .. ' syn match DueDate ' ..
        regex_hi ..
        ' display containedin=mkdNonListItemBlock,mkdListItemLine,mkdBlockquote contained')
    vim.api.nvim_command('autocmd BufEnter ' .. ft .. ' hi def link DueDate ' ..
        date_hi)
end

function M.draw(buf)
    local user_time
    local user_hour
    local user_min
    local user_sec = 00

    -- get current time
    local now = os.time(os.date('*t'))

    -- find which date pattern is being passed in by user
    for key, value in pairs(vim.api.nvim_buf_get_lines(buf, 0, -1, {})) do
        local dateTime = string.match(value, datetime_pattern)
        local due

        if dateTime then
            local cur_year, month, day, user_hour, user_min = dateTime:match(datetime_pattern_match)
            user_time = os.time({
                year = cur_year,
                month = month,
                day = day,
                hour = user_hour,
                min = user_min,
                sec = user_sec
            })

            due = now - user_time
        end

        if due then
            local parsed

            if due > 0 then
                parsed = { parseDue(due), due_hi }
            else
                parsed = { future, future_hi }
            end

            vim.api.nvim_buf_set_virtual_text(buf, _VT_NS, key - 1, {
                { prescript, prescript_hi }, parsed
            }, {})
        end
    end
end

function M.clear(buf) vim.api.nvim_buf_clear_namespace(buf, _VT_NS, 0, -1) end

function M.redraw(buf)
    M.clear(buf)
    M.draw(buf)
end

return M