vanilla-wow-addons – Rev 1

Subversion Repositories:
Rev:
----------------------------------------------------------
----------------------------------------------------------
-- Simple Action Sets Beta 0.4                          --
--                                                      --
-- Allows all 120 action buttons to be saved to action  --
-- sets. Sets can then be swapped to on the fly.        --
--                                                      --
-- Thanks to Cide, Ts, and Gello for some excellent     --
-- mods to "borrow" from.                               --
----------------------------------------------------------
----------------------------------------------------------

SAS_POS = 270;
SAS_OFFSET = 0

SAS_POS_DEFAULT = 270;
SAS_OFFSET_DEFAULT = 0;

SAS_POS_TEMP = nil;
SAS_OFFSET_TEMP = nil;

--SAS_DEBUG = nil;

local PlrName;
local PlrClass; -- not used yet

-- Fix for barmods that badly hook PickupAction instead of doing it in external functions or xml
local barmods = { ctmod = {"CT_HotbarButtons_Locked"}, nurfed = {"NURFED_LOCKALL", 0} };

-- Path name for all icons in the game
local IconPath = "Interface\\Icons\\";

-- Table used to track what's on the cursor
SAS_SavedPickup = {}; -- name, rank, macro, link, texture


------------------------------
-- SAS Main Frame functions --
------------------------------

function SASMain_UpdateDisplay()
        local tab = SASMain.selectedTab;
        if ( tab == 1 ) then
                SASActions:SetHeight(280);
                SASMainBottomDivider:SetPoint("TOPLEFT", SASMainTopDivider, "BOTTOMLEFT", 0, -270);
                SASSets:Show()
                SASOptions:Hide();
                SASHelp:Hide();
        elseif ( tab == 2 ) then
                SASActions:SetHeight(185);
                SASMainBottomDivider:SetPoint("TOPLEFT", SASMainTopDivider, "BOTTOMLEFT", 0, -175);
                SASSets:Hide();
                SASOptions:Show();
                SASHelp:Hide();
        elseif ( tab == 3 ) then
                SASActions:SetHeight(185);
                SASMainBottomDivider:SetPoint("TOPLEFT", SASMainTopDivider, "BOTTOMLEFT", 0, -175);
                SASSets:Hide();
                SASOptions:Hide();
                SASHelp:Show();
        end
end

function SASMain_Toggle()
        if ( SASMain:IsVisible() ) then
                HideUIPanel(SASMain);
        else
                ShowUIPanel(SASMain);
        end
end


-----------------------------
-- Actions Frame functions --
-----------------------------
function SASActions_OnShow()
        SASActions_Load( SAS_GetCurrentSet() );
end

function SASActions_OnHide()
        SAS_Temp = nil;
end

function SASActions_Load( set, plr )
        SAS_Temp = {};
        
        if ( not plr ) then
                plr = PlrName;
        end
        
        if ( not set or set == SAS_TEXT_CURRENT ) then
                set = nil;
                SAS_Temp = SAS_IterateActions();
                SASDebug( "Loading current actions" );
                UIDropDownMenu_Initialize(SASActionSetsDropDown, SASActions_DropDown_Initialize);
                UIDropDownMenu_SetSelectedID( SASActionSetsDropDown, 0 );
                SASActionSetsDropDownButton:Disable();
                SASActionSetsDropDownText:SetText( "|c00999999"..SAS_TEXT_CURRENT );
                SASActionsDelete:Disable();
        elseif ( plr ~= PlrName ) then
                SAS_Temp = SAS_CopyTable(SAS_Saved[plr]["s"][set]);
                SASDebug( "Loading set "..set.." from "..plr );
                UIDropDownMenu_Initialize(SASActionSetsDropDown, SASActions_DropDown_Initialize);
                UIDropDownMenu_SetSelectedID( SASActionSetsDropDown, 0 );
                SASActionSetsDropDownText:SetText( "|c00999999"..SAS_TEXT_CURRENT );
                SASActionsDelete:Disable();
        else
                SAS_Temp = SAS_CopyTable(SAS_Saved[plr]["s"][set]);
                SASDebug( "Loading set "..set );
                UIDropDownMenu_Initialize(SASActionSetsDropDown, SASActions_DropDown_Initialize);
                UIDropDownMenu_SetSelectedName( SASActionSetsDropDown, set );
                SASActionsDelete:Enable();
        end
        
        for k, v in SAS_Saved[PlrName]["s"] do
                SASActionSetsDropDownButton:Enable();
                break;
        end
        
        SASActions_Display();
        SASActionsSave:Disable();
        --SAS_CurrentSet = set;
        TitanPanelSAS_Update();
end

function SASActions_Bar_CheckAll()
        -- Check all bars enabled or disabled
        local check = this:GetChecked();
        for i = 0, 9 do
                getglobal( "SASActionBar"..i.."Enable"):SetChecked(check);
                --SASActions_Bar_Toggle( i, check );
                if ( SAS_Temp[i] ) then
                        if ( check ) then
                                SAS_Temp[i][0] = nil;
                        else
                                SAS_Temp[i][0] = 1;
                        end
                end
        end
        SASActions_Display();
end

function SASActions_BarEnable_OnClick( bar, enable )
        -- Enable or disable a bar
        if ( SAS_Temp[bar] ) then
                if ( enable ) then
                        SAS_Temp[bar][0] = nil;
                else
                        SAS_Temp[bar][0] = 1;
                end
        end
        SASActions_UpdateBar( bar )
        SASActionsCheckAll:SetChecked(1);
        
        SASActions_SaveEnable();
end

function SASActionBarButton_OnClick()
        local bar = this:GetParent():GetID();
        local enable = SAS_BarEnabled(bar)
        local LocalSavedBar = SAS_CopyTable(SAS_Temp[bar]);
        local returnbar = SAS_DraggingBar;
        
        if ( SASFakeDragFrame.Bar and not IsShiftKeyDown() and not IsControlKeyDown() ) then
                SAS_Temp[bar] = SASFakeDrag_Drop(1);
                --SAS_Temp[bar]["enable"] = enable;
                if ( returnbar ) then
                        SAS_DraggingBar = nil;
                        --enable = SAS_Temp[returnbar]["enable"];
                        SAS_Temp[returnbar] = SAS_CopyTable(LocalSavedBar);
                        --SAS_Temp[returnbar]["enable"] = enable;
                        SASActions_UpdateBar(returnbar);
                end
                LocalSavedBar = nil;
        elseif ( IsControlKeyDown() and not IsShiftKeyDown() ) then
                SAS_Temp[bar] = {};
                --SAS_Temp[bar]["enable"] = enable;
        end
        
        if ( SAS_BarHasActions(bar) and LocalSavedBar ) then
                SASFakeDrag_PickupBar(LocalSavedBar);
                if ( not IsShiftKeyDown() ) then
                        SAS_DraggingBar = bar;
                end
        end
        SASActions_UpdateBar(bar);
        SASActions_SaveEnable();
end

function SASActionBarButton_OnReceiveDrag()
        SASActionBarButton_OnClick();
end

function SASActionBarButton_OnDragStart()
        local bar = this:GetParent():GetID();
        if ( SAS_BarHasActions(bar) ) then
                SASDebug("Picking up bar "..bar );
                SASFakeDrag_PickupBar( SAS_Temp[bar] );
                SAS_DraggingBar = bar;
                SASActions_UpdateBar(bar);
        else
                SASFakeDrag_PickupBar();
                SAS_DraggingBar = nil;
        end
end

function SASActionBarButton_OnEnter()
        this:SetScript("OnUpdate", SASActionBarButton_OnUpdate);
        GameTooltip:SetOwner(this, "ANCHOR_RIGHT");
        GameTooltip:SetText( getglobal("SAS_TEXT_BARS_"..this:GetParent():GetID()) );
        GameTooltip:Show();
end

function SASActionBarButton_OnLeave()
        this:SetScript("OnUpdate", nil);
        
        for i=1, 12 do
                local button = getglobal( this:GetParent():GetName().."Action"..i ):GetName();
                getglobal( button.."Delete" ):Hide();
                getglobal( button.."Copy" ):Hide();
        end
        
        GameTooltip:Hide();
end

function SASActionBarButton_OnUpdate()
        if ( not SAS_Temp ) then return; end
        
        local BarFrame = this:GetParent();
        local barName = BarFrame:GetName();
        
        for i=1, 12 do
                local button = getglobal( barName.."Action"..i ):GetName();
                if ( IsControlKeyDown() and not IsShiftKeyDown() and getglobal( button.."Icon" ):IsVisible() ) then
                        getglobal( button.."Delete" ):Show();
                        getglobal( button.."Copy" ):Hide();
                elseif ( IsShiftKeyDown() and not IsControlKeyDown() and SAS_BarHasActions(BarFrame:GetID()) ) then
                        getglobal( button.."Copy" ):Show();
                        getglobal( button.."Delete" ):Hide();
                else
                        getglobal( button.."Delete" ):Hide();
                        getglobal( button.."Copy" ):Hide();
                end
        end
end

function SASActionBarButton_OnDragStop()
        SASFakeDrag_Drop();
end

function SASActions_DropDown_OnLoad()
        UIDropDownMenu_Initialize(this, SASActions_DropDown_Initialize);
        UIDropDownMenu_SetWidth(135);
        UIDropDownMenu_SetButtonWidth(24);
        UIDropDownMenu_JustifyText("LEFT", SASActionSetsDropDown);
        if ( SAS_GetCurrentSet() ) then
                UIDropDownMenu_SetSelectedName(SASActionSetsDropDown, SAS_GetCurrentSet());
        else
                UIDropDownMenu_SetText( "|c00999999"..SAS_TEXT_CURRENT, SASActionSetsDropDown );
        end
end

function SASActions_DropDown_Initialize()
        if ( not SAS_Saved or not SAS_Saved[PlrName] or not SAS_Saved[PlrName]["s"] ) then return; end
        local list = {};
        for k, v in SAS_Saved[PlrName].s do
                tinsert(list, k);
        end
        table.sort(list);
        local info;
        for k, v in list do
                info = {};
                info.text = v;
                info.value = v;
                info.justifyH = "LEFT";
                info.func = SASActions_DropDown_OnClick;
                UIDropDownMenu_AddButton(info);
        end
end

function SASActions_DropDown_OnClick()
        UIDropDownMenu_SetSelectedID( SASActionSetsDropDown, this:GetID() );
        SASActions_Load(this:GetText());
