local M = {}

function M.telescope_conf()
    local telescope = require('telescope')

    telescope.setup {
        defaults = {
            prompt_prefix = '   ',
            selection_caret = ' ',
            set_env = {['COLORTERM'] = 'truecolor'},
            sorting_strategy = 'ascending',
            layout_strategy = 'horizontal',
            layout_config = {
                horizontal = {
                    prompt_position = 'top',
                    preview_width = 0.6
                },
                width = 0.8,
                height = 0.8
            },
            file_ignore_patterns = {'.git', '.svn', '.hg', 'node_modules'}
        },
        pickers = {
            find_files = {
                hidden = true,
                follow = true
            },
            grep_string = {
                opts = '--hidden'
            },
            file_browser = {
                hidden = true
            }
        },
        extensions = {
            project = {
                base_dirs = {{os.getenv('HOME') .. '/Code', max_depth = 4}},
                hidden_files = true
            },
            fzf = {
                fuzzy = true,
                override_generic_sorter = false,
                override_file_sorter = true,
                case_mode = 'smart_case'
            }
        }
    }
    telescope.load_extension('projects')
    telescope.load_extension('project')
    telescope.load_extension('fzf')

    -- wrap lines inside preview pane
    vim.api.nvim_command('autocmd User TelescopePreviewerLoaded setlocal wrap')
end

function M.octo_conf()
    require('octo').setup()
end

function M.neogit_conf()
    require('neogit').setup {
        integrations = {
            diffview = true
        }
    }
end

function M.diffview_conf()
    require('diffview').setup {diff_binaries = true}
end

function M.asynctasks_conf()
    -- vim.g.asyncrun_open = 8 -- when using quickfix window (output=terminal is preferable)
    vim.g.asyncrun_rootmarks = {'.git', '.svn', '.root', '.hg', '.projectile'}

    vim.g.asynctasks_term_pos = 'bottom'
    vim.g.asynctasks_term_rows = 10
    vim.g.asynctasks_config_name = 'tasks.ini'
    vim.g.asynctasks_template = '~/.config/nvim/asynctasks.ini'
end

function M.markdown_preview_conf()
    vim.g.mkdp_refresh_slow = 1
    vim.g.mkdp_filetypes = {
        'markdown',
        'pandoc.markdown',
        'rmd'
    }
    -- vim.g.mkdp_browser = 'qutebrowser'
    -- vim.g.mkdp_page_title = '「${name}」'
    -- vim.g.mkdp_echo_preview_url = 1
end

function M.rest_conf()
    require('rest-nvim').setup {
        -- Open request results in a horizontal split
        result_split_horizontal = false,
        -- Skip SSL verification, useful for unknown certificates
        skip_ssl_verification = false,
        -- Highlight request on run
        highlight = {
            enabled = true,
            timeout = 150,
        },
        -- Jump to request line on run
        jump_to_request = false,
    }
end

function M.orgmode_conf()
    local c = require('themes.' .. vim.g.colors_name .. '.colors')

    require('orgmode').setup {
        -- General settings
        org_agenda_files = {'~/Documents/Org/agenda/*'},
        org_default_notes_file = '~/Documents/Org/notes.org',
        org_todo_keywords = {
            'TODO', 'PROJ', 'LOOP', 'STRT', 'WAIT', 'HOLD', 'IDEA', 'DONE', 'KILL',
            '[ ]', '[-]', '[X]' , '|', 'OKAY', 'YES', 'NO'
        },
        org_todo_keyword_faces = {
            TODO = ':foreground ' .. c.green .. ' :weight bold',
            PROJ = ':foreground ' .. c.grey_bright .. ' :weight bold :slant italic',
            LOOP = ':foreground ' .. c.green .. ' :weight bold :underline on',
            STRT = ':foreground ' .. c.blue .. ' :weight bold',
            WAIT = ':foreground ' .. c.yellow .. ' :weight bold',
            HOLD = ':foreground ' .. c.yellow .. ' :weight bold :slant italic',
            IDEA = ':foreground ' .. c.green .. ' :weight bold :slant italic',
            DONE = ':foreground ' .. c.grey2 .. ' :weight bold',
            KILL = ':foreground ' .. c.red .. ' :weight bold',
            OKAY = ':foreground ' .. c.grey1 .. ' :weight bold :slant italic',
            YES = ':foreground ' .. c.grey1 .. ' :weight bold :underline on',
            NO = ':foreground ' .. c.red .. ' :weight bold :underline on'
        },
        org_hide_leading_stars = true,
        org_highlight_latex_and_related = 'entities',

        -- Agenda settings
        org_deadline_warning_days = 7,
        org_agenda_span = 'week',
        org_agenda_start_on_weekday = 7, -- Start a week in Sunday
        org_agenda_min_height = 15,

        -- Tags settings
        org_use_tag_inheritance = false
    }
