-- Pull in the wezterm API
local wezterm = require("wezterm")
local act = wezterm.action

-- Pull custom modules
local theme = require("theme-switcher")
-- local meeting_notifier = require("meeting-notifier")
local profiler = require("profiler")
local history = require("history")

local config = {}
local keys = {}
local key_tables = {}

-- This will hold the configuration.
if wezterm.config_builer then
	config = wezterm.config_builder()
end

config.debug_key_events = false

if wezterm.target_triple == "x86_64-pc-windows-msvc" then
	-- Windows-specific settings
	config.default_prog = { "wsl.exe", "~", "-d", "Ubuntu-20.04" }
elseif wezterm.target_triple == "x86_64-apple-darwin" then
	-- macOS-specific settings
	config.macos_window_background_blur = 10
	config.default_prog = { "/bin/zsh" }
	config.font = wezterm.font_with_fallback({
		{ family = "MesloLGS NF",       scale = 0.9 },
		{ family = "Symbols Nerd Font", scale = 0.9 },
	})
elseif wezterm.target_triple == "x86_64-unknown-linux-gnu" then
	-- Linux-specific settings
	config.default_prog = { "/bin/bash" }
	config.font = wezterm.font_with_fallback({
		{ family = "MesloLGS NF", scale = 0.9 },
		{ family = "Ubuntu Mono", scale = 0.9 },
	})
end

config.check_for_updates = true
config.use_ime = true
config.term = "xterm-256color"
theme.apply_to_config(config)
config.line_height = 1.1

config.window_padding = {
	left = 5,
	right = 10,
	top = 10,
	bottom = 5,
}

config.inactive_pane_hsb = {
	saturation = 0.9,
	brightness = 0.7,
}

-- Activate if you need to debug spawn commands
-- config.exit_behavior = "Hold"

config.initial_rows = 50
config.initial_cols = 140

config.use_dead_keys = false
config.enable_scroll_bar = false
config.scrollback_lines = 3000

config.adjust_window_size_when_changing_font_size = false
config.window_decorations = "RESIZE | MACOS_FORCE_ENABLE_SHADOW"
config.enable_tab_bar = false
config.use_fancy_tab_bar = false
config.tab_max_width = 25
config.switch_to_last_active_tab_when_closing_tab = true
config.show_new_tab_button_in_tab_bar = false

config.audible_bell = "Disabled"

config.window_frame = {
	font = wezterm.font({ family = "Meslo NF", weight = "Regular" }),
}

config.hyperlink_rules = {
	-- Matches: a URL in parens: (URL)
	{
		regex = "\\((\\w+://\\S+)\\)",
		format = "$1",
		highlight = 1,
	},
	-- Matches: a URL in brackets: [URL]
	{
		regex = "\\[(\\w+://\\S+)\\]",
		format = "$1",
		highlight = 1,
	},
	-- Matches: a URL in curly braces: {URL}
	{
		regex = "\\{(\\w+://\\S+)\\}",
		format = "$1",
		highlight = 1,
	},
	-- Matches: a URL in angle brackets: <URL>
	{
		regex = "<(\\w+://\\S+)>",
		format = "$1",
		highlight = 1,
	},
	-- Then handle URLs not wrapped in brackets
	{
		regex = "[^(]\\b(\\w+://\\S+[)/a-zA-Z0-9-]+)",
		format = "$1",
		highlight = 1,
	},
	-- implicit mailto link
	{
		regex = "\\b\\w+@[\\w-]+(\\.[\\w-]+)+\\b",
		format = "mailto:$0",
	},
}

config.set_environment_variables = {
	PATH = wezterm.home_dir .. "/.local/bin/scripts:" .. "/usr/local/bin:" .. os.getenv("PATH"),
}

