--init.lua, FPS++ bootstrap. creates the Details Framework addon object, defines the
--default profile, and wires the lifecycle hooks. loaded early (right after the
--localization), so it only references the core and UI systems inside the lifecycle
--callbacks, which fire after every addon file has finished loading.

local _ = nil
local addonName, private = ...

local detailsFramework = DetailsFramework or LibStub("DetailsFramework-1.0")

---@class profile : table
---@field enabled boolean
---@field context context_profile
---@field ui ui_profile
---@field manual_hide manual_hide_profile
---@field graphics graphics_profile
---@field graphics_cvars graphics_cvars_profile
---@field event_counter event_counter_profile
---@field safety safety_profile
---@field unit_frames unit_frames_profile

---@class context_profile : table
---@field in_dungeon boolean
---@field in_dungeon_encounter boolean
---@field in_raid boolean
---@field in_raid_encounter boolean
---@field always boolean

---@class ui_profile : table
---@field disable_minimap boolean
---@field disable_buffs boolean
---@field disable_raid_frames boolean
---@field disable_action_bars boolean
---@field disable_damage_meter boolean

---@class manual_hide_profile : table
---@field minimap boolean
---@field buffs boolean
---@field raid_frames boolean
---@field action_bars boolean

---@class graphics_profile : table
---@field reduce_particle_density boolean
---@field reduce_shadows boolean

---@class graphics_cvars_profile : table
---@field liquid_detail boolean
---@field shadow_quality boolean
---@field depth_effects boolean
---@field outline_mode boolean
---@field spell_density boolean
---@field environment_detail boolean
---@field ground_clutter boolean
---@field view_distance boolean
---@field anti_aliasing boolean

---@class event_counter_profile : table
---@field enabled boolean

---@class safety_profile : table
---@field restore_on_disable boolean
---@field defer_combat_changes boolean

---@class unit_frames_profile : table
---@field enabled boolean
---@field max_debuff_icons number
---@field debuff_icon_size number
---@field debuff_icon_spacing number
---@field unit_width number
---@field unit_height number
---@field unit_scale number
---@field unit_vertical_padding number
---@field show_unit_name boolean
---@field anchor unit_frames_anchor_profile
---@field raid_anchor unit_frames_anchor_profile
---@field keybinds unit_frames_keybind_profile[]

---@class unit_frames_anchor_profile : table
---@field x number
---@field y number

---@class unit_frames_keybind_profile : table
---@field keybind string --the key combination, e.g. "F" or "SHIFT-Q"
---@field action string --"spell" | "macro" | "target" | "focus" | "togglemenu"
---@field spellId number --required when action is "spell"
---@field macro string --required when action is "macro", e.g. "/cast [@mouseover] Rejuvenation"