end

function M.spectre_conf()
    require('spectre').setup()

    -- Mappings
    vim.api.nvim_set_keymap('n', '<leader>po', ':lua require("spectre").open()<CR>', {noremap = true, silent = true})
    vim.api.nvim_set_keymap('n', '<leader>pp', 'viw:lua require("spectre").open_file_search()<CR>', {noremap = true, silent = true})
    vim.api.nvim_set_keymap('n', '<leader>pw', ':lua require("spectre").open_visual({select_word = true})<CR>', {noremap = true, silent = true})
    vim.api.nvim_set_keymap('v', '<leader>p', ':lua require("spectre").open_visual()<CR>', {noremap = true, silent = true})
end

function M.translate_conf()
    vim.g.trans_join_lines = 1
    vim.g.trans_win_height = 15
    vim.g.trans_default_direction = ':ja'
    vim.g.trans_directions_list = {
        {'', 'en'},
        {'', 'ja'},
        {'', 'de'},
        {'', 'ru'},
        {'', 'fr'},
        {'', 'nl'},
        {'', 'es'},
        {'', 'zh-CN'},
        {'', 'zh-TW'}
    }
end

function M.undotree_conf()
    vim.g.undotree_WindowLayout = 2
    vim.g.undotree_SplitWidth = 30
    vim.g.undotree_DiffpaneHeight = 10
    vim.g.undotree_SetFocusWhenToggle = 1
    vim.g.undotree_RelativeTimestamp = 1
end

function M.toggleterm_conf()
    require('toggleterm').setup {
        shade_terminals = false,
        float_opts = {
            border = 'curved',
            -- width = 80,
            -- height = 80,
            winblend = 3,
            highlights = {
                border = 'Normal',
                background = 'Normal'
            }
        }
    }
end

-- function M.wilder_conf()
--     vim.api.nvim_command [[call wilder#setup({'modes': [':', '/', '?']})]]

    -- Doesn't work yet. Bugs in Neovim (see neovim/neovim#14809 and gelguy/wilder.nvim#53)
    -- so can't do multi-line config inside vim.cmd [[ ]] with \
--     vim.api.nvim_command [[
--     call wilder#set_option('renderer', wilder#renderer_mux({
--         \ ':': wilder#popupmenu_renderer({
--         \    'highlighter': [
--         \        wilder#pcre2_highlighter(),
--         \        wilder#python_cpsm_highlighter()
--         \    ],
--         \    'left': [
--         \        ' ',
--         \        wilder#popupmenu_devicons(),
--         \        wilder#popupmenu_buffer_flags({
--         \            'flags': ' a + ',
--         \            'icons': {'+': '', 'a': '', 'h': ''}
--         \        })
--         \    ],
--         \    'right': [' ', wilder#popupmenu_scrollbar()]
--         \ }),
--         \ '/': wilder#wildmenu_renderer({
--         \    'highlighter': wilder#basic_highlighter(),
--         \    'separator': ' · ',
--         \    'right': [' ', wilder#wildmenu_index()]
--         \ })
--         \ }))
--     ]]

--     vim.api.nvim_command [[
--     call wilder#set_option('pipeline', [
--         \ wilder#branch(
--         \    wilder#python_file_finder_pipeline({
--         \       'file_command': ['fd', '--type', 'f', '--follow', '--hidden', '--exclude', '.git'],
--         \       'dir_command': ['fd', '--type', 'd', '--follow', '--hidden', '--exclude', '.git'],
--         \       'filters': ['cpsm_filter', 'fuzzy_filter']
--         \    }),
--         \    wilder#cmdline_pipeline({'language': 'python', 'fuzzy': 1, 'set_pcre2_patter': v:true}),
--         \    wilder#python_search_pipeline({'pattern': 'fuzzy'})
--         \ )
--         \ ])
--     ]]
-- end

