local wezterm = require("wezterm")
local M = {}

M.alert_popup_before_seconds = 15
M.alert_if_in_next_minutes = 30
M.theme_bg = "#2c323c"
M.theme_red = "#f92572"
M.nerd_font_meeting = "󰤙"

M.ical_buddy = "/usr/local/bin/icalBuddy"
M.ignored_cal = "Birthdays, Family, Contacts, School, Home, Canadian Holidays, Canadiens, Jours fériés au Canada"

local function execute_command(command)
	local f = io.popen(command)
	if f == nil then
		return ""
	end
	local result = f:read("*all")
	f:close()
	return result
end

local function check_ical_buddy()
	local result = execute_command("test -f " .. M.ical_buddy)
	if result == "" then
		wezterm.log_error("Error: iCalBuddy is not installed")
		return false
	end
	return true
end

local function get_meeting_command(event_filter)
	return string.format(
		'%s --includeEventProps "title,datetime,attendees" --propertyOrder "title,datetime" --noCalendarNames --dateFormat "%%A" --includeOnlyEventsFromNowOn --limitItems 1 --excludeAllDayEvents --separateByDate --excludeCals "%s" %s',
		M.ical_buddy,
		M.ignored_cal,
		event_filter
	)
end

local function get_next_meeting()
	local command = get_meeting_command("eventsToday")
	local next_meeting = execute_command(command)
	if next_meeting == "" then
		return nil
	end
	return next_meeting
end

local function parse_result(ical_output)
	local title, start_time, end_time, attendees
	for line in ical_output:gmatch("[^\r\n]+") do
		if line:match("%d%d:%d%d - %d%d:%d%d") then
			start_time = line:match("(%d%d:%d%d) -")
			end_time = line:match(" - (%d%d:%d%d)")
		end
		if line:match("attendees:") then
			attendees = line:gsub("attendees: ", ""):gsub("^%s*(.-)%s*$", "%1")
		end
	end
	title = ical_output:match("[^\r\n]+")
	return { title = title, start_time = start_time, end_time = end_time, attendees = attendees }
end

local function calculate_times(start_time)
	if not start_time then
		return nil
	end

	local current_date = os.date("*t")
	local epoc_meeting = os.time({
		year = current_date.year,
		month = current_date.month,
		day = current_date.day,
		hour = tonumber(start_time:sub(1, 2)),
		min = tonumber(start_time:sub(4, 5)),
		sec = 0,
	})
	local epoc_now = os.time()
	local epoc_diff = epoc_meeting - epoc_now
	local minutes_till_meeting = math.floor(epoc_diff / 60)

	return { minutes_till_meeting = minutes_till_meeting, epoc_diff = epoc_diff }
end

local function display_popup(meeting)
	local meeting_info = string.format(
		"Title: %s\nStart Time: %s\nEnd Time: %s\nAttendees: %s",
		meeting.title,
		meeting.start_time,
		meeting.end_time,
		meeting.attendees
	)
	wezterm.gui.show_popup(meeting_info)
end

local function update_tab_bar(times, meeting)
	local status = wezterm.format({
		{ Background = { Color = M.theme_bg } },
		{ Foreground = { Color = M.theme_red } },
		{
			Text = string.format(
				" %s %s (%d minutes) ",
				M.nerd_font_meeting,
				meeting.title,
				times.minutes_till_meeting
			),
		},
	})

	if times.epoc_diff <= M.alert_popup_before_seconds then
		display_popup(meeting)
	end

	return status
end

function M.main()
	print("here")
	if not check_ical_buddy() then
		return ""
	end

	local next_meeting = get_next_meeting()
	if not next_meeting then
		return ""
	end

	local meeting = parse_result(next_meeting)
	local times = calculate_times(meeting.start_time)
	if not times then
		return ""
	end

	return update_tab_bar(times, meeting)
end

function M.setup_update_timer(interval_seconds)
	interval_seconds = interval_seconds or 60 -- Default interval is 60 seconds

	local function update()
		local meeting_status = M.main()
		if meeting_status ~= "" then
			wezterm.on("update-right-status", function(window)
				window:set_right_status(wezterm.format({
					{ Text = meeting_status },
				}))
			end)
		end
	end

	-- Initially update
	update()

	-- Set up periodic update timer
	wezterm.update_built_in_timer("meeting_notifier_update", interval_seconds, update)
end

return M