config.leader = { key = "a", mods = "CTRL", timeout_milliseconds = 1000 }
keys = {
	{ key = "LeftArrow",  mods = "OPT",    action = act.SendString("\x1bb") },
	{ key = "RightArrow", mods = "OPT",    action = act.SendString("\x1bf") },

	-- The physical CMD key on OSX is the Alt key on Win/*nix, so map the common Alt-combo commands.
	{ key = ".",          mods = "CMD",    action = act.SendString("\x1b.") },
	{ key = "p",          mods = "CMD",    action = act.SendString("\x1bp") },
	{ key = "n",          mods = "CMD",    action = act.SendString("\x1bn") },
	{ key = "b",          mods = "CMD",    action = act.SendString("\x1bb") },
	{ key = "f",          mods = "CMD",    action = act.SendString("\x1bf") },

	-- Window management
	{ key = "a",          mods = "LEADER", action = act({ SendString = "`" }) },
	{ key = "v",          mods = "LEADER", action = act({ SplitVertical = { domain = "CurrentPaneDomain" } }) },
	{ key = "b",          mods = "LEADER", action = act.SplitHorizontal({ domain = "CurrentPaneDomain" }) },
	{ key = "z",          mods = "LEADER", action = "TogglePaneZoomState" },
	{ key = "c",          mods = "LEADER", action = act({ SpawnTab = "CurrentPaneDomain" }) },
	{ key = "n",          mods = "LEADER", action = act({ ActivateTabRelative = 1 }) },
	{ key = "p",          mods = "LEADER", action = act({ ActivateTabRelative = -1 }) },

	{ key = "h",          mods = "LEADER", action = act.ActivatePaneDirection("Left") },
	{ key = "j",          mods = "LEADER", action = act.ActivatePaneDirection("Down") },
	{ key = "k",          mods = "LEADER", action = act.ActivatePaneDirection("Up") },
	{ key = "l",          mods = "LEADER", action = act.ActivatePaneDirection("Right") },

	{ key = "H",          mods = "LEADER", action = act({ AdjustPaneSize = { "Left", 5 } }) },
	{ key = "J",          mods = "LEADER", action = act({ AdjustPaneSize = { "Down", 5 } }) },
	{ key = "K",          mods = "LEADER", action = act({ AdjustPaneSize = { "Up", 5 } }) },
	{ key = "L",          mods = "LEADER", action = act({ AdjustPaneSize = { "Right", 5 } }) },

	{ key = "`",          mods = "LEADER", action = act.ActivateLastTab },
	{ key = " ",          mods = "LEADER", action = act.ActivateTabRelative(1) },
	{ key = "x",          mods = "LEADER", action = act({ CloseCurrentPane = { confirm = true } }) },

	{
		key = "f",
		mods = "LEADER",
		action = act.SpawnCommandInNewTab({
			args = { "sessionizer" },
		}),
	},

	{
		key = "d",
		mods = "LEADER",
		action = wezterm.action_callback(function(window, pane)
			window:perform_action(act.SendString("wzp\n"), pane)
		end),
	},

	{
		key = "o",
		mods = "LEADER",
		action = wezterm.action_callback(function(window, pane)
			window:perform_action(act.SendString("vim .\n"), pane)
		end),
	},

	-- {
	-- 	key = "j",
	-- 	mods = "LEADER",
	-- 	action = wezterm.action_callback(function(window, pane)
	-- 		-- Get a list of tab titles
	-- 		local tabs = window:tabs_with_info()
	-- 		local tab_titles = {}
	-- 		for _, tab in ipairs(tabs) do
	-- 			table.insert(tab_titles, tab.index .. ": " .. tab.active_pane.title)
	-- 		end
	--
	-- 		-- Join the tab titles with newlines
	-- 		local tab_list = table.concat(tab_titles, "\n")
	--
	-- 		-- Run fzf on the tab list
	-- 		local result = wezterm.run_child_process({
	-- 			"sh", "-c", "echo -e '" .. tab_list .. "' | fzf --reverse"
	-- 		})
	--
	-- 		-- Extract the selected tab index
	-- 		if result.exit_status == 0 then
	-- 			local selected_tab = tonumber(result.stdout:match("^(%d+):"))
	-- 			if selected_tab then
	-- 				window:perform_action(wezterm.action { ActivateTab = selected_tab - 1 }, pane)
	-- 			end
	-- 		end
	-- 	end),
	-- },

	{ key = "w", mods = "LEADER", action = act.ShowTabNavigator },

	-- Activate Copy Mode
	{ key = "[", mods = "LEADER", action = act.ActivateCopyMode },
	-- Paste from Copy Mode
	{ key = "y", mods = "LEADER", action = act.PasteFrom("PrimarySelection") },

	--open wezterm config quickly
	{
		key = ",",
		mods = "LEADER",
		action = act.SpawnCommandInNewTab({
			cwd = os.getenv("WEZTERM_CONFIG_DIR"),
			set_environment_variables = {
				TERM = "screen-256color",
			},
			args = {
				"/usr/local/bin/nvim",
				os.getenv("WEZTERM_CONFIG_FILE"),
			},
		}),
	},

	{
		key = "r",
		mods = "LEADER",
		action = act.ReloadConfiguration,
	},

	-- Swich to default workspace
	{
		key = "y",
		mods = "CTRL | SHIFT",
		action = act.SwitchToWorkspace({
			name = "default",
		})
	},

	--Switch to monitoring workspace
	{
		key = "m",
		mods = "CTRL | SHIFT",
		action = act.SwitchToWorkspace({
			name = "monitoring",
			spawn = {
				args = { "top" },
			},
		}),
	},

	-- Create a new workspace with a randomm anem and switch to it
	{ key = "i", mods = "CTRL | SHIFT", action = act.SwitchToWorkspace },

	-- Show command history
	-- {
	-- 	key = "r",
	-- 	mods = "CTRL",
	-- 	action = wezterm.action_callback(function()
	-- 		history.show_command_history()
	-- 	end),
	-- },


	--Show launcher in fuzzy selecton mode
	{
		key = "s",
		mods = "CTRL | SHIFT",
		action = act.ShowLauncherArgs({
			flags = "FUZZY|WORKSPACES",
		}),
	},
}

key_tables = {
	copy_mode = {
		{ key = "c",          mods = "CTRL",  action = act.CopyMode("Close") },
		{ key = "q",          mods = "NONE",  action = act.CopyMode("Close") },
		{ key = "Escape",     mods = "NONE",  action = act.CopyMode("Close") },

		{ key = "h",          mods = "NONE",  action = act.CopyMode("MoveLeft") },
		{ key = "j",          mods = "NONE",  action = act.CopyMode("MoveDown") },
		{ key = "k",          mods = "NONE",  action = act.CopyMode("MoveUp") },
		{ key = "l",          mods = "NONE",  action = act.CopyMode("MoveRight") },

		{ key = "LeftArrow",  mods = "NONE",  action = act.CopyMode("MoveLeft") },
		{ key = "DownArrow",  mods = "NONE",  action = act.CopyMode("MoveDown") },
		{ key = "UpArrow",    mods = "NONE",  action = act.CopyMode("MoveUp") },
		{ key = "RightArrow", mods = "NONE",  action = act.CopyMode("MoveRight") },

		{ key = "RightArrow", mods = "ALT",   action = act.CopyMode("MoveForwardWord") },
		{ key = "f",          mods = "ALT",   action = act.CopyMode("MoveForwardWord") },
		{ key = "Tab",        mods = "NONE",  action = act.CopyMode("MoveForwardWord") },

		{ key = "LeftArrow",  mods = "ALT",   action = act.CopyMode("MoveBackwardWord") },
		{ key = "b",          mods = "ALT",   action = act.CopyMode("MoveBackwardWord") },
		{ key = "Tab",        mods = "SHIFT", action = act.CopyMode("MoveBackwardWord") },

		{ key = "0",          mods = "NONE",  action = act.CopyMode("MoveToStartOfLine") },
		{ key = "Enter",      mods = "NONE",  action = act.CopyMode("MoveToStartOfNextLine") },

		{ key = "$",          mods = "NONE",  action = act.CopyMode("MoveToEndOfLineContent") },
		{ key = "$",          mods = "SHIFT", action = act.CopyMode("MoveToEndOfLineContent") },
		{ key = "^",          mods = "NONE",  action = act.CopyMode("MoveToStartOfLineContent") },
		{ key = "^",          mods = "SHIFT", action = act.CopyMode("MoveToStartOfLineContent") },

		{ key = "v",          mods = "NONE",  action = act.CopyMode({ SetSelectionMode = "Cell" }) },
		{ key = "V",          mods = "NONE",  action = act.CopyMode({ SetSelectionMode = "Line" }) },
		{ key = "V",          mods = "SHIFT", action = act.CopyMode({ SetSelectionMode = "Line" }) },
		{ key = "v",          mods = "CTRL",  action = act.CopyMode({ SetSelectionMode = "Block" }) },

		{ key = "G",          mods = "NONE",  action = act.CopyMode("MoveToScrollbackBottom") },
		{ key = "G",          mods = "SHIFT", action = act.CopyMode("MoveToScrollbackBottom") },
		{ key = "g",          mods = "NONE",  action = act.CopyMode("MoveToScrollbackTop") },

		{ key = "H",          mods = "NONE",  action = act.CopyMode("MoveToViewportTop") },
		{ key = "H",          mods = "SHIFT", action = act.CopyMode("MoveToViewportTop") },
		{ key = "M",          mods = "NONE",  action = act.CopyMode("MoveToViewportMiddle") },
		{ key = "M",          mods = "SHIFT", action = act.CopyMode("MoveToViewportMiddle") },
		{ key = "L",          mods = "NONE",  action = act.CopyMode("MoveToViewportBottom") },
		{ key = "L",          mods = "SHIFT", action = act.CopyMode("MoveToViewportBottom") },

		{ key = "o",          mods = "NONE",  action = act.CopyMode("MoveToSelectionOtherEnd") },
		{ key = "O",          mods = "NONE",  action = act.CopyMode("MoveToSelectionOtherEndHoriz") },
		{ key = "O",          mods = "SHIFT", action = act.CopyMode("MoveToSelectionOtherEndHoriz") },

		{ key = "PageUp",     mods = "NONE",  action = act.CopyMode("PageUp") },
		{ key = "PageDown",   mods = "NONE",  action = act.CopyMode("PageDown") },

		{ key = "b",          mods = "CTRL",  action = act.CopyMode("PageUp") },
		{ key = "f",          mods = "CTRL",  action = act.CopyMode("PageDown") },

		-- Enter y to copy and quit the copy mode.
		{
			key = "y",
			mods = "NONE",
			action = act.Multiple({
				act.CopyTo("ClipboardAndPrimarySelection"),
				act.CopyMode("Close"),
			}),
		},

		-- Enter search mode to edit the pattern.
		-- When the search pattern is an empty string the existing pattern is preserved
		{ key = "/", mods = "NONE", action = act({ Search = { CaseSensitiveString = "" } }) },
		{ key = "?", mods = "NONE", action = act({ Search = { CaseInSensitiveString = "" } }) },
		{ key = "n", mods = "CTRL", action = act({ CopyMode = "NextMatch" }) },
		{ key = "p", mods = "CTRL", action = act({ CopyMode = "PriorMatch" }) },
	},

	search_mode = {
		{ key = "Escape", mods = "NONE", action = act({ CopyMode = "Close" }) },
		-- Go back to copy mode when pressing enter, so that we can use unmodified keys like "n"
		-- to navigate search results without conflicting with typing into the search area.
		{ key = "Enter",  mods = "NONE", action = "ActivateCopyMode" },
		{ key = "c",      mods = "CTRL", action = "ActivateCopyMode" },
		{ key = "n",      mods = "CTRL", action = act({ CopyMode = "NextMatch" }) },
		{ key = "p",      mods = "CTRL", action = act({ CopyMode = "PriorMatch" }) },
		{ key = "r",      mods = "CTRL", action = act.CopyMode("CycleMatchType") },
		{ key = "u",      mods = "CTRL", action = act.CopyMode("ClearPattern") },
	},
}

-- -- move prompt to the bottom
-- local function move_prompt_to_bottom()
-- 	os.execute("tput cup $LINES")
-- end

-- config.on_start = move_prompt_to_bottom()

config.keys = keys
config.key_tables = key_tables

wezterm.on("gui-startup", function()
	profiler.startup("WZ_PROJECT", "profiles")
end)

wezterm.on("mux-is-process-stateful", function(proc)
	_ = proc
	return nil
end)

wezterm.on("format-tab-title", function(tab)
	local pane = tab.active_pane
	local title = pane.title

	if pane.domain_name ~= "local" then
		title = title .. " - (" .. pane.current_working_dir .. ")"
	end

	return title
end)

-- Setup the update timer for meeting notification
-- meeting_notifier.setup_update_timer(5) -- Update every 60 seconds

wezterm.on("update-right-status", function(window)
	local stat = window:active_workspace()

	if window:active_key_table() then
		stat = window:active_key_table()
	end
	if window:leader_is_active() then
		stat = "L"
	end

	local date = wezterm.strftime("%a %b %-d %H:%M")

	window:set_right_status(wezterm.format({
		{ Text = stat },
		{ Text = " | " },
		{ Text = date },
	}))
end)

config.default_prog = { "/usr/local/bin/zsh" }

return config

