local M = {}

function M.dashboard_conf()
    local dashboard = require('alpha.themes.dashboard')

    dashboard.section.header = {
        type = 'text',
        val = {
            [[<-. (`-')_  (`-')  _                 (`-')  _     <-. (`-')  ]],
            [[   \( OO) ) ( OO).-/     .->        _(OO ) (_)       \(OO )_ ]],
            [[,--./ ,--/ (,------.(`-')----. ,--.(_/,-.\ ,-(`-'),--./  ,-.)]],
            [[|   \ |  |  |  .---'( OO).-.  '\   \ / (_/ | ( OO)|   `.'   |]],
            [[|  . '|  |)(|  '--. ( _) | |  | \   /   /  |  |  )|  |'.'|  |]],
            [[|  |\    |  |  .--'  \|  |)|  |_ \     /_)(|  |_/ |  |   |  |]],
            [[|  | \   |  |  `---.  '  '-'  '\-'\   /    |  |'->|  |   |  |]],
            [[`--'  `--'  `------'   `-----'     `-'     `--'   `--'   `--']]
        },
        opts = {
            position = 'center',
            -- wrap = 'overflow',
            hl = 'DashboardHeader'
        }
    }

    dashboard.section.footer = {
        type = 'text',
        val = 'おかえりなさい',
        opts = {
            position = 'center',
            hl = 'DashboardFooter'
        }
    }

    local button = function(sc, txt, keybind, keybind_opts)
        local sc_ = sc:gsub('%s', ''):gsub('SPC', '<leader>')

        local opts = {
            position = 'center',
            shortcut = sc,
            cursor = 5,
            width = 50,
            align_shortcut = 'right',
            hl = 'DashboardCenter',
            hl_shortcut = 'DashboardShortcut',
        }
        if keybind then
            keybind_opts = vim.F.if_nil(keybind_opts, {noremap = true, silent = true, nowait = true})
            opts.keymap = {'n', sc_, keybind, keybind_opts}
        end

        local function on_press()
            local key = vim.api.nvim_replace_termcodes(sc_ .. '<Ignore>', true, false, true)
            vim.api.nvim_feedkeys(key, 'normal', false)
        end

        return {
            type = 'button',
            val = txt,
            on_press = on_press,
            opts = opts,
        }
    end

    dashboard.section.buttons = {
        type = 'group',
        val = {
            button('SPC f g', '  Find word'),
            button('SPC f f', '  Find file'),
            button('SPC f o', '  Recent files'),
            button('SPC f d', 'ﱮ  Recent directories'),
            button('SPC f m', '  Bookmarks'),
            button('SPC f p', '  Projects'),
            button('SPC s l', '  Load last session')
        },
        opts = {spacing = 1}
    }

    require('alpha').setup {
        layout = {
            {type = 'padding', val = 4},
            dashboard.section.header,
            {type = 'padding', val = 2},
            dashboard.section.buttons,
            dashboard.section.footer
        },
        opts = {margin = 5}
    }

    -- Hide tabline in dashboard buffer
    vim.api.nvim_command [[
    autocmd FileType alpha set showtabline=0 | autocmd BufUnload <buffer> set showtabline=2
    ]]
end

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

    local vi_mode_colors = {
        NORMAL        = colors.green,
        OP            = colors.green,
        INSERT        = colors.blue,
        VISUAL        = colors.yellow,
        LINES         = colors.yellow,
        BLOCK         = colors.yellow,
        REPLACE       = colors.red,
        ['V-REPLACE'] = colors.red,
        ENTER         = colors.cyan,
        MORE          = colors.cyan,
        SELECT        = colors.orange,
        COMMAND       = colors.purple,
        SHELL         = colors.green,
        TERM          = colors.green,
        NONE          = colors.white2
    }

    local function file_osinfo()
        local os = vim.bo.fileformat:upper()
        local icon
        if os == 'UNIX' then
            icon = ' '
        elseif os == 'MAC' then
            icon = ' '
        else
            icon = ' '
        end
        return icon .. os
    end

    local function buffer_not_empty()
        if vim.fn.empty(vim.fn.expand('%:t')) ~= 1 then
            return true
        end
        return false
    end

    local vi_mode_utils = require('feline.providers.vi_mode')

    local comps = {
        dummy = {
            provider = '▊',
            hl = {fg = colors.blue},
            right_sep = ' '
        },
        vi_mode = {
            provider = ' ',
            hl = function()
                return {
                    name = vi_mode_utils.get_mode_highlight_name(),
                    fg = vi_mode_utils.get_mode_color()
                }
            end,
            right_sep = ' '
        },
        filesize = {
            provider = 'file_size',
            enabled = buffer_not_empty,
            hl = {fg = colors.fg, style = 'bold'},
            right_sep = ' '
        },
        fileinfo = {
            provider = {
                name = 'file_info',
                opts = {
                    file_modified_icon = ' ',
                    file_readonly_icon = ' ',
                    type = 'base-only' -- relative, unique, full-path, short-path, relative-short, unique-short
                }
            },
            enabled = buffer_not_empty,
            hl = {fg = colors.blue, style = 'bold'},
            right_sep = ' '
        },
        lineinfo = {
            provider = 'position',
            hl = {fg = colors.fg},
            right_sep = ' '
        },
        percent = {
            provider = 'line_percentage',
            hl = {fg = colors.fg, style = 'bold'},
            right_sep = ' '
        },
        codeact = {
            provider = function()
                local present, state = pcall(require, 'nvim-lightbulb')
                if present then
                    return state.get_status_text()
                else
                    return ''
                end
            end,
            hl = {fg = colors.green, style = 'bold'}
        },
        diagerr = {
            provider = 'diagnostic_errors',
            icon = ' ',
            hl = {fg = colors.red},
            left_sep = ' '
        },
        diagwarn = {
            provider = 'diagnostic_warnings',
            icon = ' ',
            hl = {fg = colors.yellow},
            left_sep = ' '
        },
        diaghint = {
            provider = 'diagnostic_hints',
            icon = ' ',
            hl = {fg = colors.cyan},
            left_sep = ' '
        },
        diaginfo = {
            provider = 'diagnostic_info',
            icon = ' ',
            hl = {fg = colors.blue},
            left_sep = ' '
        },
        lspclient = {
            provider = 'lsp_client_names',
            icon = '  LSP:',
            hl = {fg = colors.purple, style = 'bold'},
            left_sep = '  '
        },
        format = {
            provider = file_osinfo,
            hl = {fg = colors.cyan},
            left_sep = '  '
        },
        encode = {
            provider = 'file_encoding',
            hl = {fg = colors.fg},
            left_sep = ' '
        },
        filetype = {
            provider = 'file_type',
            hl = {fg = colors.blue, style = 'bold'},
            left_sep = '  '
        },
        gitbranch = {
            provider = 'git_branch',
            icon = ' ',
            hl = {fg = colors.green, style = 'bold'},
            left_sep = '  '
        },
        diffadd = {
            provider = 'git_diff_added',
            icon = ' ',
            hl = {fg = colors.green},
            left_sep = ' '
        },
        diffchange = {
            provider = 'git_diff_changed',
            icon = '柳',
            hl = {fg = colors.yellow},
            left_sep = ' '
        },
        diffremove = {
            provider = 'git_diff_removed',
            icon = ' ',
            hl = {fg = colors.red},
            left_sep = ' '
        }
    }

    -- Initialize the components table before defining it
    local components = {
        active = {},
        inactive = {}
    }

    table.insert(components.active, {})
    table.insert(components.active, {})
    table.insert(components.active, {})
    table.insert(components.inactive, {})
    table.insert(components.inactive, {})

    table.insert(components.active[1], comps.dummy)
    table.insert(components.active[1], comps.vi_mode)
    table.insert(components.active[1], comps.filesize)
    table.insert(components.active[1], comps.fileinfo)
    table.insert(components.active[1], comps.lineinfo)
    table.insert(components.active[1], comps.percent)
    table.insert(components.active[3], comps.codeact)
    table.insert(components.active[3], comps.diagerr)
    table.insert(components.active[3], comps.diagwarn)
    table.insert(components.active[3], comps.diaghint)
    table.insert(components.active[3], comps.diaginfo)
    table.insert(components.active[3], comps.lspclient)
    table.insert(components.active[3], comps.format)
    table.insert(components.active[3], comps.encode)
    table.insert(components.active[3], comps.filetype)
    table.insert(components.active[3], comps.gitbranch)
    table.insert(components.active[3], comps.diffadd)
    table.insert(components.active[3], comps.diffchange)
    table.insert(components.active[3], comps.diffremove)
    table.insert(components.inactive[1], comps.dummy)
    table.insert(components.inactive[1], comps.fileinfo)
    table.insert(components.inactive[2], comps.filetype)

    require('feline').setup {
        colors = {bg = colors.grey1, fg = colors.fg},
        components = components,
        vi_mode_colors = vi_mode_colors,
        force_inactive = {
            filetypes = {
                'packer',
                'dashboard',
                'alpha',
                'NvimTree',
                'undotree',
                'DIFF',
                'TROUBLE',
                'Outline'
            },
            buftypes = {'terminal', 'nofile'},
            bufnames = {}
        }
    }
end

function M.bufferline_conf()
    require('bufferline').setup {
        options = {
            numbers = 'none',
            max_name_length = 16,
            max_prefix_length = 13,
            tab_size = 16,
            diagnostics = false, -- 'nvim_lsp'
            -- diagnostics_update_in_insert = false,
            -- diagnostics_indicator = function(count, level, diagnostics_dict, context)
            --     local s = ''
            --     for e, n in pairs(diagnostics_dict) do
            --         local sym = e == 'error' and 'x ' or (e == 'warning' and '! ' or (e == 'info' and 'i ' or '? '))
            --         s = s .. n .. sym
            --     end
            --     return s
            -- end,
            show_close_icon = false,
            show_buffer_icons = true,
            show_tab_indicators = true,
            enforce_regular_tabs = false,
            show_buffer_close_icons = false,
            always_show_bufferline = true,
            offsets = {
                {filetype = 'NvimTree', text = 'NvimTree', text_align = 'center'},
                {filetype = 'packer', text = 'Packer', text_align = 'center'}
            },
            separator_style = 'thin'
        },
        highlights = {
            fill = {guibg = {attribute = 'bg', highlight = 'TabLineFill'}},
            indicator_selected = {guifg = {attribute = 'fg', highlight = 'TabLineSel'}},
            -- diagnostic_selected = {guifg = {attribute = 'fg', highlight = 'LspDiagnosticsSignHint', gui = 'bold,italic'}},
            -- info_diagnostic_selected = {guifg = {attribute = 'fg', highlight = 'LspDiagnosticsSignInformation', gui = 'bold,italic'}},
            -- info_selected = {guifg = {attribute = 'fg', highlight = 'LspDiagnosticsDefaultInformation', gui = 'bold,italic'}},
            -- warning_diagnostic_selected = {guifg = {attribute = 'fg', highlight = 'LspDiagnosticsSignWarning', gui = 'bold,italic'}},
            -- warning_selected = {guifg = {attribute = 'fg', highlight = 'LspDiagnosticsDefaultWarning', gui = 'bold,italic'}},
            -- error_diagnostic_selected = {guifg = {attribute = 'fg', highlight = 'LspDiagnosticsSignError', gui = 'bold,italic'}},
            -- error_selected = {guifg = {attribute = 'fg', highlight = 'LspDiagnosticsDefaultError', gui = 'bold,italic'}}
        }
    }
end

-- FIX: wait for config migration to setup()
function M.nvimtree_conf()
    vim.g.nvim_tree_gitignore = 1
    vim.g.nvim_tree_ignore = {'.git', '.hg', '.svn', 'node_modules'}
    vim.g.nvim_tree_auto_ignore_ft = {'dashboard', 'alpha'}
    vim.g.nvim_tree_indent_markers = 1
    vim.g.nvim_tree_git_hl = 1
    vim.g.nvim_tree_highlight_opened_files = 1
    -- vim.g.nvim_tree_add_trailing = 1
    -- vim.g.nvim_tree_disable_window_picker = 1
    -- vim.g.nvim_tree_symlink_arrow = ' ➛ '
    vim.g.nvim_tree_respect_buf_cwd = 1
    -- vim.g.nvim_tree_create_in_closed_folder = 1
    vim.g.nvim_tree_icons = {
        default = '',
        symlink = '',
        git = {
            unstaged = '',
            staged = '',
            unmerged = '',
            renamed = '',
            untracked = 'ﱡ',
            deleted = '',
            ignored = ''
        },
        folder = {
            arrow_open = '',
            arrow_closed = '',
            default = '',
            open = 'ﱮ',
            empty = '',
            empty_open = '',
            symlink = '',
            symlink_open = 'ﱮ'
        }
    }

    require('nvim-tree').setup {
        open_on_setup = false,
        ignore_ft_on_setup  = {'dashboard', 'alpha'},
        auto_close = true,
        open_on_tab = false,
        update_to_buf_dir = {
            enable = false,
            auto_open = true
        },
        hijack_cursor = true,
        update_cwd = true,
        diagnostics = {
            enable = true,
            icons = {
                hint = '',
                info = '',
                warning = '',
                error = ''
            }
        },
        update_focused_file = {
            enable = true,
            update_cwd = true,
            ignore_list = {}
        },
        system_open = {
            cmd = 'xdg-open',
            args = {}
        },
        view = {
            width = 35,
            side = 'left',
            auto_resize = false
        }
    }
end

function M.whichkey_conf()
    require('which-key').setup {
        plugins = {
            spelling = {
                enabled = true,
                suggestions = 30
            }
        },
        icons = {
            breadcrumb = '»',
            separator = 'ﰲ',
            group = '+'
        },
        layout = {
            align = 'center'
        }
    }
end

function M.gitsigns_conf()
    require('gitsigns').setup {
        signs = {
            add          = {hl = 'DiffAdd'   , text = '', numhl='GitSignsAddNr'},
            change       = {hl = 'DiffChange', text = '', numhl='GitSignsChangeNr'},
            delete       = {hl = 'DiffDelete', text = '', numhl='GitSignsDeleteNr'},
            topdelete    = {hl = 'DiffDelete', text = '', numhl='GitSignsDeleteNr'},
            changedelete = {hl = 'DiffChange', text = '', numhl='GitSignsChangeNr'}
        },
        signcolumn = false,
        numhl = true,
        linehl = false,
        word_diff = false,
        keymaps = {
            -- Default keymap options
            noremap = true,

            ['n ]g'] = {expr = true, '&diff ? \']g\' : \':lua require"gitsigns.actions".next_hunk()<CR>\''},
            ['n [g'] = {expr = true, '&diff ? \'[g\' : \':lua require"gitsigns.actions".prev_hunk()<CR>\''},

            ['n <leader>gs'] = ':lua require"gitsigns".stage_hunk()<CR>',
            ['v <leader>gs'] = ':lua require"gitsigns".stage_hunk({vim.fn.line("."), vim.fn.line("v")})<CR>',
            ['n <leader>gu'] = ':lua require"gitsigns".undo_stage_hunk()<CR>',
            ['n <leader>gr'] = ':lua require"gitsigns".reset_hunk()<CR>',
            ['v <leader>gr'] = ':lua require"gitsigns".reset_hunk({vim.fn.line("."), vim.fn.line("v")})<CR>',
            ['n <leader>gR'] = ':lua require"gitsigns".reset_buffer()<CR>',
            ['n <leader>gp'] = ':lua require"gitsigns".preview_hunk()<CR>',
            ['n <leader>gb'] = ':lua require"gitsigns".blame_line(true)<CR>',
            ['n <leader>gS'] = ':lua require"gitsigns".stage_buffer()<CR>',
            ['n <leader>gU'] = ':lua require"gitsigns".reset_buffer_index()<CR>',

            -- Text objects
            ['o ih'] = ':<C-U>lua require"gitsigns.actions".select_hunk()<CR>',
            ['x ih'] = ':<C-U>lua require"gitsigns.actions".select_hunk()<CR>'
        },
        watch_gitdir = {
            interval = 1000,
            follow_files = true
        },
        attach_to_untracked = true,
        current_line_blame = false,
        current_line_blame_opts = {
            delay = 1000,
            virt_text = true,
            virt_text_pos = 'right_align'
        },
        current_line_blame_formatter_opts = {
            relative_time = false
        },
        sign_priority = 6,
        update_debounce = 100,
        status_formatter = nil, -- Use default
        max_file_length = 40000,
        preview_config = {
            -- Options passed to nvim_open_win
            border = 'single',
            style = 'minimal',
            relative = 'cursor',
            row = 0,
            col = 1
        },
        yadm = {
            enable = false
        },
        diff_opts = {
            algorithm = 'myers', -- others: 'minimal', 'patience', 'histogram'
            internal = true -- If luajit is present
        }
    }
end

return M
