-- This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
-- To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/
-- or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.
local MereHealingFrames, privateVars = ...

MereHealingFrames.SpellSets = {}
MereHealingFrames.CurrentSpellSet = {}

MereHealingFrames.Spells = {}

local function FindSpellForSoul(soulSpec)
    local currentSpellSet = nil
    local currentSpellSetName = nil
    for setName, spellSet in pairs(MereHealingFrames.SpellSets) do
        if not spellSet.SoulSpecs or spellSet.SoulSpecs[soulSpec] then
            currentSpellSet = spellSet
            currentSpellSetName = setName
            break
        end
    end
    return currentSpellSet, currentSpellSetName
end

function MereHealingFrames.Spells.UpdateCurrentSpellSet()
	local currentSoulSpec = Inspect.TEMPORARY.Role()

	if currentSoulSpec == nil then
		currentSoulSpec = 1
	end

	MereHealingFrames.Debug(1, "UpdateCurrentSpellSet: Using Soul %d", currentSoulSpec)

	local currentSpellSet, currentSpellSetName = FindSpellForSoul(currentSoulSpec)

	if not currentSpellSet then
        print("Unable to find a valid spell Set for this soul, please configure a spell set for the current role (Note this maybe a glitch while transitioning to larger number of roles)")

        if (MereHealingFrames.CurrentSpellSet) then
            print ("Keeping the current spell set.")
            return
        else
            print ("Attempting to use spell set for role 1.")
            currentSpellSet, currentSpellSetName = FindSpellForSoul(1)
            if not currentSpellSet then
                print ("unable to locate spellset for role 1, something is wrong with your saved variables or spell configuration.")
                return
            end
            print ("Using spell set from role 1.")
        end
	end

	if MereHealingFrames.CurrentSpellSet ~= currentSpellSet then
		MereHealingFrames.Debug(1, "Using SpellSet %s", currentSpellSetName)
		MereHealingFrames.CurrentSpellSet = currentSpellSet
		MereHealingFrames.Spells.UpdateCurrentSpells()
	else
		MereHealingFrames.Debug(1, "SpellSet unchanged, still using %s", currentSpellSetName)
	end
end

function MereHealingFrames.Spells.UpdateCurrentSpells()
	for layoutName, layout in pairs(MereHealingFrames.Layouts) do
		MereHealingFrames.Debug(4, "Updating spells in layout: %s", layoutName)
		layout:UpdateSpells()
	end
end

function MereHealingFrames.Spells.createDefaultSoulSpec(defaultValue)
	local soulSpec = {}

	if defaultValue == nil then
		defaultValue = true
	end
	for i=1, MereHealingFrames.StaticGlobals.numberOfSoulSpecs do
		soulSpec[i] = defaultValue
	end

	return soulSpec
end

function MereHealingFrames.Spells.RenameSoulSpec(originalName, newName)
	if not MereHealingFrames.SpellSets[originalName] or MereHealingFrames.SpellSets[newName] then
		return false
	end

	local spellSet = MereHealingFrames.SpellSets[originalName]
	MereHealingFrames.SpellSets[originalName] = nil
	MereHealingFrames.SpellSets[newName] = spellSet

	return true
end

function MereHealingFrames.Spells.DeleteSpellSet(SpellSetName)
	local spellSet = MereHealingFrames.SpellSets[SpellSetName]
	if not spellSet then
		return false
	end

	local availableSpecs =  MereHealingFrames.Config.UI.CountAvailableSpecs()
	local maxSpecs = math.min(availableSpecs, MereHealingFrames.StaticGlobals.numberOfSoulSpecs)
	for i=1, maxSpecs do
		if spellSet.SoulSpecs[i] then
			return false
		end
	end

	MereHealingFrames.SpellSets[SpellSetName] = nil
	return true
end

function MereHealingFrames.Spells.SpellSetIsAssigned(SpellSetName)
	local spellSet = MereHealingFrames.SpellSets[SpellSetName]
	if not spellSet then
		return false
	end

	for i=1, MereHealingFrames.StaticGlobals.numberOfSoulSpecs do
		if spellSet.SoulSpecs[i] then
			return true
		end
	end
	return false
end

function MereHealingFrames.Spells.ClearSoulSpec(soulSpec)
	for setName, spellSet in pairs(MereHealingFrames.SpellSets) do
		if not spellSet.SoulSpecs then
			spellSet.SoulSpecs = MereHealingFrames.Spells.createDefaultSoulSpec()
		end
		spellSet.SoulSpecs[soulSpec] = false
	end
end

function MereHealingFrames.Spells.CreateEmptySpells()
	MereHealingFrames.SpellSets.DefaultSpellSet = {
		SoulSpecs = MereHealingFrames.Spells.createDefaultSoulSpec()
		}
	MereHealingFrames.CurrentSpellSet = MereHealingFrames.SpellSets.DefaultSpellSet
end

function MereHealingFrames.Spells.CreateNewSpellSet(spellSetName)
	local spellSet = {
		SoulSpecs = MereHealingFrames.Spells.createDefaultSoulSpec(false)
		}

	MereHealingFrames.SpellSets[spellSetName] = spellSet
	return spellSet
end

local ValidButtons = { 	LeftClick = true,
						RightClick = true,
						MiddleClick = true,
						Mouse4Click = true,
						Mouse5Click = true,
						WheelForward = true,
						WheelBack = true,
					}

local ValidModifiers = {
	ctrl = true,
	shift = true,
	alt = true,
	none = true
	}