end

function SASActions_Display()
        -- Update the display of all bars.
        if ( SAS_Temp ) then
                for i=0, 9 do
                        SASActions_UpdateBar( i );
                end
        end
        SASActions_SaveEnable();
end

function SASActions_UpdateBar( bar )
        -- Update the display of a bar
        local BarFrame = getglobal( "SASActionBar"..bar );
        if ( SAS_Temp[bar] ) then
                getglobal( BarFrame:GetName().."Enable"):SetChecked(not SAS_Temp[bar][0]);
        end
        if ( bar ) then
                for i=1, 12 do
                        SASActions_UpdateAction( bar, i );
                end
        end
        
        if ( SAS_DraggingBar == bar and SASFakeDragFrame:IsVisible() ) then
                BarFrame:SetAlpha(0.5);
        else
                BarFrame:SetAlpha(1.0);
        end
end

function SAS_BarEnabled( bar, set )
        if ( not set ) then set = SAS_Temp; end
        if ( set and set[bar] ) then
                return not set[bar][0];
        end
end

function SASActions_UpdateAction(bar, id)
        -- Update the display of an action.
        local button = getglobal( "SASActionBar"..bar.."Action"..id ):GetName();
        local icon = getglobal( button.."Icon" );
        local buttonName = getglobal( button.."Name" );
        local normalTexture = getglobal( button.."NormalTexture" );
        local border = getglobal( button.."Border" );
        local hotkey = getglobal( button.."HotKey" );
        local enable = SAS_BarEnabled(bar);
        
        if ( SAS_Saved[PlrName]["NoEmptyButtons"] and (not SAS_Temp[bar] or not SAS_Temp[bar][id]) ) then
                enable = nil;
        elseif ( not SAS_Saved[PlrName]["EmptyBars"] and not SAS_BarHasActions(bar) ) then
                enable = nil;
        end
        SetDesaturation( getglobal( "SASActionBar"..bar.."Action"..id.."Icon" ), not enable );
        border:Hide();
        normalTexture:SetVertexColor(1.0, 1.0, 1.0, 1.0);
        
        if ( enable ) then
                getglobal(button):SetAlpha(1.0);
        else
                getglobal(button):SetAlpha(0.5);
        end

        hotkey:SetTextColor(0.25,0.25,0.25);

        if ( not SAS_Temp ) then
                getglobal( button ):Disable();
        else
                getglobal( button ):Enable();
                
                icon:Hide()
                buttonName:Hide();
                icon:SetVertexColor(1.0, 1.0, 1.0);

                if ( SAS_Temp[bar] and SAS_Temp[bar][id] ) then
                        local name, texture, rank, link, macro = SAS_ParseActionInfo( SAS_Temp[bar][id] ); --SAS_Temp[bar][id][1], SAS_Temp[bar][id][2], SAS_Temp[bar][id][3], SAS_Temp[bar][id][4], SAS_Temp[bar][id][5];
                        texture = SAS_FullPath(texture);
                        icon:SetTexture( texture );
                        icon:Show();
                        normalTexture:SetTexture("Interface\\Buttons\\UI-Quickslot2");
                        hotkey:SetTextColor(0.6,0.6,0.6);

                        if ( macro ) then
                                buttonName:SetText( name );
                                buttonName:Show();
                                buttonName:SetTextColor(1.0, 1.0, 1.0);
                                if ( not SAS_FindMacro( name, texture, macro ) ) then
                                        border:SetVertexColor(1.0, 0.0, 0.0, 0.35);
                                        buttonName:SetTextColor(0.4, 0.4, 0.4);
                                        border:Show();
                                        normalTexture:SetVertexColor(0.9, 0.0, 0.0, 1.0);
                                        icon:SetVertexColor(0.4, 0.4, 0.4);
                                end
                        elseif ( link ) then
                                border:SetVertexColor(0, 1.0, 0, 0.35);
                                border:Show();
                                local itemLink;
                                if ( link == "?" or link == "1" ) then
                                        itemLink = SAS_CheckItem( name, bar*12+id, SASActions_GetLoaded() );
                                else
                                        itemLink = SAS_FindItem( link );
                                end
                                if ( not itemLink or itemLink == "?" ) then
                                        border:SetVertexColor(1.0, 0.0, 0.0, 0.35);
                                        normalTexture:SetVertexColor(0.9, 0.0, 0.0, 1.0);
                                        icon:SetVertexColor(0.4, 0.4, 0.4);
                                elseif ( link == "?" ) then
                                        SAS_Temp[bar][id] = SAS_IncActionInfo( SAS_Temp[bar][id], itemLink, 4 );
                                end
                        else                                    
                                local spellNum, highest = SAS_FindSpell( name, rank );
                                if ( not spellNum ) then
                                        if ( highest ) then
                                                border:SetVertexColor(0.0, 0.0, 1.0, 0.7);
                                        else
                                                icon:SetVertexColor(0.4, 0.4, 0.4);
                                                border:SetVertexColor(1.0, 0.0, 0.0, 0.35);
                                        end
                                        border:Show();
                                elseif ( not rank ) then
                                        local checktexture = GetSpellTexture( spellNum, BOOKTYPE_SPELL );
                                        if ( texture ~= checktexture ) then
                                                icon:SetTexture( checktexture );
                                                local set = SASActions_GetLoaded();
                                                if ( set ) then
                                                        SAS_Temp[bar][id] = SAS_IncActionInfo( SAS_Temp[bar][id], checktexture, 2 );
                                                        SAS_Saved[PlrName]["s"][set][bar][id] = SAS_IncActionInfo( SAS_Saved[PlrName]["s"][set][bar][id], checktexture, 2 );
                                                end
                                        end
                                end
                        end
                elseif ( SAS_Temp[bar] ) then
                        if ( enable ) then
                                normalTexture:SetTexture("Interface\\Buttons\\UI-Quickslot");
                        else
                                normalTexture:SetTexture("Interface\\Buttons\\UI-Quickslot2");
                        end
                end
        end
end

function SASActions_SaveNew( set )
        SASSaveMenuNameEB:SetText("");
        ShowUIPanel(SASSaveMenu);
        if ( set ) then
                SASSaveMenuNameEB:SetText( set );
                SASSaveMenu_Save( set );
        end
end

function SASActions_ClearTemp()
        -- Clear the temp set
        for i=0, 9 do
                SAS_Temp[i] = {};
        end
        SASActions_Display();
end

function SASActions_LoadCurrent()
        if ( SASActionsSave:GetButtonState() == "DISABLED" ) then
                SASActions_Load();
        else
                SAS_Warning("UNSAVED_LOAD", SASActions_Load);
        end
end

function SASActions_SwapSet()
        if ( SASActionsSave:GetButtonState() == "NORMAL" ) then
                SAS_Warning("SWAPPINGSAVE", SASActions_SwapSave, SASActions_GetLoaded());
        else
                SAS_Warning("SWAPPING", SAS_SwapSet, SASActions_GetLoaded());
        end
end

function SASActions_SwapSave( set )
        SAS_SaveSet( set );
        SAS_SwapSet( set );
end

function SASActions_Delete()
        SAS_Warning("DELETE", SAS_Delete, SASActions_GetLoaded());
end

function SASActions_Save()
        SAS_Warning("SAVE", SAS_SaveSet, SASActions_GetLoaded());
end

function SASActions_SaveEnable()
        local set = SASActions_GetLoaded();
        if ( set and SAS_CompareSet(SAS_Temp, SAS_Saved[PlrName]["s"][set], 2) ) then
                SASActionsSave:Enable();
        else
                SASActionsSave:Disable();
        end
end

function SASActions_Cancel()
        if ( SASActionsSave:GetButtonState() == "DISABLED" ) then
                HideUIPanel(this:GetParent());
        else
                SAS_Warning("UNSAVED_CANCEL", SASMain_Toggle);
        end
end

function SASActions_GetLoaded()
        local set = UIDropDownMenu_GetSelectedName( SASActionSetsDropDown );
        if ( set ~= SAS_TEXT_CURRENT ) then
                return set;
        end
end

function SASActionsSave_Enable()
        SASActionsSaveLeft:SetTexture("Interface\\Buttons\\UI-Panel-Button-Up");
        SASActionsSaveMiddle:SetTexture("Interface\\Buttons\\UI-Panel-Button-Up");
        SASActionsSaveRight:SetTexture("Interface\\Buttons\\UI-Panel-Button-Up");
        SASActionsSave:oldEnable();
        SASActionsSave:EnableMouse(1);
end

function SASActionsSave_Disable()
        SASActionsSaveLeft:SetTexture("Interface\\Buttons\\UI-Panel-Button-Disabled");
        SASActionsSaveMiddle:SetTexture("Interface\\Buttons\\UI-Panel-Button-Disabled");
        SASActionsSaveRight:SetTexture("Interface\\Buttons\\UI-Panel-Button-Disabled");
        SASActionsSave:oldDisable();
        SASActionsSave:EnableMouse();
end

function SASSets_Character_DropDown_OnLoad()
        UIDropDownMenu_Initialize(this, SASSets_Character_DropDown_Initialize);
        UIDropDownMenu_SetWidth(160);
        UIDropDownMenu_SetButtonWidth(24);
        UIDropDownMenu_JustifyText("LEFT", SASSets_Character_DropDown);
        UIDropDownMenu_SetSelectedID( SASSets_Character_DropDown, 1 );
end

function SASSets_Character_DropDown_Initialize()
        local info;
        local list = {};
        for k, v in SAS_Saved do
                if ( k ~= "debug" and k ~= "BackUp" and k ~= PlrName and v.s ) then
                        for j, z in v.s do
                                tinsert(list,k);
                                break;
                        end
                end
        end
        table.sort(list);
        if ( SAS_Saved["BackUp"] ) then
                tinsert(list,"BackUp");
        end
        for i=1, getn(list) do
                info = {};
                info.text = list[i];
                info.value = list[i];
                info.justifyH = "LEFT";
                info.func = SASSets_Character_DropDown_OnClick;
                UIDropDownMenu_AddButton(info);
        end
end

function SASSets_Character_DropDown_OnClick()
        UIDropDownMenu_SetSelectedName( SASSets_Character_DropDown, this:GetText() );
        UIDropDownMenu_Initialize(SASSets_CharacterSets_DropDown, SASSets_CharacterSets_DropDown_Initialize);
        UIDropDownMenu_SetSelectedID( SASSets_CharacterSets_DropDown, 1 );