--the default profile; every optimization behavior must have a key here. it is
--passed to CreateNewAddOn as the saved-vars template (it must exist before that
--call, which is why it lives here and not in core/profile.lua). top-level keys
--become addon.profile fields directly, with no extra "profile" wrapper.
---@type profile
private.defaultProfile = {
	enabled = true,

	--when the FPS reductions apply: while ANY checked condition is true (see core/context.lua).
	--"always" overrides the rest. reductions no longer apply immediately -- they follow this gate.
	context = {
		in_dungeon = false,
		in_dungeon_encounter = false,
		in_raid = false,
		--"Raid Encounters": on by default so reductions apply during raid boss fights out of the box.
		in_raid_encounter = true,
		always = false,
	},

	--Blizzard UI to hide while the context gate is active. the minimap fades out via
	--core/ui_disabler.lua; buffs/raid frames/action bars hide via core/manual_hide.lua
	--(raid frames and action bars are protected, so an in-combat change applies on combat end).
	ui = {
		disable_minimap = true,
		disable_buffs = true,
		disable_raid_frames = false,
		disable_action_bars = false,
		--"Hide Blizzard Damage Meter": like the other UI hides, gated by the context (see
		--core/optimizer.lua). on by default: the built-in meter processes combat log events, so
		--disabling it during the chosen context is a free FPS win most players want.
		disable_damage_meter = true,
	},

	--immediate manual "hide this now" toggles for live FPS testing (see core/manual_hide.lua).
	--independent of the master switch and the encounter feature; controlled by their checkboxes.
	manual_hide = {
		minimap = false,
		buffs = false,
		raid_frames = false,
		action_bars = false,
	},

	graphics = {
		reduce_particle_density = true,
		reduce_shadows = true,
	},

	--graphics CVar reductions: context-gated in the main options panel (applied while a chosen context
	--is active) and mirrored as live-preview toggles in the Live FPS Test window (see core/optimizer.lua
	--managedGraphicsCVars). each drops its CVar(s) to the lowest.
	graphics_cvars = {
		liquid_detail = true,
		--"Shadows": drops graphicsShadowQuality to 0 AND disables ambient occlusion (SSAO) together.
		shadow_quality = true,
		depth_effects = true,
		outline_mode = true,
		spell_density = true,
		environment_detail = true,
		ground_clutter = true,
		--"View Distance": far clip 1500 + graphicsViewDistance 0 together.
		view_distance = true,
		--zeroes MSAA (the expensive one) and the post-process AA mode together.
		anti_aliasing = true,
	},

	--diagnostic: tally how often each game event fires during a boss encounter (core/event_counter.lua).
	event_counter = {
		enabled = false,
	},

	safety = {
		restore_on_disable = true,
		defer_combat_changes = true,
	},

	--lightweight party/raid unit frames (health bar + debuffs only). handled by the
	--core/unitframes*.lua engine via the optimizer. disabled by default: it adds frames
	--alongside Blizzard's, so the player opts in. keybinds is a list of mouseover bindings
	--(see unit_frames_keybind_profile); empty by default.
	unit_frames = {
		enabled = false,
		max_debuff_icons = 3,
		debuff_icon_size = 20,
		debuff_icon_spacing = 1,
		unit_width = 80,
		unit_height = 34,
		unit_scale = 1,
		unit_vertical_padding = 5,
		show_unit_name = true,
		anchor = {x = 481, y = -522},
		raid_anchor = {x = 300, y = -100},
		keybinds = {},
	},
}

--prints a prefixed message to the default chat frame.
function private.Print(...)
	print("|cff44dd44FPS++|r:", ...)
end

--create the addon object. the name must match the .toc folder name and the
--saved-vars name must match the ## SavedVariables line, or settings are lost.
local addon = detailsFramework:CreateNewAddOn(addonName, "FPSPlusPlusDB", private.defaultProfile)
private.addon = addon
private.addonName = addonName

--on ADDON_LOADED: saved variables are ready and addon.profile is populated.
--profile-ready, non-UI setup goes here.
function addon:OnLoad()
	--create the default role profiles (tank/damager/healer) so each character can pick one.
	private.Core.Profile:EnsureDefaultProfiles()
end

--on PLAYER_LOGIN: the world is loaded and frames are safe to touch. initialize
--every system once here (no lazy init) and apply the active profile.
function addon:OnInit()
	private.Core.Safety:Initialize()
	private.Core.Encounter:Initialize()
	private.Core.Context:Initialize()
	private.Core.EventCounter:Initialize()
	private.UI.Options:Initialize()
	private.UI.FPSMonitor:Initialize(private.UI.Options:GetMainPanel())
	private.UI.EventPanel:Initialize(private.UI.Options:GetMainPanel())
	--register the spec-change handler and switch to this character's role profile (if auto-switch is
	--on). a switch here fires OnProfileChanged, which re-applies via the optimizer; the call below then
	--applies the resulting profile (idempotent).
	private.Core.Profile:Initialize()
	private.Core.ManualHide:Initialize()
	private.Core.Optimizer:ApplyProfile()
end

--fired by DetailsFramework.SavedVars.SetProfile when the active profile changes.
function addon:OnProfileChanged()
	private.Core.Optimizer:RestoreAll()
	private.Core.Optimizer:ApplyProfile()
	private.UI.Options:RefreshIfOpen()
end