function MereHealingFrames.Spells.UpdateSpell(spellSetName, button, modifier, spell, target, custom)
	local spellSet = MereHealingFrames.CurrentSpellSet

	if spellSetName then
		spellSet = MereHealingFrames.SpellSets[spellSetName]
		if not spellSet then
			return false
		end
	end

	if not ValidButtons[button] or not ValidModifiers[modifier] then
		MereHealingFrames.Debug(4, "Invalid button %s or modifier %s", button or "no button", modifier or "none")
		return false
	end

	if not spellSet[button] then
		spellSet[button] = {}
	end

	(spellSet[button])[modifier or "none"] = { spell = spell, target = target, custom = custom }
	MereHealingFrames.Spells.RefreshUI()
	return true
end

function MereHealingFrames.Spells.ClearSpell(spellSetName, button, modifier)
	local spellSet = MereHealingFrames.CurrentSpellSet

	if spellSetName then
		spellSet = MereHealingFrames.SpellSets[spellSetName]
		if not spellSet then
			return false
		end
	end

	if not ValidButtons[button] or not ValidModifiers[modifier] then
		MereHealingFrames.Debug(4, "Invalid button %s or modifier %s", button or "no button", modifier or "none")
		return false
	end

	if not spellSet[button] then
		spellSet[button] = {}
	end

	(spellSet[button])[modifier or "none"] = nil
	MereHealingFrames.Spells.RefreshUI()
	return true
end

function MereHealingFrames.Spells.ResetSpells(spellSetName)
	local spellSet = MereHealingFrames.CurrentSpellSet

	if spellSetName then
		spellSet = MereHealingFrames.SpellSets[spellSetName]
		if not spellSet then
			return false
		end
	end

	for buttonName, value in pairs(ValidButtons) do
		spellSet[buttonName] = nil
	end
	MereHealingFrames.Spells.RefreshUI()
	return true
end

function MereHealingFrames.Spells.RefreshUI()
	MereHealingFrames.Config.window:RefreshSpells()
end

-- TODO, might be able to tabulize and loop this function...
function MereHealingFrames.Spells.CreateCastMacros(casts, unitId)
	if not casts then return nil end

	local castMacro = "/suppressmacrofailures\n"
	if (casts["ctrl"]) then
		castMacro = castMacro .. MereHealingFrames.Spells.CreateCastMacro(casts["ctrl"], unitId, "[ctrl]")
	end

	if (casts["alt"]) then
		castMacro = castMacro .. MereHealingFrames.Spells.CreateCastMacro(casts["alt"], unitId, "[alt]")
	end

	if (casts["shift"]) then
		castMacro = castMacro .. MereHealingFrames.Spells.CreateCastMacro(casts["shift"], unitId, "[shift]")
	end

	if (casts["none"]) then
		castMacro = castMacro .. MereHealingFrames.Spells.CreateCastMacro(casts["none"], unitId, "")
	end
	return castMacro
end

function MereHealingFrames.Spells.CreateCastMacro(cast, unitId, modifier)
	if cast.spell then
        local macrotext = ""
        for spellName, _ in string.gsplit(cast.spell, ",") do
            local trimmedSpellName = spellName:trim()
            if trimmedSpellName:lower() == "target" then
                macrotext = macrotext .. "/target " .. modifier .. " @" .. unitId .. "\n"
            elseif trimmedSpellName ~= "" then
		        macrotext = macrotext .. "/cast " .. modifier .." @" .. unitId .. " " .. trimmedSpellName .. "\n"
            end
        end
        return macrotext
	elseif cast.target then
		return "/target " .. modifier .. " @" .. unitId .. "\n"
	elseif cast.custom then
		print("Custom macro not supported yet")
	end
	return ""
end

function MereHealingFrames.Spells.printSpellSet(spellSet)
    for button, val in pairs(ValidButtons) do
        local buttonSet = spellSet[button]
        if (buttonSet) then
            local printedSomething = false
            for modifier, cast in pairs(buttonSet) do
                if cast then
                    if cast.spell then
                        print (button .. ": [" .. modifier .. "] " .. cast.spell)
                        printedSomething = true
                    elseif cast.target then
                        print (button .. ": [" .. modifier .. "] target")
                        printedSomething = true
                    elseif cast.custom then
                        print (button .. ": [" .. modifier .. "] custom: " .. cast.custom)
                        printedSomething = true
                    end
                end
            end
            if (not printedSomething) then
                print(button .. ": nothing configured");
            end
        else
            print(button .. ": nothing configured");
        end
   end
end

function MereHealingFrames.Spells.CreateMagicMere()
	MereHealingFrames.SpellSets = {}
	MereHealingFrames.SpellSets.DefaultSpellSet = {
		SoulSpecsFilter = nil,
		LeftClick = {
			ctrl = { spell="Healing Breath" },
			shift = nil,
			alt = nil,
			none = { spell="Healing Spray"},
			},
		RightClick = {
			ctrl = { spell = "Healing Grace"},
			shift = nil,
			alt = nil,
			none = { spell = "Restorative Flame"},
			},
		MiddleClick = {
			ctrl = nil,
			shift = { target = true },
			alt = nil,
			none = { spell = "Cauterize"},
			},
		Mouse4Click = {
			ctrl = nil,
			shift = nil,
			alt = nil,
			none = { spell = "Ward of the Ancestors"},
			},
		Mouse5Click = {
			ctrl = nil,
			shift = nil,
			alt = nil,
			none = { spell = "Searing Transfusion" },
			},
		WheelForward = {
			ctrl = nil,
			shift = nil,
			alt = nil,
			none = { spell = "Latent Blaze"},
			},
		WheelBack = {
			ctrl = nil,
			shift = nil,
			alt = nil,
			none = { spell = "Sterilize"},
			},
	}
	MereHealingFrames.CurrentSpellSet = MereHealingFrames.SpellSets.DefaultSpellSet
end