end

function SASSets_CharacterSets_DropDown_OnLoad()
        UIDropDownMenu_Initialize(this, SASSets_CharacterSets_DropDown_Initialize);
        UIDropDownMenu_SetWidth(160);
        UIDropDownMenu_SetButtonWidth(24);
        UIDropDownMenu_JustifyText("LEFT", SASSets_CharacterSets_DropDown);
        UIDropDownMenu_SetSelectedID( SASSets_CharacterSets_DropDown, 1 );
end

function SASSets_CharacterSets_DropDown_Initialize()
        local info;
        local list = {};
        local char = SASSets_Character_DropDownText:GetText();
        if ( SAS_Saved[char] and SAS_Saved[char]["s"] ) then
                for k, v in SAS_Saved[char]["s"] do
                        tinsert(list,k);
                end
        end
        table.sort(list);
        for i=1, getn(list) do
                info = {};
                info.text = list[i];
                info.value = list[i];
                info.justifyH = "LEFT";
                info.func = SASSets_CharacterSets_DropDown_OnClick;
                UIDropDownMenu_AddButton(info);
        end
end

function SASSets_CharacterSets_DropDown_OnClick()
        UIDropDownMenu_SetSelectedID( SASSets_CharacterSets_DropDown, this:GetID() );
end

function SASActions_LoadOtherSet()
        local char = SASSets_Character_DropDownText:GetText();
        local set = SASSets_CharacterSets_DropDownText:GetText();
        SASActions_Load( set, char );
end

-------------------------------
-- SASActionButton functions --
-------------------------------
function SASActionButton_OnClick( button )
        -- Pick up action, and replace with held action (if there is one)
        local bar = this:GetParent():GetID();
        local id = this:GetID();
        --local i = id + bar * 12;
        local LocalSavedAction;
        if ( button == "RightButton" and SASFakeDragFrame.Action ) then
                SASFakeDrag_Drop(1);
        elseif ( IsShiftKeyDown() and not IsControlKeyDown() ) then
                LocalSavedAction = SAS_Temp[bar][id];
                SAS_ClearCursor();
        else
                if ( SAS_IsValidAction ) then
                        -- Cursor has an item / action / macro that can be placed on the action bar
                        SASDebug("SASActionButton_OnClick getting action "..SAS_ParseActionInfo(SAS_SavedPickup, 1).." from cursor");
                        if ( SAS_ParseActionInfo(SAS_SavedPickup, 6) ) then
                                -- Spell is passive, don't add to set
                                UIErrorsFrame:AddMessage(ERR_PASSIVE_ABILITY, 1.0, 0.1, 0.1, 1.0, UIERRORS_HOLD_TIME);
                        else
                                if ( SAS_Temp[bar] and not SAS_Temp[bar][id] == SAS_SavedPickup ) then
                                        LocalSavedAction = SAS_Temp[bar][id];
                                end
                                SAS_Temp[bar][id] = SAS_SavedPickup;
                                SASActions_UpdateAction( bar, id );

                                if ( SAS_ReturnAction ) then
                                        PlaceAction( SAS_ReturnAction );
                                else
                                        SAS_ClearCursor();
                                end
                        end
                elseif ( SASFakeDragFrame.Action ) then
                        -- Cursor fake drag is holding an action
                        SASDebug("SASActionButton_OnClick getting fake drag action "..SAS_ParseActionInfo(SASFakeDragFrame.Action, 1));
                        if ( SAS_Temp[bar] and SAS_Temp[bar][id] ) then
                                LocalSavedAction = SAS_CopyTable(SAS_Temp[bar][id]);
                        end
                        SAS_Temp[bar][id] = SASFakeDrag_Drop(1)
                        SASActions_UpdateAction( bar, id );
                elseif ( SAS_Temp[bar][id] ) then
                        SASDebug("SASActionButton_OnClick putting action "..SAS_ParseActionInfo(SAS_Temp[bar][id], 1).." on fake drag");
                        -- This slot already has an action, pick it up
                        LocalSavedAction = SAS_Temp[bar][id];
                        SAS_Temp[bar][id] = nil;
                        SASActions_UpdateAction( bar, id );
                        if ( IsControlKeyDown() and not IsShiftKeyDown() ) then
                                LocalSavedAction = nil;
                        end
                        getglobal( this:GetName().."Delete" ):Hide();
                        getglobal( this:GetName().."Copy" ):Hide();
                end
        end

        if ( LocalSavedAction ) then
                SASFakeDrag_PickupAction( LocalSavedAction );
        end
        SASActions_SaveEnable();
end

function SASActionButton_OnDragStart()
        local bar = this:GetParent():GetID();
        local id = this:GetID();
        SASFakeDrag_PickupAction( SAS_Temp[bar][id] );
        if ( not IsShiftKeyDown() ) then
                SAS_Temp[bar][id] = nil;
                SASActions_UpdateAction( bar, id );
                SASActions_SaveEnable();
        end
end

function SASActionButton_OnDragStop()
        SASFakeDrag_Drop();
end

function SASActionButton_OnReceiveDrag()
        SASDebug("Drag Receive");
        SASActionButton_OnClick();
end     

function SASActionButton_OnEnter()
        -- Make Tooltip to display for this button
        this:SetScript("OnUpdate", SASActionButton_OnUpdate); --this.hasfocus = 1;
        
        local bar = this:GetParent():GetID();
        local id = this:GetID();
        local enabled = getglobal( "SASActionBar"..bar.."Enable" ):GetChecked();

        if ( not enabled ) then
                SetDesaturation( getglobal(this:GetName().."Icon"), 0 );
                this:SetAlpha(1.0);
                this:SetNormalTexture("Interface\\Buttons\\UI-Quickslot");
        end

        if ( getglobal( this:GetName().."Icon" ):IsVisible() and SAS_Temp ) then
                GameTooltip:SetOwner(this, "ANCHOR_RIGHT");             
                SAS_SetTooltip( bar, id );
        end
end

function SASActionButton_OnLeave()
        -- Hide the tooltip, reset desaturated on disabled bars
        local enabled = getglobal( "SASActionBar"..this:GetParent():GetID().."Enable" ):GetChecked();
        local bar = this:GetParent():GetID();
        local id = this:GetID();
        SASActions_UpdateAction( bar, id );
        this:SetScript("OnUpdate", nil); --this.hasfocus = nil;
        getglobal( this:GetName().."Delete" ):Hide();
        getglobal( this:GetName().."Copy" ):Hide();
        GameTooltip:Hide();
end

function SASActionButton_OnUpdate()
        if ( not getglobal( this:GetName().."Icon" ):IsVisible() or not SAS_Temp ) then return; end
        
        if ( IsControlKeyDown() and not IsShiftKeyDown() ) then
                getglobal( this:GetName().."Delete" ):Show();
        else
                getglobal( this:GetName().."Delete" ):Hide();
        end
        if ( IsShiftKeyDown() and not IsControlKeyDown() ) then
                getglobal( this:GetName().."Copy" ):Show();
        else
                getglobal( this:GetName().."Copy" ):Hide();
        end
end


----------------------------
-- Options Menu Functions --
----------------------------
function SASOptions_OnShow()
        SASOptions_Update();
        SASOptionsMinimapShow:SetChecked( not SAS_Saved[PlrName]["HideMinimapButton"] );
        SASOptionsMinimapShowText:SetText( SAS_TEXT_OPTIONS_MINIMAP_SHOW );
        SASOptionsMinimapDrag:SetChecked( SAS_Saved[PlrName]["LockMinimapButton"] );
        SASOptionsMinimapDragText:SetText( SAS_TEXT_OPTIONS_MINIMAP_DRAG );
        SASOptionsMinimapPositionUndo:Disable();
        SASOptionsGeneralWarnings:SetChecked( not SAS_Saved[PlrName]["NoUIWarnings"] );
        SASOptionsGeneralWarningsText:SetText( SAS_TEXT_OPTIONS_GENERAL_WARNINGS );
        SASOptionsGeneralWarnings.tooltipText = SAS_TEXT_OPTIONS_GENERAL_WARNINGS_TOOLTIP;
        SASOptionsGeneralEmptyBars:SetChecked( not SAS_Saved[PlrName]["EmptyBars"] );
        SASOptionsGeneralEmptyBarsText:SetText( SAS_TEXT_OPTIONS_GENERAL_EMPTYBARS );
        SASOptionsGeneralEmptyBars.tooltipText = SAS_TEXT_OPTIONS_GENERAL_EMPTYBARS_TOOLTIP;
        SASOptionsGeneralEmptyButtons:SetChecked( SAS_Saved[PlrName]["NoEmptyButtons"] );
        SASOptionsGeneralEmptyButtonsText:SetText( SAS_TEXT_OPTIONS_GENERAL_EMPTYBUTTONS );
        SASOptionsGeneralEmptyButtons.tooltipText = SAS_TEXT_OPTIONS_GENERAL_EMPTYBUTTONS_TOOLTIP;
        SASOptionsGeneralFakeItemTooltips:SetChecked( not SAS_Saved[PlrName]["HideFakeItemTooltips"] );
        SASOptionsGeneralFakeItemTooltipsText:SetText( SAS_TEXT_OPTIONS_GENERAL_FAKEITEMTOOLTIPS );
        SASOptionsGeneralFakeItemTooltips.tooltipText = SAS_TEXT_OPTIONS_GENERAL_FAKEITEMTOOLTIPS_TOOLTIP;
        SASOptionsGeneralAutoRestore:SetChecked( not SAS_Saved[PlrName]["AutoRestore"] );
        SASOptionsGeneralAutoRestoreText:SetText( SAS_TEXT_OPTIONS_GENERAL_AUTORESTORE );
        SASOptionsGeneralAutoRestore.tooltipText = SAS_TEXT_OPTIONS_GENERAL_AUTORESTORE_TOOLTIP;
        SASOptionsGeneralAutoRestoreWarning:SetChecked( not SAS_Saved[PlrName]["NoAutoRestoreWarnings"] );
        SASOptionsGeneralAutoRestoreWarningText:SetText( SAS_TEXT_OPTIONS_GENERAL_AUTORESTOREWARN );
        SASOptionsGeneralAutoRestoreWarning.tooltipText = SAS_TEXT_OPTIONS_GENERAL_AUTORESTOREWARN_TOOLTIP;
        SAS_POS_TEMP = SAS_POS;
        SAS_OFFSET_TEMP = SAS_OFFSET;