function M.neoscroll_conf()
    require('neoscroll').setup()
end

function M.sniprun_conf()
    local c = require('themes.' .. vim.g.colors_name .. '.colors')

    require('sniprun').setup {
        display = {
            'Classic',                    --# display results in the command-line  area
            'VirtualTextOk',              --# display ok results as virtual text (multiline is shortened)
            -- 'VirtualTextErr',          --# display error results as virtual text
            -- 'TempFloatingWindow',      --# display results in a floating window
            -- 'LongTempFloatingWindow',  --# same as above, but only long results. To use with VirtualText__
            -- 'Terminal',                --# display results in a vertical split
            -- 'NvimNotify',              --# display with the nvim-notify plugin
            -- 'Api'                      --# return output to a programming interface
        },
        show_no_output = {
            'Classic',
            'TempFloatingWindow' --# implies LongTempFloatingWindow, which has no effect on its own
        },
        snipruncolors = {
            SniprunVirtualTextOk   =  {bg = c.cyan, fg = c.black},
            SniprunFloatingWinOk   =  {fg = c.cyan},
            SniprunVirtualTextErr  =  {bg = c.orange, fg = c.black},
            SniprunFloatingWinErr  =  {fg = c.orange}
        },
        inline_messages = 0, --# inline_message (0/1) is a one-line way to display messages
                             --# to workaround sniprun not being able to display anything
        borders = 'single' --# display borders around floating windows
                           --# possible values are 'none', 'single', 'double', or 'shadow'
    }
end

function M.session_conf()
    require('persistence').setup {
        dir = vim.fn.expand(vim.fn.stdpath('data') .. '/sessions/'),
        options = {'buffers', 'curdir', 'tabpages', 'winsize'}
    }

    -- Mappings
    vim.api.nvim_set_keymap('n', '<leader>ss', ':lua require("persistence").save()<CR>', {noremap = true, silent = true})
    vim.api.nvim_set_keymap('n', '<leader>sd', ':lua require("persistence").stop()<CR>', {noremap = true, silent = true})
    vim.api.nvim_set_keymap('n', '<leader>sl', ':lua require("persistence").load({last = true})<CR>', {noremap = true, silent = true})
    vim.api.nvim_set_keymap('n', '<leader>sr', ':lua require("persistence").load()<CR>', {noremap = true, silent = true})
end

function M.filetype_conf()
    require('filetype').setup {
        overrides = {
            extensions = {
                md = 'markdown',
                mkd = 'markdown',
                toml = 'toml',
                rasi = 'css',
                vifm = 'vim',
                log = 'log',
                LO = 'log'
            },
            literal = {
                vifmrc = 'vim'
            },
            complex = {
                ['*_log'] = 'log',
                ['G*_LOG'] = 'log',
                ['.*waybar/config'] = 'jsonc',
                ['.*lf/lfrc'] = 'sh'
            }
        }
    }
end

function M.closebuf_conf()
    require('close_buffers').setup {
        preserve_window_layout = {'this'},
        next_buffer_cmd = function(windows)
            require('bufferline').cycle(1)
            local bufnr = vim.api.nvim_get_current_buf()

            for _, window in ipairs(windows) do
                vim.api.nvim_win_set_buf(window, bufnr)
            end
        end
    }
end

function M.winshift_conf()
    require('winshift').setup {
        highlight_moving_win = true,  -- Highlight the window being moved
        focused_hl_group = 'Visual',  -- The highlight group used for the moving window
        moving_win_options = {
            -- These are local options applied to the moving window while it's
            -- being moved. They are unset when you leave Win-Move mode.
            wrap = false,
            cursorline = false,
            cursorcolumn = false,
            colorcolumn = '',
        }
    }
end

function M.winpicker_conf()
    require('window-picker').setup {
        keys = 'alskdjfhgwoeiruty',
        -- Swap windows by holding shift + letter
        swap_shift = true,
        exclude = {NvimTree = true, alpha = true},
        -- Flash the cursor line of the newly focused window
        flash_duration = 300
    }
end

return M