end

function SASOptions_General_Warnings()
        SAS_Saved[PlrName]["NoUIWarnings"] = not this:GetChecked();
end

function SASOptions_General_EmptyBars()
        SAS_Saved[PlrName]["EmptyBars"] = not this:GetChecked();
        SASActions_Display();
end

function SASOptions_General_EmptyButtons()
        SAS_Saved[PlrName]["NoEmptyButtons"] = this:GetChecked();
        SASActions_Display();   
end

function SASOptions_General_FakeItemTooltips()
        SAS_Saved[PlrName]["HideFakeItemTooltips"] = not this:GetChecked();
end

function SASOptions_General_AutoRestore()
        SAS_Saved[PlrName]["AutoRestore"] = not this:GetChecked();
end

function SASOptions_General_AutoRestoreWarnings()
        SAS_Saved[PlrName]["NoAutoRestoreWarnings"] = not this:GetChecked();
end

function SASOptions_Minimap_Show()
        SAS_Saved[PlrName]["HideMinimapButton"] = not this:GetChecked();
        if ( this:GetChecked() ) then
                SASMinimapFrame:Show();
        else
                SASMinimapFrame:Hide();
        end
end

function SASOptions_Minimap_Drag()
        SAS_Saved[PlrName]["LockMinimapButton"] = this:GetChecked();
end

function SASOptions_Minimap_Defaults()
        SAS_POS = SAS_POS_DEFAULT;
        SAS_OFFSET = SAS_POS_DEFAULT;
        SASMinimap_PosUpdate();
end

function SASOptions_Minimap_Undo()
        SAS_POS = SAS_POS_TEMP;
        SAS_OFFSET = SAS_OFFSET_TEMP;
        SASMinimap_PosUpdate();
        SASOptions_Update();
end

function SASOptions_Update()
        if ( SAS_POS < 0 ) then SAS_POS = SAS_POS + 360; end
        SASButtonPos:SetValue(SAS_POS);
        SASButtonOffset:SetValue(SAS_OFFSET);
end


--------------------------------------
-- Warning and Save Frame Functions --
--------------------------------------
function SAS_Warning( type, func, value, force )
        if ( SAS_Saved[PlrName]["NoUIWarnings"] and ( not force or SAS_Saved[PlrName]["NoAutoRestoreWarnings"] ) ) then
                func(value);
        else
                if ( value ) then
                        SASWarningFrameText:SetText( string.gsub(getglobal("SAS_TEXT_WARNING_"..type), "%%s", value) );
                else
                        SASWarningFrameText:SetText( getglobal("SAS_TEXT_WARNING_"..type ) );
                end
                SASWarningFrame.func = func;
                SASWarningFrame.value = value
                ShowUIPanel(SASWarningFrame);
        end
end

function SASWarning_Okay()
        SASWarningFrame.func(SASWarningFrame.value)
        SASWarningFrame.func = nil;
        SASWarningFrame.value = nil;
        HideUIPanel(this:GetParent());
end

function SASSaveMenu_Save( set )
        SASSaveMenuHelp.warned = nil
        SASSaveMenuHelp:Hide();
        SAS_SaveSet( set );
        HideUIPanel( SASSaveMenu );
end


---------------------------------
-- Minimap Button functions --
---------------------------------
function SASMinimap_OnLoad()
        -- Load and initialize Simple Action Sets
        this:RegisterEvent("VARIABLES_LOADED");
        this:RegisterForClicks("LeftButtonUp", "RightButtonUp");
        this:RegisterForDrag("LeftButton", "RightButton");
        
        tinsert(UISpecialFrames,"SASMain");
        
        SlashCmdList["SAS"] = SAS_Console;
        SLASH_SAS1 = "/sas";
end

function SASMinimap_OnEvent()
        if( event == "VARIABLES_LOADED" ) then
                this:RegisterEvent("ACTIONBAR_SHOWGRID");
                this:RegisterEvent("ACTIONBAR_HIDEGRID");
                this:RegisterEvent("UNIT_INVENTORY_CHANGED");
                this:RegisterEvent("BAG_UPDATE");
                this:RegisterEvent("PLAYER_LOGOUT");
                
                SASMinimap_PosUpdate();
                
                PlrName = UnitName("player").." - "..GetCVar("realmName");
                
                SASFrame.PlrName = PlrName;
                
                PlrClass, PlrClass = UnitClass("player");
                
                if ( not SAS_Saved ) then
                        SAS_Saved = {};
                end
                if ( not SAS_Saved[PlrName] ) then
                        SAS_Saved[PlrName] = {};
                        SAS_Saved[PlrName]["s"] = {};
                end
                
                if ( SAS_Saved[PlrName]["sets"] ) then
                        SAS_UpgradeSets();
                end
                
                if ( SAS_Saved[PlrName]["HideMinimapButton"] ) then
                        SASMinimapFrame:Hide();
                end
                
                local currentset = SAS_GetCurrentSet();
                local liveactions = SAS_IterateActions(1);
                
                if ( SAS_Saved[PlrName]["AutoRestore"] and SAS_Saved["BackUp"] and SAS_Saved["BackUp"]["s"][PlrName] ) then
                        if ( SAS_CompareSet( liveactions, SAS_Saved["BackUp"]["s"][PlrName] ) ) then
                                SAS_Warning( "CHANGEDSINCELAST", SAS_RestoreBackUp, nil, 1 );
                                return;
                        end
                end
                if ( currentset ) then
                        if ( SAS_CompareSet( liveactions, SAS_Saved[PlrName]["s"][currentset] ) ) then
                                SASDebug( currentset.." does not appear to be loaded." );
                                SAS_SetCurrentSet();
                        else
                                SASDebug( currentset.." appears to be loaded, keeping as current set." );
                        end
                end
        elseif( event == "ACTIONBAR_SHOWGRID" ) then
                if ( not SAS_SwappingSet ) then
                        SAS_IsValidAction = 1;
                        --SASDebug("Valid Item on Cursor");
                end
        elseif( event == "ACTIONBAR_HIDEGRID" ) then
                if ( not SAS_SwappingSet ) then
                        SAS_IsValidAction = nil;
                        --SASDebug("No Valid Item on Cursor");
                end
        elseif ( event == "UNIT_INVENTORY_CHANGED" or event == "BAG_UPDATE" ) then
                if ( arg1 == "player" or tonumber(arg1) ) then
                        SAS_FindMissingItems();
                        SASActions_Display();
                end
        elseif ( event == "PLAYER_LOGOUT" ) then
                if ( not SAS_Saved["BackUp"] ) then
                        SAS_Saved["BackUp"] = {};
                        SAS_Saved["BackUp"]["s"] = {};
                end
                SAS_Saved["BackUp"]["s"][PlrName] = SAS_IterateActions();
        end
end

function SASMinimap_OnClick( button )
        -- Open up the main menu
        SAS_SetsDropDown:Hide();
        if ( button == "LeftButton" ) then
                if ( this:GetScript("OnUpdate") ) then
                        SASMinimap_DragStop()
                else
                        SASMain_Toggle();
                end
        else
                if ( this:GetScript("OnUpdate")) then
                        SASMinimap_DragStop();
                        SAS_POS = SAS_POS_TEMP;
                        SASMinimap_PosUpdate();
                else
                        SAS_SetsDropDown.point = "TOPRIGHT";
                        SAS_SetsDropDown.relativePoint = "BOTTOMLEFT";
                        ToggleDropDownMenu(1, nil, SAS_SetsDropDown, "SASMinimapButton", 0, 0);
                end
        end
end

-- Dragging functions for the minimap button position
function SASMinimap_DragStart()
        if ( not SAS_Saved[PlrName]["LockMinimapButton"] ) then
                SAS_POS_TEMP = SAS_POS;
                this:SetScript("OnUpdate", SASMinimap_DragUpdate); --SASMinimapFrame.BeingDragged = true;
        end
end
function SASMinimap_DragStop()
        SASMinimapButton:UnlockHighlight()
        this:SetScript("OnUpdate", nil); --SASMinimapFrame.BeingDragged = nil;
end
function SASMinimap_DragUpdate()
        -- Thanks to Gello for making this a ton shorter
        SASMinimapButton:LockHighlight();
        local curX, curY = GetCursorPosition();
        local mapX, mapY = Minimap:GetCenter();
        SAS_POS = math.deg(math.atan2( curY - mapY * Minimap:GetEffectiveScale(), mapX * Minimap:GetEffectiveScale() - curX ));
        SASMinimap_PosUpdate();
end

function SASMinimap_OnEnter()
        if ( SAS_SetsDropDown:IsVisible() ) then return; end
        GameTooltip:SetOwner(this, "ANCHOR_LEFT");
        GameTooltip:AddLine("Simple Action Sets");
        if ( SAS_Saved[PlrName]["LockMinimapButton"] ) then
                GameTooltip:AddLine(" Minimap button is locked", 0.6, 0.6, 0.6);
        elseif ( SASMinimapFrame.BeingDragged ) then
                GameTooltip:AddLine(" Right click SAS button to reset", 0.7, 0.7, 0.7);
        else
                GameTooltip:AddLine(" Drag to reposition minimap button", 0.7, 0.7, 0.7);
        end
        GameTooltip:Show();
end

function SASMinimap_PosUpdate()
        SASMinimapFrame:SetPoint("TOPLEFT","Minimap","TOPLEFT",53-((80+SAS_OFFSET)*cos(SAS_POS or 0)),((80+SAS_OFFSET)*sin(SAS_POS or 0))-55);
        SASOptions_Update();
end

function SASMinimap_SetsDropDown_Initialize()
        -- Setup the minimap dropdown menu
        local info = {};
        local hasSets;

        info.text = SAS_TEXT_DROPDOWN_TITLE;
        info.isTitle = 1;
        info.justifyH = "CENTER";
        info.notCheckable = 1;
        UIDropDownMenu_AddButton(info);
        
        SAS_SetsDropDown_Initialize();
end

function SAS_SetsDropDown_Initialize()
        local hasSets;
        
        local info = {};
        info.text = SAS_TEXT_DROPDOWN_OPEN;
        info.notCheckable = 1;
        info.func = SASMinimap_SetsDropDown_OnClick;
        UIDropDownMenu_AddButton(info);
        
        info = {};
        info.text = SAS_TEXT_DROPDOWN_SAVENEW;
        info.notCheckable = 1;
        info.func = SASMinimap_SetsDropDown_OnClick;
        UIDropDownMenu_AddButton(info);
        
        info = {};
        info.text = SAS_TEXT_DROPDOWN_SAVECURRENT;
        info.notCheckable = 1;
        if ( not SAS_GetCurrentSet() ) then
                info.disabled = 1;
        end
        info.func = SASMinimap_SetsDropDown_OnClick;
        UIDropDownMenu_AddButton(info);
        
        info = {};
        info.text = SAS_TEXT_DROPDOWN_SETS;
        info.isTitle = 1;
        info.justifyH = "CENTER";
        info.notCheckable = 1;
        UIDropDownMenu_AddButton(info);
        if ( SAS_Saved and SAS_Saved[PlrName]["s"] ) then
                local list = {};
                for k, v in SAS_Saved[PlrName]["s"] do
                        tinsert(list,k);
                end
                table.sort(list);
                for k, v in list do
                        info = { };
                        info.text = v;
                        info.isTitle = nil;
                        if ( SAS_GetCurrentSet() == v ) then
                                info.checked = 1;
                        end
                        info.func = SASMinimap_SetsDropDown_OnClick;
                        UIDropDownMenu_AddButton(info);
                        hasSets = 1;
                end
        end
        if ( not hasSets ) then
                info = { };
                info.text = SAS_TEXT_DROPDOWN_NONE;
                info.disabled = 1;
                UIDropDownMenu_AddButton(info);
        end
end

function SASMinimap_SetsDropDown_OnClick()
        -- minimap dropdown menu handler
        local id = this:GetID();
        if ( id == 2 ) then
                ShowUIPanel(SASMain);
        elseif ( id == 3 ) then
                SASActions_SaveNew();
        elseif ( id == 4 ) then
                SAS_Warning("SAVE", SAS_SaveSet, SAS_GetCurrentSet());
        elseif ( id > 5 ) then
                SASDebug( this:GetText() );
                SAS_SwapSet( this:GetText() );
        end
end

function SASMinimap_SetsDropDown_OnLoad()
        UIDropDownMenu_Initialize(this, SASMinimap_SetsDropDown_Initialize, "MENU");
end


-------------------------
-- Fake Drag functions --
-------------------------
function SASFakeDrag_Drop(clear)
        -- Pick up sas item 
        SASFakeDragFrame:Hide();
        local focus = GetMouseFocus();
        local action = SASFakeDragFrame.Action;
        local bar = SASFakeDragFrame.Bar;
        if ( focus and not (focus.IsSASAction or focus.IsSASBar) or clear ) then
                if ( SASFakeDragFrame.Action ) then
                        PlaySoundFile("Sound\\Interface\\uSpellIconDrop.wav");
                        SASDebug("Dumping FakeDrag Action "..SAS_ParseActionInfo(SASFakeDragFrame.Action, 1));
                elseif ( SASFakeDragFrame.Bar ) then
                        PlaySoundFile("Sound\\Interface\\uSpellIconDrop.wav");
                        SASDebug("Dumping FakeDrag Bar");
                else
                        --SASDebug("Dumping FakeDrag Action, no action");
                end
                SASFakeDragFrame.Action = nil;
                SASFakeDragFrame.Bar = nil;
                SASFakeDragFrame:SetScript("OnUpdate", nil);
                if ( SAS_DraggingBar ) then
                        if ( SASActions:IsVisible() ) then
                                SASActions_UpdateBar(SAS_DraggingBar);
                        else
                                SAS_DraggingBar = nil;
                        end
                end
        end
        return action or bar;
end

function SASFakeDrag_PickupAction(action)
        SASFakeDragFrame.Action = action;
        SASFakeDragFrame.Bar = nil;
        if ( action ) then
                local name, texture = SAS_ParseActionInfo( action );
                for i=1, 12 do
                        getglobal( "SASFakeDragFrameIcon"..i ):SetTexture();
                end
                SASDebug("FakeDrag Pickup Action "..name);
                SASFakeDragFrame:Show();
                SASFakeDragFrameIcon:SetTexture( SAS_FullPath(texture) );
                SASFakeDragFrameIcon:SetAlpha( 0.5 );
                PlaySoundFile("Sound\\Interface\\uSpellIconPickup.wav");
                SASFakeDragFrame:SetScript("OnUpdate", SASFakeDrag_OnUpdate);
        else
                SASFakeDragFrame:Hide();
                SASFakeDragFrame:SetScript("OnUpdate", nil);
        end
end

function SASFakeDrag_PickupBar(bar)
        SASFakeDragFrame.Bar = SAS_CopyTable(bar);
        SASFakeDragFrame.Action = nil;
        if ( bar ) then
                SASFakeDragFrameIcon:SetTexture();
                for i=1, 12 do
                        local icon = getglobal( "SASFakeDragFrameIcon"..i );
                        if ( bar[i] ) then
                                local texture = SAS_ParseActionInfo( bar[i], 2 );
                                icon:SetTexture( SAS_FullPath(texture) );
                                icon:SetTexCoord( 0, 1, 0, 1 );
                        else
                                icon:SetTexture("Interface\\Buttons\\UI-Quickslot");
                                icon:SetTexCoord( 0.1875, 0.8125, 0.1875, 0.8125 );
                        end
                        icon:SetAlpha( 0.5 );
                        SASFakeDragFrame:Show();
                        SASFakeDragFrame:SetScript("OnUpdate", SASFakeDrag_OnUpdate);
                end
                PlaySoundFile("Sound\\Interface\\uSpellIconPickup.wav");
        else
                SASFakeDragFrame:Hide();
                SASFakeDragFrame:SetScript("OnUpdate", nil);
        end
end

function SASFakeDrag_OnUpdate()
        -- Update the position of the FakeDrag frame to under the cursor
        if ( (this.Action or this.Bar) and this:IsVisible() ) then
                if ( SASActions:IsVisible() ) then
                        local curX, curY = GetCursorPosition();
                        local scale = UIParent:GetScale();
                        this:SetPoint("CENTER", "UIParent", "BOTTOMLEFT", curX/scale, curY/scale );
                else
                        SASFakeDrag_Drop(1);
                        this:SetScript("OnUpdate", nil);
                end
        else
                this:SetScript("OnUpdate", nil);
        end
end


-------------------------
-- Titan Panel Support --
-------------------------
function TitanPanelSASButton_OnLoad()
        this.registry = { 
                id = SAS_TITAN_ID,
                menuText = "Simple Action Sets", 
                buttonTextFunction = "TitanPanelSASButton_GetButtonText", 
                tooltipTitle = SAS_TITLE,
                tooltipTextFunction = "TitanPanelSASButton_GetTooltipText",
                icon = "Interface\\AddOns\\SimpleActionSets\\sas",
                iconWidth = 16,
                savedVariables = {
                        ShowLabelText = 1,  -- Default to 1
                        ShowIcon = 1;
                        ShowColoredText = 1,
                }
        };
end

function TitanPanelSASButton_GetButtonText(id)
        -- If id not nil, return corresponding plugin button
        -- Otherwise return this button and derive the real id
        local button, id = TitanUtils_GetButton(id, true);

        if ( SAS_GetCurrentSet() ) then
                if ( TitanGetVar(SAS_TITAN_ID, "ShowColoredText") ) then
                        return SAS_TITAN_LABEL, TitanUtils_GetGreenText( SAS_GetCurrentSet() );
                else
                        return SAS_TITAN_LABEL, TitanUtils_GetHighlightText( SAS_GetCurrentSet() );
                end
        else
                return SAS_TITAN_LABEL, TitanUtils_GetHighlightText( SAS_TITAN_NA );
        end
end

function TitanPanelSASButton_GetTooltipText()
        return TitanUtils_GetGreenText(SAS_TITAN_HINT);
end

function TitanPanelSAS_OnClick(button)
        if ( button == "LeftButton" ) then
                SASMain_Toggle();
        end
end
                
function TitanPanelRightClickMenu_PrepareSASMenu()
        TitanPanelRightClickMenu_AddTitle(TitanPlugins[SAS_TITAN_ID].menuText);
        
        SAS_SetsDropDown_Initialize();
        
        TitanPanelRightClickMenu_AddSpacer();   
        TitanPanelRightClickMenu_AddToggleIcon(SAS_TITAN_ID);
        TitanPanelRightClickMenu_AddToggleLabelText(SAS_TITAN_ID);
        TitanPanelRightClickMenu_AddToggleColoredText(SAS_TITAN_ID);

        TitanPanelRightClickMenu_AddSpacer();   
        TitanPanelRightClickMenu_AddCommand(TITAN_PANEL_MENU_HIDE, SAS_TITAN_ID, TITAN_PANEL_MENU_FUNC_HIDE);
end

function TitanPanelSAS_Update()
        if ( TitanPanelSASButton and TitanPanelButton_UpdateButton ) then
                TitanPanelButton_UpdateButton(SAS_TITAN_ID);
        end
end


------------------------
-- Reusable functions --
------------------------

function SASPrint(msg)
        -- Basic print function
        if ( not msg ) then
                msg = "|wnil";
        end
        msg = string.gsub( msg, "%|w", "|cffff0000" );
        msg = string.gsub( msg, "%|i", "|cffe6e6fA" );
        DEFAULT_CHAT_FRAME:AddMessage( "<|cff40E0D0SAS|r> "..msg, 0.012, 0.658, 0.62 );
        --local cols = "|cff03A98E";
end

function SASDebug(msg)
        -- Print when debug is turned on
        if ( SAS_Saved["debug"] ) then SASPrint("<|wDEBUG|r> "..msg); end
end

function SASTooltipAddLine(msg)
        -- Adds a colored line to the tooltip
        GameTooltip:AddLine( msg, 0.012, 0.658, 0.62, 1, 1 );
        GameTooltip:Show();
end

function SAS_ClearCursor()
        -- Clear the cursor of anything
        local i = 500
        while GetSpellName( i, BOOKTYPE_SPELL ) do
                i = i+1;
        end
        PickupSpell( i+1, BOOKTYPE_SPELL );
end

function SAS_BuildActionInfo(...) -- name, texture, rank, link, macro, ?
        if ( arg[2] ) then arg[2] = tPath(arg[2]); end
        if ( arg[3] ) then arg[3] = tRank(arg[3]); end
        if ( arg[4] ) then arg[4] = tLink(arg[4]); end
        while not arg[arg.n] and arg.n > 1 do arg.n = arg.n - 1; end
        if ( arg.n < 2 ) then return; end
        local string = "";
        for i=1, arg.n do
                string = string..(arg[i] or "").."·";
        end
        return string;
end

function SAS_IncActionInfo( action, val, part )
        if ( not val ) then return;
        elseif ( not part ) then part = 1; end
        local a = {SAS_ParseActionInfo(action)};
        a[part] = val;
        
        return SAS_BuildActionInfo( a[1], a[2], a[3], a[4], a[5], a[6] );
end

function SAS_ParseActionInfo( action, ... )
        if not action then return; end
        if type(action)~="string" then return action; end
        local a = {};
        for val in string.gfind( action, "(.-)·" ) do
                tinsert( a, val );
        end
        for k, v in a do if v == "" then v = nil; end end
        if ( arg.n > 0 ) then
                local b = {};
                for i=1, arg.n do
                        tinsert( b, a[arg[i]] );
                end
                return unpack(b);
        else
                return a[1], a[2], tonumber(a[3]), a[4], tonumber(a[5]), a[6]; --name, texture, rank, link, macro, ?;
        end
end

function SAS_ItemLink( item )
        -- Return an item's link
        local itemLink = SAS_FindItem( item );
        if ( itemLink ) then
                return SAS_FindLink( itemLink );
        end
end
function SAS_FindLink( item )
        -- Find an item's link number from it's item link
        if ( item ) then
                for link in string.gfind( item, "(%d+:%d+:%d+:%d+)" ) do
                        return tLink(link);
                end
        end
end

function SAS_ItemName( item )
        -- Return an item's name
        local itemName = SAS_FindItem( item );
        if ( itemName ) then
                return SAS_FindName( itemName );
        end
end
function SAS_FindName( item )
        -- Find an item's name from it's item link
        if ( item ) then
                for name in string.gfind( item, "%[(.+)%]") do
                        return name;
                end
        end
end

function SAS_FindItem( item )
        -- Iterate over items the player has and return it's link and location --
        if ( not item ) then return; end
        
        item = tostring(item);
        
        -- Iterate over bags
        for i=0, 4 do
                local bagSlots = GetContainerNumSlots(i);
                if ( bagSlots ) then
                        for j=1, bagSlots do
                                --SASDebug("Doing GetContainerItemLink() on "..i.." "..j);
                                local itemLink = GetContainerItemLink(i,j);
                                if ( itemLink ) then
                                        if ( item == SAS_FindLink( itemLink ) or item == SAS_FindName( itemLink ) ) then
                                                return itemLink, i, j;
                                        end
                                end
                        end
                end
        end
        
        -- Iterate over paper doll
        for i=0, 23 do
                --SASDebug("Doing GetInventoryItemLink() on "..i);
                local itemLink = GetInventoryItemLink("player",i);
                if ( itemLink ) then
                        if ( itemLink ) then
                                if ( item == SAS_FindLink( itemLink ) or item == SAS_FindName( itemLink ) ) then
                                        return itemLink, nil, nil, i;
                                end
                        end
                end
        end
end

function SAS_FindSpell( spell, rank )
        -- Iterate over spells the player has and return location
        if ( not spell ) then return; end
        local i = 1;
        local highest;
        local spellName, spellRank = GetSpellName( i, BOOKTYPE_SPELL );
        --if ( any and PlrClass == "WARRIOR" and PlrClass == "ROGUE" ) then
        --      rank = nil;
        --end
        local name, texture, offset, numSpells = nil, nil, 0, 0;
        --if ( not strict and PlrClass == "DRUID" and GetNumSpellTabs() == 4 ) then
        --      name, texture, offset, numSpells = GetSpellTabInfo(3)
        --      numSpells = numSpells+offset;
        --end
        while spellName do
                if ( spellName == spell ) then
                        highest = i;
                        if ( rank ) then
                                if ( tRank(spellRank) == tonumber(rank) ) then
                                        return i;
                                end
                        else
                                return i;
                        end
                end
                i = i+1;
                spellName, spellRank = GetSpellName( i, BOOKTYPE_SPELL );
        end
        
        return nil, highest;
end

function SAS_FindMacro( name, texture, macro )
        -- Check saved macro id
        local macroName, macroTexture, bestguess;
        if ( macro ) then
                macroName, macroTexture = GetMacroInfo(macro);
                if ( macroName == name ) then
                        if ( texture and macroTexture == texture ) then
                                return macro;
                        end
                        bestguess = macro;
                end
        end
        
        -- If no direct match, iterate over macros and return matching index
        local numAccountMacros, numCharacterMacros = GetNumMacros();
        numCharacterMacros = numCharacterMacros + 18;
        for i=1, 36 do
                if ( i > numAccountMacros and i < 19 ) then
                        -- no more global macros, skip to local
                        i = 19;
                end
                if ( i > numCharacterMacros ) then
                        -- no more macros
                        break;
                end
                macroName, macroTexture = GetMacroInfo(i)
                if ( macroName and macroName == name ) then
                        if ( texture and macroTexture == texture ) then
                                return i;
                        end
                        bestguess = i;
                end
        end
        
        return bestguess;
end

function SAS_GetActionInfo( id, quick )
        -- Scans an action button to attempt to determine if it's a spell, macro, or item
        if ( HasAction(id) ) then
                SASToolTip:SetAction(id);
                local name = SASToolTipTextLeft1:GetText();
                local rank, macro, link;
                local texture = GetActionTexture(id);

                local count = GetActionCount(id);

                if ( name and name ~= "" ) then
                        if ( SASToolTipTextRight1:IsShown() ) then
                                rank = tRank(SASToolTipTextRight1:GetText())
                        end
                        
                        local spellNum = SAS_FindSpell( name, rank );
                        if ( spellNum ) then
                                -- is ActionButton a spell
                                texture = GetSpellTexture( spellNum, BOOKTYPE_SPELL ); -- auras don't have correct texture on action bar
                        elseif ( GetActionText(id) ) then
                                -- is ActionButton a macro
                                macro = GetMacroIndexByName(name); -- will find first macro with name by creation date
                        else
                                -- is ActionButton an item
                                if ( quick ) then -- avoid slow item check
                                        link = "?";
                                else
                                        if ( count > 0 ) then
                                                link = SAS_ItemLink( name );
                                                if ( not link ) then SASDebug("|wItem "..name.." on action button "..id.." not found."); end
                                        else
                                                SASDebug("|wItem "..name.." on action button "..id.." is an item not on this character.");
                                                link = SAS_CheckItemDBs( name );
                                        end
                                end
                        end
                        
                        return name, texture, rank, link, macro; --{ name, rank, macro, link, texture };
                        
                elseif ( SAS_Saved[PlrName]["MissingItems"] and SAS_Saved[PlrName]["MissingItems"][id] ) then
                        name, texture, rank, link = SAS_ParseActionInfo(SAS_Saved[PlrName]["MissingItems"][id]);
                        if ( link == "?" ) then
                                link = SAS_CheckItemDBs(name);
                        end
                        return name, texture, rank, link, macro;
                else
                        SASDebug("|wAction "..id.." HasAction() but doesn't have anything in it.");
                end
        end
end

function SAS_IterateActions( quick )
        -- Iterate over all current actions
        local actionlist = {};
        for i=0, 9 do
                actionlist[i] = {};
                for j=1, 12 do
                        actionlist[i][j] = SAS_BuildActionInfo( SAS_GetActionInfo( j+(i*12), quick ) ); --action[1], action[2], action[3], action[4], action[5] );
                end
        end
        
        return actionlist;
end

function SAS_SetTooltip( bar, id )
        -- Sets the Tooltip for the found action
        if ( not bar or not id ) then return; end
        
        if ( SAS_Temp[bar][id] ) then
                local name, texture, rank, link, macro = SAS_ParseActionInfo( SAS_Temp[bar][id] ); --SAS_Temp[bar][id][1], SAS_Temp[bar][id][2], SAS_Temp[bar][id][3], SAS_Temp[bar][id][4], SAS_Temp[bar][id][5];
                texture = SAS_FullPath(texture);
                local TooltipReturn;
                -- is a macro
                if ( macro ) then
                        TooltipReturn = GameTooltip:SetText( name, 1, 1, 1 );
                        local macroName,macroTexture,macroText = GetMacroInfo( SAS_FindMacro(name, texture, macro) );
                        if ( macroText ) then
                                GameTooltip:AddLine( macroText, 0.75, 0.75, 0.75, 1, 1 );
                                GameTooltip:Show();
                        else
                                SASTooltipAddLine( SAS_TEXT_TOOLTIP_NOMACRO );
                        end
                -- is an item
                elseif ( link ) then
                        local itemLink;
                        SASDebug("SAS_SetTooltip - link = "..link);
                        if ( link == "?" or link == "1" ) then
                                itemLink = SAS_FindItem( name );
                                if ( itemLink ) then
                                        link = SAS_FindLink(itemLink);
                                else
                                        link = nil;
                                end
                        else
                                itemLink = SAS_FindItem( link );
                        end
                        if ( link and GetItemInfo("item:"..link) ) then
                                TooltipReturn = GameTooltip:SetHyperlink("item:"..link);
                                if ( not itemLink ) then
                                        SASTooltipAddLine( SAS_TEXT_TOOLTIP_NOTHAVE );
                                end
                        else
                                TooltipReturn = GameTooltip:SetText( name, 1, 1, 1 );
                                SASTooltipAddLine( SAS_TEXT_TOOLTIP_NOTVALID );
                        end
                -- is a spell
                else
                        local spellNum, highest = SAS_FindSpell( name, rank );
                        if ( spellNum ) then
                                TooltipReturn = GameTooltip:SetSpell( spellNum, BOOKTYPE_SPELL );
                                if ( rank ) then
                                        local spellName, spellRank = GetSpellName( spellNum, BOOKTYPE_SPELL );
                                        GameTooltipTextRight1:SetText( spellRank );
                                        GameTooltipTextRight1:SetTextColor( 0.5, 0.5, 0.5 );
                                        GameTooltipTextRight1:Show();
                                        GameTooltip:Show();
                                end
                        elseif ( highest ) then
                                local spellName, spellRank = GetSpellName( highest, BOOKTYPE_SPELL );
                                local string = string.gsub( SAS_TEXT_TOOLTIP_NOSPELLRANK, "%%r", rank );
                                TooltipReturn = GameTooltip:SetSpell( highest, BOOKTYPE_SPELL );
                                if ( spellRank ) then
                                        GameTooltipTextRight1:SetText( spellRank );
                                        GameTooltipTextRight1:SetTextColor( 0.5, 0.5, 0.5 );
                                        GameTooltipTextRight1:Show();
                                        GameTooltip:Show();
                                end
                                SASTooltipAddLine( string );
                        else
                                TooltipReturn = GameTooltip:SetText( name, 1, 1, 1 );
                                if ( rank ) then
                                        GameTooltipTextRight1:SetText( RANK.." "..rank );
                                        GameTooltipTextRight1:SetTextColor( 0.5, 0.5, 0.5 );
                                        GameTooltipTextRight1:Show();
                                        GameTooltip:Show();
                                end
                                SASTooltipAddLine( SAS_TEXT_TOOLTIP_NOSPELL );
                        end
                end
                
                if ( TooltipReturn ) then
                        this.updateTooltip = TOOLTIP_UPDATE_TIME;
                else
                        this.updateTooltip = nil;
                end
        end
end

function SAS_BarHasActions(bar, set)
        if ( not set ) then
                set = SAS_Temp;
        end
        if ( bar and set[bar] ) then
                for i=1, 12 do
                        if ( set[bar][i] ) then
                                return 1;
                        end
                end
        end
end

function SAS_ClearSlot(id)
        -- Clear an action slot
        if ( HasAction(id) and not SAS_Saved[PlrName]["NoEmptyButtons"] ) then
                PickupAction(id);
                SAS_ClearCursor();
        end
end

function SAS_MissingItem( id, itemInfo )
        -- Add to list of items to place on the bar when available.
        if ( id and itemInfo ) then
                if ( not SAS_Saved[PlrName]["MissingItems"] ) then
                        SAS_Saved[PlrName]["MissingItems"] = {};
                end
                local missing = SAS_Saved[PlrName]["MissingItems"]
                if ( not missing[id] or SAS_ParseActionInfo(missing[id], 3) ~= itemInfo[3] ) then
                        if ( not SAS_original_HasAction( id ) ) then
                                i = 1;
                                local passive = IsSpellPassive( i, BOOKTYPE_SPELL );
                                while passive do
                                        i = i + 1;
                                        passive = IsSpellPassive( i, BOOKTYPE_SPELL );
                                end
                                PickupSpell( i, BOOKTYPE_SPELL );
                                SAS_original_PickupAction( id );
                        end
                        SAS_Saved[PlrName]["MissingItems"][id] = SAS_BuildActionInfo(itemInfo[1], itemInfo[2], nil, itemInfo[3], nil, nil, itemInfo[4]);
                        SAS_original_PickupAction( id );
                        SAS_ClearCursor();
                        SASDebug( itemInfo[1] );
                end
        end
end

function SAS_ForceUpdate( id )
        if ( id and not SAS_original_HasAction( id ) ) then
                SASDebug( "force update on "..id );
                SAS_ToggleBarLocks();
                i = 1;
                --if ( not SAS_original_HasAction( id ) ) then
                        local passive = IsSpellPassive( i, BOOKTYPE_SPELL );
                        while passive do
                                i = i + 1;
                                passive = IsSpellPassive( i, BOOKTYPE_SPELL );
                        end
                        PickupSpell( i, BOOKTYPE_SPELL );
                        SAS_original_PickupAction( id );
                --end
                SAS_original_PickupAction( id );
                SAS_ToggleBarLocks(1);
                SAS_ClearCursor();
        end
end

function SAS_FindMissingItems()
        -- Readd missing items to action bar
        if ( not SAS_Saved[PlrName]["MissingItems"] ) then return; end
        SAS_ToggleBarLocks();
        for id, itemInfo in SAS_Saved[PlrName]["MissingItems"] do
                SAS_PlaceItem( id, SAS_ParseActionInfo( itemInfo, 4, 1, 6 ) );
        end
        SAS_ToggleBarLocks(1);
end

function SAS_GetMissingItemInfo( id )
        if ( id ) then
                if ( SAS_Saved and PlrName ) then
                        if ( SAS_Saved[PlrName]["MissingItems"] and SAS_Saved[PlrName]["MissingItems"][id] ) then
                                return SAS_Saved[PlrName]["MissingItems"][id];
                        end
                end
        end
end

function SAS_CheckItemDBs( name )
        -- check if there are any item db mods, get item link from that
        if ( ItemLinks ) then
                if ( ItemLinks[name] and ItemLinks[name]["i"] ) then
                        SASDebug( "found "..name.." in LootLink db" );
                        return tLink(ItemLinks[name]["i"]);
                end
        elseif ( IMDB ) then
                local realm = GetCVar("realmName");
                if ( IMDB[realm] and IMDB[realm][name] ) then
                        for itemLink in string.gfind( IMDB[realm][name], "item(%d:%d:%d:%d)" ) do
                                SASDebug( "found "..name.." in ItemSync db" );
                                return tLink(itemLink);
                        end
                elseif ( IMDB[name] ) then
                        for itemLink in string.gfind( IMDB[name], "item(%d:%d:%d:%d)" ) do
                                SASDebug( "found "..name.." in ItemSync db" );
                                return tLink(itemLink);
                        end
                end
        end
        
        SASDebug( "could not find "..name.." in either item dbs." );
        
        return "?";
end

function SAS_PlaceItem( id, link, name, set )
        -- Place an item, update set link id if found
        local itemLink, bag, slot, inv;
        if ( link == "?" or link == "1" ) then
                itemLink, bag, slot, inv = SAS_CheckItem( name, id, set );
        else
                itemLink, bag, slot, inv = SAS_FindItem( link );
        end
        if ( bag ) then
                PickupContainerItem( bag, slot );
                PlaceAction(id);
                return 1;
        elseif ( inv ) then
                PickupInventoryItem( inv );
                PlaceAction(id);
                return 1;
        end
end

function SAS_CheckItem( name, id, set )
        if ( name ) then
                itemLink, bag, slot, inv = SAS_FindItem( name );
                itemLink = SAS_FindLink(itemLink)
                if ( not itemLink ) then
                        itemLink = SAS_CheckItemDBs( name );
                end
                if ( itemLink and itemLink ~= "?" and itemLink ~= "1" ) then
                        local slot = math.mod( id, 12 );
                        local bar = (id-slot) / 12;
                        if ( SAS_Saved[PlrName]["s"][set] ) then
                                local action = SAS_Saved[PlrName]["s"][set][bar][slot];
                                local iname, ilink = SAS_ParseActionInfo(action, 1, 4);
                                if ( iname ) then
                                        if ( iname == name and ilink and ilink == "?" ) then
                                                SASDebug( "Updating item in action #"..id.." in set "..set.." with itemLink." );
                                                SAS_Saved[PlrName]["s"][set][bar][slot] = SAS_IncActionInfo(action, itemLink, 4);
                                        else
                                                SASDebug( "|wAttempted to update itemLink in action #"..id.." but names are wrong?" );
                                        end
                                end
                        end
                end
        end
        return itemLink, bag, slot, inv;
end

function SAS_ToggleBarLocks( on )
        -- disable locking on bar mods that hook PickupAction()
        for k, v in barmods do
                if ( getglobal(v[1]) ) then
                        if ( on ) then
                                setglobal(v[1], v[3])
                        else
                                v[3] = getglobal(v[1]);
                                setglobal(v[1], v[2]);
                        end
                end
        end
end

function SAS_SwapSet( set, player )
        -- Swaps a saved set to the player's real action bars.
        if ( not player ) then
                SASDebug( "SAS_SwapSet - No player name specified, using "..PlrName );
                player = PlrName;
        end
        
        local actions;
        if ( set ) then
                SASDebug(" SAS_SwapSet - about to do copy table on SAS_Saved["..player.."][sets]["..set.."]" );
                actions = SAS_CopyTable( SAS_Saved[player]["s"][set] );
        elseif ( SASMain:IsVisible() ) then
                SASDebug(" SAS_SwapSet - about to do copy table on SAS_Temp" );
                actions = SAS_CopyTable( SAS_Temp );
        else
                return;
        end

        if ( not actions ) then
                SASDebug("|wNo actions to change to.");
                return;
        end
                
        SAS_SwappingSet = true;
        if ( player == PlrName ) then
                SAS_SetCurrentSet( set );
        end
        SAS_ToggleBarLocks();
        SAS_ClearCursor();
        for i = 0, 9 do
                if ( SAS_BarEnabled(i,actions) and not ( not SAS_BarHasActions(i, actions) and not SAS_Saved[PlrName]["EmptyBars"] ) ) then
                        SASDebug("Bar "..(i+1).." is enabled");
                        for j = 1, 12 do
                                local id = j + i*12;
                                local msg = "Action "..id;
                                if ( actions[i][j]  ) then
                                        local ename, etexture, erank, elink, emacro = SAS_GetActionInfo(id, 1);
                                        local name, texture, rank, link, macro = SAS_ParseActionInfo( actions[i][j] ); --actions[i][j][1], actions[i][j][2], actions[i][j][3], actions[i][j][4], actions[i][j][5];
                                        if ( (name == ename and (( rank == erank ) or ( macro and emacro ) or ( link and elink ))) ) then
                                                msg = msg.." is the same as the one trying to be swapped.";
                                        else
                                                if ( macro ) then
                                                        msg = msg.." is a macro.";
                                                        local macroID = SAS_FindMacro( name, texture, macro )
                                                        if ( macroID ) then
                                                                PickupMacro( macroID );
                                                                PlaceAction(id);
                                                        else
                                                                msg = msg.." |wCouldn't find macro."
                                                                SAS_ClearSlot(id);
                                                        end
                                                elseif ( link ) then
                                                        msg = msg.." is an item.";
                                                        if ( not SAS_PlaceItem( id, link, name, set ) ) then
                                                                msg = msg.." |wCouldn't find item."
                                                                SAS_MissingItem( id, {name, texture, link, set} );
                                                        end
                                                elseif ( name ) then
                                                        msg = msg.." is a spell.";
                                                        local spellNum, highest = SAS_FindSpell( name, rank );
                                                        if ( spellNum ) then
                                                                PickupSpell( spellNum, BOOKTYPE_SPELL );
                                                                PlaceAction(id);
                                                        elseif ( highest ) then
                                                                local spellName, spellRank = GetSpellName( highest, BOOKTYPE_SPELL );
                                                                if ( rank ~= spellRank ) then
                                                                        msg = msg.." Can't find rank, using highest found instead.";
                                                                        PickupSpell( highest, BOOKTYPE_SPELL );
                                                                        PlaceAction(id);
                                                                else
                                                                        msg = msg.." Action is highest rank found, won't swap.";
                                                                end
                                                        else
                                                                msg = msg.." |wCoulnd't find spell."
                                                                SAS_ClearSlot(id);
                                                        end
                                                else
                                                        msg = msg.." is has no name, link, macro?";
                                                end
                                        end
                                        
                                        SAS_ClearCursor();
                                elseif ( not SAS_Saved[PlrName]["NoEmptyButtons"] ) then
                                        msg = msg.." is empty.";
                                        SAS_ClearSlot(id);
                                end
                                SASDebug(msg);
                        end
                elseif ( not SAS_BarEnabled(i,actions) ) then
                        SASDebug("Bar "..(i+1).." not enabled, skipping");
                else
                        SASDebug("Bar "..(i+1).." has no actions, skipping");
                end
        end
        SAS_ClearCursor();
        SAS_ToggleBarLocks(1);
                        
        SAS_SwappingSet = nil;
        TitanPanelSAS_Update();
end

function SAS_CopyTable(copyTable)
        -- properly copies a table instead of referencing the same table, thanks Sallust.
        if ( not copyTable ) then return; end
        local returnTable = {};
        for k, v in copyTable do
                if type(v) == "table" then
                        returnTable[k] = SAS_CopyTable(v);
                else
                        returnTable[k] = v;
                end
        end
        return returnTable;
end

function SAS_SetExists( set )
        -- Check to see if the set already exists
        if SAS_Saved[PlrName]["s"][set] then
                return true;
        end
end

function SAS_SaveSet(set)
        -- Save a set
        if ( not set ) then
                if ( SAS_GetCurrentSet() ) then
                        set = SAS_GetCurrentSet();
                else
                        return;
                end
        end
        local actions;
        if ( SASMain:IsVisible() and SAS_Temp ) then
                actions = SAS_CopyTable(SAS_Temp);
        else
                actions = SAS_IterateActions();
        end
        SASPrint(SAS_TEXT_SAVING..set);
        SAS_Saved[PlrName]["s"][set] = SAS_CopyTable(actions);
        SASActions_Load( set );
end

function SAS_Delete(set)
        -- Delete a set
        SASDebug(SAS_TEXT_DELETING..set);
        SAS_Saved[PlrName]["s"][set] = nil;
        if ( SAS_GetCurrentSet() == set ) then
                SAS_SetCurrentSet();
        end
        SASActions_Load();
end

function SAS_SetCurrentSet( set )
        SAS_Saved[PlrName]["CurrentSet"] = set;
end

function SAS_GetCurrentSet()
        if ( SAS_Saved and PlrName ) then
                return SAS_Saved[PlrName]["CurrentSet"];
        end
end

function SASBackUp()
        SAS_BackUp = SAS_IterateActions();
end

function SAS_RestoreBackUp()
        SAS_SwapSet( PlrName, "BackUp" );
end

function SAS_Console( msg )
        if ( strlower(string.sub( msg, 1, 4 )) == "swap" ) then
                local set = string.sub( msg, 6 );
                if ( set and SAS_SetExists( set ) ) then
                        SAS_SwapSet( set );
                else
                        SASPrint( string.gsub(SAS_TEXT_CONSOLE_NOVALID, "%%s", set) );
                end
        elseif ( strlower(string.sub( msg, 1, 4 )) == "save" ) then
                local set = string.sub( msg, 6 );
                if ( set ) then
                        if ( SAS_SetExists( set ) ) then
                        else
                                SAS_SaveSet( set );
                        end
                end
        elseif ( strlower(string.sub( msg, 1, 5 )) == "debug" ) then
                SAS_Saved["debug"] = not SAS_Saved["debug"];
        elseif ( strlower(string.sub( msg, 1, 4 )) == "show" or msg == "" ) then
                SASMain_Toggle();
        else
                SASPrint( SAS_TEXT_CONSOLE_HELP );
        end
end
function tPath( texture )
        -- truncate icon's file path
        return string.gsub( texture, IconPath, "" );
end

function SAS_FullPath( texture )
        -- add icon's file path back in
        if ( texture ) then return IconPath..texture; end
end

function tRank( rank )
        -- truncate ranks to just numerical data
        if ( not rank ) then return; end
        for i in string.gfind( rank, "%d+" ) do return tonumber(i); end
end

function tLink( itemLink )
        -- truncate item links to item ids
        if ( not itemLink ) then return; end
        for num in string.gfind( itemLink, "(%d+):0:0:0" ) do return num; end
        return itemLink;
end

function SAS_TableNil(a)
        if a then
                for k, v in a do
                        return a;
                end
        end
end

local function actionComp( a, b )
        if a and b then
                local A = { SAS_ParseActionInfo( a ) };
                local B = { SAS_ParseActionInfo( b ) };
                for k, v in A do
                        if ( k ~= 4 and (not B[k] or v ~= B[k]) ) then
                                SASDebug( k.." "..v.." does not == "..B[k] );
                                return 1;
                        end
                end
        else
                if ( a ) then
                        SASDebug( "no b" );
                elseif ( b ) then
                        SASDebug( "no a" );
                else
                        SASDebug( "no a or b" );
                end
                return 1;
        end
end

function SAS_CompareSet( set1, set2, strict )
        -- Compare two sets to see if they're similar
        if ( not set1 or not set2 ) then
                if ( not set1 ) then
                        SASDebug( "no set1" );
                elseif ( not set2 ) then
                        SASDebug( "no set2" );
                else
                        SASDebug( "no set1 or set2" );
                end
                return 1;
        end
                
        for i=0, 9 do
                if ( set1[i] ) then
                        if ( strict == 2 ) then
                                if ( set1[i][0] ~= set2[i][0] ) then
                                        return 1;
                                end
                        end
                        for j=1, 12 do
                                if ( set1[i][j] ) then
                                        if ( actionComp( set1[i][j], set2[i][j] ) ) then
                                                SASDebug( "returning at "..i.." "..j );
                                                return 1;
                                        end
                                elseif ( strict and set2[i][j] ) then   
                                        SASDebug( "strict returning at "..i.." "..j.." no set1 but set2" );
                                        return 1;
                                end
                        end
                elseif ( strict and set2[i] ) then
                        SASDebug( "strict returning at "..i.." no set1 but set2" );
                        return 1;
                end
        end
end

function SAS_UpgradeSets()
        -- Move action set data from 0.373 and prior versions to 0.4+
        for p, v in SAS_Saved do
                if ( v["sets"] ) then
                        SASPrint( "Doing upgrade on "..p.."'s sets" );
                        v["s"] = {};
                        for s, k in v["sets"] do
                                v["s"][s] = {};
                                for i=0, 9 do
                                        v["s"][s][i] = {};
                                        if ( not k[i]["enable"] ) then
                                                v["s"][s][i] = {[0] = 1};
                                        end
                                        for j=1, 12 do
                                                local a = SAS_TableNil(SAS_CopyTable(k[i][j]));
                                                if ( a ) then
                                                        v["s"][s][i][j] = SAS_BuildActionInfo(a[1],a[5],a[2],a[4],a[3]);
                                                end
                                        end
                                end
                        end
                        v["sets"] = nil; -- delete old set data!!
                end
        end
end


-- Unused code

--[[ unneeded delay code - save for later
function SAS_MissingItem( id, itemInfo )
        -- Add to list of items to place on the bar when available.
        if ( id ) then
                if ( not SAS_Saved[PlrName]["MissingItems"] ) then
                        SAS_Saved[PlrName]["MissingItems"] = {};
                end
                SAS_Saved[PlrName]["MissingItems"][id] = itemInfo;
                SAS_ForceUpdate( id );
        end
end]]

--[[function SAS_ForceUpdate( id )
        -- Force an update event for an action
        tinsert( SAS_ForceUpdateList, id );
        SASFrame:SetScript( "OnUpdate", SAS_Delayed_OnUpdate );
end

function SAS_Delayed_OnUpdate()
        local id = SAS_ForceUpdateList[1];
        if ( id and not SAS_original_HasAction( id ) ) then
                local itemInfo = SAS_GetMissingItemInfo( id );
                i = 1;
                local passive = IsSpellPassive( i, BOOKTYPE_SPELL );
                while passive do
                        i = i + 1;
                        passive = IsSpellPassive( i, BOOKTYPE_SPELL );
                end
                PickupSpell( i, BOOKTYPE_SPELL );
                SAS_original_PickupAction( id );
                SAS_Saved[PlrName]["MissingItems"][id] = itemInfo;
                SAS_original_PickupAction( id );
                SAS_ClearCursor();
                tremove( SAS_ForceUpdateList, 1 );
        else
                SASFrame:SetScript( "OnUpdate", nil );
        end
end]]

--[[ attempt to unquely identify macros
function SAS_CreateUniqueMacros()
        local function iterateMacros()
                local all, numglobal, numlocal = {}, GetNumMacros();
                numlocal = numlocal + 18;
                for i=1, 36 do
                        if ( i > numglobal and i < 19 ) then
                                -- no more global macros, skip to local
                                i = 19;
                        end
                        if ( i > numlocal ) then
                                -- no more macros
                                return;
                        end
                        local name = GetMacroInfo(i);
                        if ( name ) then
                                if ( all[name] ) then
                                        all[name] = all[name] + 1;
                                        EditMacro(i, name.."·");
                                        return iterateMacros();
                                else
                                        all[name] = 0;
                                end
                        end
                end
        end
        iterateMacros();
end

function SAS_StripUniqueMacros()
        for i=1, 36 do
                local name = GetMacroInfo(i);
                if ( name ) then
                        EditMacro(i, SAS_StripUniqueMacroName(name));
                end
        end
end

function SAS_StripUniqueMacroName(name)
        return string.gsub(name, "(.-)·+", "%1");
end]]