vanilla-wow-addons – Rev 1

Subversion Repositories:
Rev:
-- default Variables
configdata = {
                                                        activetab = 1,
                                                        mainframeposx = 10 , 
                                                        mainframeposy = -300,
                                                        namessize = 200,
                                                        usenamebar = true,
                                                        hidenamebar = true,
                                                        namebartext = "!trigger - !count",
                                                        titletext = "!tNext [!iExpired/!iAll]",
                                                        namebarposx = 10,
                                                        namebarposy = -450,
                                                        minimizedposx = 10,
                                                        minimizedposy = -500,
                                                        minimized = true,
                                                        triggerconfposx = 300,
                                                        triggerconfposx = -400,                                                 
                                                        timersort = 1,
                                                        timersortascending = false,
                                                        triggersort = 1,
                                                        triggersortascending = false,   
                                                        spamto = TIMERS_LOC_ALLWOSELF,
                                                        spamonpress = 10,
                                                        alldisabled = false,
                                                        framescale = 100                                                
                                                        };

TimerscurrentTime = nil;

timerdata = {};

-- Hooks
local Timers_OldSpellHook;
local Timers_OldSpellHookByName;
local Timers_OldUseAction;

-- local variables
local timerUpdateFlag = false;
local triggerPointer = {};
local timeIsCorrect = false;
local timers_dropdown_row;
local trigger_edit;
local triggerdata_DEFAULT = {};
local configdata_DEFAULT = {};
local groupdata_DEFAULT = {};
local inCombat = false;
local timeSinceUpdate = 0;
local currSpellCast;
local IconArray = {};
local Timers_Debug = false;

-- GUI Functions
function TimersDropDownMainMenu_Init()
        UIDropDownMenu_Initialize(this, TimersMenu_CreateMainMenuDropDown, "MENU");
end

function TimersDropDownTimerRowMenu_Init()
        UIDropDownMenu_Initialize(this, TimersMenu_CreateTimerRowDropDown, "MENU");
end

function TimersDropDownTimerRowMenuEntry_Init()
        if string.find(this:GetName(),"ChanBox") ~= nil then
                UIDropDownMenu_Initialize(this, TimersMenu_CreateTimerRowChannelDropDown, "SELECTOR");
        elseif string.find(this:GetName(),"TypeBox") ~= nil then
                UIDropDownMenu_Initialize(this, TimersMenu_CreateTimerRowTypeDropDown, "SELECTOR");
        elseif string.find(this:GetName(),"ModeBox") ~= nil then        
                UIDropDownMenu_Initialize(this, TimersMenu_CreateTimerRowModeDropDown, "SELECTOR");
        elseif string.find(this:GetName(), "TextBox") or string.find(this:GetName(), "EditBox4") then
                UIDropDownMenu_Initialize(this, TimersMenu_CreateTimerRowTextDropDown, "SELECTOR");     
        end
end     

function TimersMenu_CreateTimerRowTextDropDown(level)
        if level == 1 then
                info = {["text"] = TIMERS_LOC_COMBATSTART, ["func"] = TimersEdit_SaveTextImplicit, ["arg1"] = this ,["arg2"] = TIMERS_LOC_COMBATSTART};
                UIDropDownMenu_AddButton(info, 1);
                info = {["text"] = TIMERS_LOC_COMBATSTOP, ["func"] = TimersEdit_SaveTextImplicit, ["arg1"] = this ,["arg2"] = TIMERS_LOC_COMBATSTOP};
                UIDropDownMenu_AddButton(info, 1);
                info = {["text"] = TIMERS_LOC_ZONEENTER, ["func"] = TimersEdit_SaveTextImplicit, ["arg1"] = this ,["arg2"] = TIMERS_LOC_ZONEENTER};
                UIDropDownMenu_AddButton(info, 1);
                info = {["text"] = TIMERS_LOC_SPELL_CAST, ["func"] = TimersEdit_SaveTextImplicit, ["arg1"] = this ,["arg2"] = TIMERS_LOC_SPELL_CAST};
                UIDropDownMenu_AddButton(info, 1);              
        end
end

function TimersConfig_CreateSpamToDropDown(level)
        if level == 1 then
                info = {["text"] = TIMERS_LOC_ALL, ["func"] = TimersMenu_SetConfigSpam, ["arg1"] = this , ["arg2"] = TIMERS_LOC_ALL};
                UIDropDownMenu_AddButton(info, 1);
                info = {["text"] = TIMERS_LOC_ALLWOSELF, ["func"] = TimersMenu_SetConfigSpam, ["arg1"] = this ,["arg2"] = TIMERS_LOC_ALLWOSELF};
                UIDropDownMenu_AddButton(info, 1);
                info = {["text"] = TIMERS_LOC_ONLYSELECTED, ["func"] = TimersMenu_SetConfigSpam, ["arg1"] = this ,["arg2"] = TIMERS_LOC_ONLYSELECTED};
                UIDropDownMenu_AddButton(info, 1);
                info = {["text"] = TIMERS_LOC_ONLYHIGHER, ["func"] = TimersMenu_SetConfigSpam, ["arg1"] = this ,["arg2"] = TIMERS_LOC_ONLYHIGHER};
                UIDropDownMenu_AddButton(info, 1);
        end
end     

function TimersMenu_CreateTimerRowChannelDropDown(level)
        if level == 1 then
                if not (triggerdata[trigger_edit].name == "default") then
                        info = {["text"] = TIMERS_LOC_DEFAULT, ["func"] = TimersEdit_SaveChannel, ["arg1"] = this , ["arg2"] = TIMERS_LOC_DEFAULT};
                        UIDropDownMenu_AddButton(info, 1);      
                end
                info = {["text"] = TIMERS_LOC_SELF, ["func"] = TimersEdit_SaveChannel, ["arg1"] = this ,["arg2"] = TIMERS_LOC_SELF};
                UIDropDownMenu_AddButton(info, 1);
                info = {["text"] = TIMERS_LOC_PARTY, ["func"] = TimersEdit_SaveChannel, ["arg1"] = this ,["arg2"] = TIMERS_LOC_PARTY};
                UIDropDownMenu_AddButton(info, 1);
                info = {["text"] = TIMERS_LOC_RAID, ["func"] = TimersEdit_SaveChannel, ["arg1"] = this ,["arg2"] = TIMERS_LOC_RAID};
                UIDropDownMenu_AddButton(info, 1);
                info = {["text"] = TIMERS_LOC_CTRAID, ["func"] = TimersEdit_SaveChannel, ["arg1"] = this ,["arg2"] = TIMERS_LOC_CTRAID};
                UIDropDownMenu_AddButton(info, 1);
        end
end

function TimersMenu_CreateTimerRowTypeDropDown(level)
        if level == 1 then
                if not (triggerdata[trigger_edit].name == "default") then
                        info = {["text"] = TIMERS_LOC_DEFAULT, ["func"] = TimersEdit_SaveType, ["arg1"] = this ,["arg2"] = TIMERS_LOC_DEFAULT};
                        UIDropDownMenu_AddButton(info, 1);      
                end
                info = {["text"] = TIMERS_LOC_MULTIPLE, ["func"] = TimersEdit_SaveType, ["arg1"] = this ,["arg2"] = TIMERS_LOC_MULTIPLE};
                UIDropDownMenu_AddButton(info, 1);
                info = {["text"] = TIMERS_LOC_ONCE, ["func"] = TimersEdit_SaveType, ["arg1"] = this ,["arg2"] = TIMERS_LOC_ONCE};
                UIDropDownMenu_AddButton(info, 1);
                info = {["text"] = TIMERS_LOC_ONCEGROUP, ["func"] = TimersEdit_SaveType, ["arg1"] = this ,["arg2"] = TIMERS_LOC_ONCEGROUP};
                UIDropDownMenu_AddButton(info, 1);
                info = {["text"] = TIMERS_LOC_PAUSE, ["func"] = TimersEdit_SaveType, ["arg1"] = this ,["arg2"] = TIMERS_LOC_PAUSE};
                UIDropDownMenu_AddButton(info, 1);
                info = {["text"] = TIMERS_LOC_STOP, ["func"] = TimersEdit_SaveType, ["arg1"] = this ,["arg2"] = TIMERS_LOC_STOP};
                UIDropDownMenu_AddButton(info, 1);
                info = {["text"] = TIMERS_LOC_WARNONLY, ["func"] = TimersEdit_SaveType, ["arg1"] = this ,["arg2"] = TIMERS_LOC_WARNONLY};
                UIDropDownMenu_AddButton(info, 1);
        end
end

function TimersMenu_CreateTimerRowModeDropDown(level)
        if level == 1 then
                if not (triggerdata[trigger_edit].name == "default") then
                        info = {["text"] = TIMERS_LOC_DEFAULT, ["func"] = TimersEdit_SaveMode, ["arg1"] = this ,["arg2"] = TIMERS_LOC_DEFAULT};
                        UIDropDownMenu_AddButton(info, 1);
                end
                info = {["text"] = TIMERS_LOC_CONTINUE, ["func"] = TimersEdit_SaveMode, ["arg1"] = this ,["arg2"] = TIMERS_LOC_CONTINUE};
                UIDropDownMenu_AddButton(info, 1);
                info = {["text"] = TIMERS_LOC_DELETE, ["func"] = TimersEdit_SaveMode, ["arg1"] = this ,["arg2"] = TIMERS_LOC_DELETE};
                UIDropDownMenu_AddButton(info, 1);
                info = {["text"] = TIMERS_LOC_RESET, ["func"] = TimersEdit_SaveMode, ["arg1"] = this ,["arg2"] = TIMERS_LOC_RESET};
                UIDropDownMenu_AddButton(info, 1);
                info = {["text"] = TIMERS_LOC_INC, ["func"] = TimersEdit_SaveMode, ["arg1"] = this ,["arg2"] = TIMERS_LOC_INC};
                UIDropDownMenu_AddButton(info, 1);
        end
end

function TimersMenu_CreateMainMenuDropDown(level)
        if configdata.activetab == 1 then
                if level == 1 then
                        if configdata.alldisabled then
                                info = {["text"] = TIMERS_LOC_ENABLEALL, ["func"] = TimersEdit_ToggleDisableAll};
                                UIDropDownMenu_AddButton(info, 1);
                        else
                                info = {["text"] = TIMERS_LOC_DISABLEALL, ["func"] = TimersEdit_ToggleDisableAll};
                                UIDropDownMenu_AddButton(info, 1);
                        end
                        info = {["text"] = " -------- ",["notClickable"] = 1};
                        UIDropDownMenu_AddButton(info, 1);
                        info = {["text"] = TIMERS_LOC_DELETEXPIRED, ["func"] = TimersEdit_DeleteExpired};
                        UIDropDownMenu_AddButton(info, 1);
                        info = {["text"] = TIMERS_LOC_DELETEBYGROUP, ["hasArrow"] = 1};
                        UIDropDownMenu_AddButton(info, 1);              
                        info = {["text"] = TIMERS_LOC_DELETALL, ["func"] = TimersEdit_DeleteAllTimer};
                        UIDropDownMenu_AddButton(info, 1);
                        info = {["text"] = " -------- ",["notClickable"] = 1};
                        UIDropDownMenu_AddButton(info, 1);
                        info = {["text"] = TIMERS_LOC_RESETEXPIRED, ["func"] = TimersEdit_ResetExpired};
                        UIDropDownMenu_AddButton(info, 1);
                        info = {["text"] = TIMERS_LOC_RESETBYGROUP, ["hasArrow"] = 1};
                        UIDropDownMenu_AddButton(info, 1);
                        info = {["text"] = TIMERS_LOC_RESETALL, ["func"] = TimersEdit_ResetAll};
                        UIDropDownMenu_AddButton(info, 1);
                        info = {["text"] = " -------- ",["notClickable"] = 1};
                        UIDropDownMenu_AddButton(info, 1);
                        info = {["text"] = TIMERS_LOC_SPAMALLTO,["hasArrow"] = 1};
                        UIDropDownMenu_AddButton(info, 1);
                elseif level == 2 and string.find(this:GetName(), "Button4") then
                        if table.getn(timerdata) == 0 then
                                info = {["text"] = TIMERS_LOC_NO_TIMERS,["notClickable"] = 1};
                                UIDropDownMenu_AddButton(info, 2);
                        else
                                for i=1, table.getn(groupdata) do
                                        local hasTimer = false;
                                        for j=1, table.getn(timerdata) do
                                                if triggerdata[Timers_TriggerNameToNumber(timerdata[j].trigger)].group == groupdata[i].name or (not triggerdata[Timers_TriggerNameToNumber(timerdata[j].trigger)].group and groupdata[i].name == TIMERS_LOC_NOGROUP) then
                                                        hasTimer = i;
                                                end
                                        end
                                        if hasTimer then
                                                info = {["text"] = groupdata[i].name, ["func"] = TimersEdit_DeleteByGroup, ["arg1"] = groupdata[i].name};
                                                UIDropDownMenu_AddButton(info, 2);
                                        end
                                end
                        end
                elseif level == 2 and string.find(this:GetName(), "Button8") then
                        if table.getn(timerdata) == 0 then
                                info = {["text"] = TIMERS_LOC_NO_TIMERS,["notClickable"] = 1};
                                UIDropDownMenu_AddButton(info, 2);
                        else
                                for i=1, table.getn(groupdata) do
                                        local hasTimer = false;
                                        for j=1, table.getn(timerdata) do
                                                if triggerdata[Timers_TriggerNameToNumber(timerdata[j].trigger)].group == groupdata[i].name or (not triggerdata[Timers_TriggerNameToNumber(timerdata[j].trigger)].group and groupdata[i].name == TIMERS_LOC_NOGROUP) then
                                                        hasTimer = i;
                                                end
                                        end
                                        if hasTimer then
                                                info = {["text"] = groupdata[i].name, ["func"] = TimersEdit_ResetByGroup, ["arg1"] = groupdata[i].name};
                                                UIDropDownMenu_AddButton(info, 2);
                                        end
                                end
                        end                                                                     
                elseif level == 2 and string.find(this:GetName(), "Button11") then
                        if ChatEdit_GetLastTellTarget(ChatFrameEditBox) ~= "" then
                                info = {["text"] = TIMERS_LOC_REPLY.." ("..ChatEdit_GetLastTellTarget(ChatFrameEditBox)..")", ["func"]=TimersSend_AllTimer,  ["arg1"]="REPLY"};
                                UIDropDownMenu_AddButton(info, 2);
                        end
                        info = {["text"] = TIMERS_LOC_SELF, ["func"]=TimersSend_AllTimer,  ["arg1"]=TIMERS_LOC_SELF};
                        UIDropDownMenu_AddButton(info, 2);
                        info = {["text"] = TIMERS_LOC_PARTY, ["func"]=TimersSend_AllTimer,  ["arg1"]=TIMERS_LOC_PARTY};
                        UIDropDownMenu_AddButton(info, 2);
                        info = {["text"] = TIMERS_LOC_RAID, ["func"]=TimersSend_AllTimer,  ["arg1"]=TIMERS_LOC_RAID};
                        UIDropDownMenu_AddButton(info, 2);
                        info = {["text"] = TIMERS_LOC_OFFICER, ["func"]=TimersSend_AllTimer,  ["arg1"]=TIMERS_LOC_OFFICER};
                        UIDropDownMenu_AddButton(info, 2);                      
                end
        elseif configdata.activetab == 3 then
                if level == 1 then
                        if configdata.hideinactive then
                                info = {["text"] = TIMERS_LOC_TOGGLEALLINACTIVSHOW, ["func"] = Timers_ToggleShowInactive};
                                UIDropDownMenu_AddButton(info, 1);
                        else
                                info = {["text"] = TIMERS_LOC_TOGGLEALLINACTIVHIDE, ["func"] = Timers_ToggleShowInactive};
                                UIDropDownMenu_AddButton(info, 1);
                        end
                        info = {["text"] = TIMERS_LOC_TOGGLEALLFOLD, ["func"]= Timers_ToggleFoldAll};
                        UIDropDownMenu_AddButton(info, 1);
                        info = {["text"] = TIMERS_LOC_TOGGLEALL, ["func"] = Timers_ToggleActiveAll};
                        UIDropDownMenu_AddButton(info, 1);
                        info = {["text"] = " -------- ",["notClickable"] = 1};
                        UIDropDownMenu_AddButton(info, 1);
                        info = {["text"] = TIMERS_LOC_RESETALLCNT, ["func"] = Timers_ResetAllCnt};
                        UIDropDownMenu_AddButton(info, 1);
                        info = {["text"] = " -------- ",["notClickable"] = 1};
                        UIDropDownMenu_AddButton(info, 1);
                        info = {["text"] = TIMERS_LOC_ADDGROUP, ["func"] = Timers_AddGroup };
                        UIDropDownMenu_AddButton(info, 1);
                        info = {["text"] = TIMERS_LOC_DELETEGROUP, ["hasArrow"] = 1};
                        UIDropDownMenu_AddButton(info, 1);
                        info = {["text"] = TIMERS_LOC_ADDTRIGGER, ["func"] = Timers_AddTrigger};
                        UIDropDownMenu_AddButton(info, 1);
                        info = {["text"] = " -------- ",["notClickable"] = 1};
                        UIDropDownMenu_AddButton(info, 1);
                        info = {["text"] = TIMERS_LOC_RESETALLTRIGGER, ["func"] = Timers_ResetAllTrigger};
                        UIDropDownMenu_AddButton(info, 1);                      
                elseif level == 2 then
                        local onlydefault = true;
                        for i = 1, table.getn(groupdata) do
                                if groupdata[i].isnotdefault then
                                        info = {["text"] = groupdata[i].name, ["func"] = Timers_DeleteGroup, ["arg1"] = i};
                                        UIDropDownMenu_AddButton(info, 2);
                                        onlydefault = false;
                                end                             
                        end
                        if onlydefault then
                                info = {["text"] = TIMERS_LOC_NOT_DELETE_DEFAULT, ["notClickable"] = 1};
                                UIDropDownMenu_AddButton(info, 2);
                        end                                     
                end
        end
end

function TimersMenu_CreateTimerRowDropDown(level)
        if (configdata.activetab == 1 or configdata.activetab == 2) then
                if level == 1 then
                        local i = Timers_GetRow(this)+FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame);
                        timers_dropdown_row = Timers_GetRow(this);
                        info = {["text"] = TIMERS_LOC_INVOKED,["notClickable"] = 1};
                        UIDropDownMenu_AddButton(info, 1);
                        info = {["text"] = timerdata[i].trigger,["notClickable"] = 1};
                        UIDropDownMenu_AddButton(info, 1);
                        info = {["text"] = " -------- ",["notClickable"] = 1};
                        UIDropDownMenu_AddButton(info, 1);                                      
                        info = {["text"] = TIMERS_LOC_DELETE, ["func"] = TimersEdit_DeleteTimer, ["arg1"] = this};
                        UIDropDownMenu_AddButton(info, 1);
                        info = {["text"] = TIMERS_LOC_RESET, ["func"] = TimersEdit_ResetTimer, ["arg1"] = this};
                        UIDropDownMenu_AddButton(info, 1);
                        if not timerdata[i].stopped then
                                if not timerdata[i].paused then
                                        info = {["text"] = TIMERS_LOC_PAUSE, ["func"] = TimersEdit_TogglePaused, ["arg1"] = this};
                                        UIDropDownMenu_AddButton(info, 1);
                                else
                                        info = {["text"] = TIMERS_LOC_RESUME, ["func"] = TimersEdit_TogglePaused, ["arg1"] = this};
                                        UIDropDownMenu_AddButton(info, 1);
                                end
                                if triggerdata[Timers_TriggerNameToNumber(timerdata[i].trigger)].mode == TIMERS_LOC_INC then            
                                        info = {["text"] = TIMERS_LOC_STOP, ["func"] = TimersEdit_StopTimer, ["arg1"] = this};
                                        UIDropDownMenu_AddButton(info, 1);
                                end
                        end
                        info = {["text"] = TIMERS_LOC_SPAMTO,["hasArrow"] = 1};
                        UIDropDownMenu_AddButton(info, 1);
                elseif level == 2 then
                        if ChatEdit_GetLastTellTarget(ChatFrameEditBox) ~= "" then
                                info = {["text"] = TIMERS_LOC_REPLY.." ("..ChatEdit_GetLastTellTarget(ChatFrameEditBox)..")", ["func"] = TimersSend_Timer, ["arg1"] = timers_dropdown_row, ["arg2"] = "REPLY"};
                                UIDropDownMenu_AddButton(info, 2);
                        end
                        info = {["text"] = TIMERS_LOC_PARTY, ["func"] = TimersSend_Timer, ["arg1"] = timers_dropdown_row, ["arg2"] = TIMERS_LOC_PARTY};
                        UIDropDownMenu_AddButton(info, 2);
                        info = {["text"] = TIMERS_LOC_RAID, ["func"] = TimersSend_Timer, ["arg1"] = timers_dropdown_row, ["arg2"] = TIMERS_LOC_RAID};
                        UIDropDownMenu_AddButton(info, 2);
                        info = {["text"] = TIMERS_LOC_CTRAID, ["func"] = TimersSend_Timer, ["arg1"] = timers_dropdown_row, ["arg2"] = TIMERS_LOC_CTRAID};
                        UIDropDownMenu_AddButton(info, 2);
                        info = {["text"] = TIMERS_LOC_OFFICER, ["func"] = TimersSend_Timer, ["arg1"] = timers_dropdown_row, ["arg2"] = TIMERS_LOC_OFFICER};
                        UIDropDownMenu_AddButton(info, 2);                                      
                end
        else
                if level == 1 then
                        timers_dropdown_row = Timers_GetRow(this);
                        info = {["text"] = TIMERS_LOC_ADVANCEDCONF, ["func"] = Timers_ShowAdvancedConfig};
                        UIDropDownMenu_AddButton(info, 1);                      
                        info = {["text"] = TIMERS_LOC_RESETCNT, ["func"] = Timers_ResetCnt, ["arg1"] = this};
                        UIDropDownMenu_AddButton(info, 1);
                        if triggerdata[Timers_RowToTrigger(timers_dropdown_row+FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame))].isnotdefault then
                                info = {["text"] = TIMERS_LOC_DELETETRIGGER, ["func"] = Timers_DeleteTrigger, ["arg1"] = this};
                                UIDropDownMenu_AddButton(info, 1);
                        end
                        if not (triggerdata[Timers_RowToTrigger(Timers_GetRow(this)+FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame))].name == "default") then
                                info = {["text"] = TIMERS_LOC_MOVETOGROUP,["hasArrow"] = 1};
                                UIDropDownMenu_AddButton(info, 1);
                        end     
                        if Timers_TriggerNameToDefaultNumber(triggerdata[Timers_RowToTrigger(Timers_GetRow(this)+FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame))].name) then
                                info = {["text"] = TIMERS_LOC_RESETTRIGGER, ["func"] = Timers_ResetTriggerByRow, ["arg1"] = this};
                                UIDropDownMenu_AddButton(info, 1);
                        end
                elseif level == 2 then
                        for i = 1, table.getn(groupdata) do
                                info = {["text"] = groupdata[i].name, ["func"] = Timers_MoveToGroup, ["arg1"] = timers_dropdown_row, ["arg2"] = i};
                                UIDropDownMenu_AddButton(info, 2);              
                        end
                end
        end
end

function TimersMenu_SetConfigSpam(arg,text)
        configdata.spamto = text;
        TimersMenu_SetEditBoxText(arg,text);
end     

function TimersMenu_SetEditBoxText(caller,text)
        getglobal(caller:GetParent():GetName().."Text"):SetText(text);
end

        
function Timers_TabControl(arg) -- Tab Control

         activeset = 0; -- Verschiebung für das Active Tab
        
        -- Erstes Tab Testen
        if arg == TimersMainFrameTabButton1 then        
                TimersMainFrameTabButton1MiddleDisabled:Show();
                TimersMainFrameTabButton1RightDisabled:Show();
                TimersMainFrameTabButton1LeftDisabled:Show();
                TimersMainFrameTabButton1Middle:Hide();
                TimersMainFrameTabButton1Right:Hide();
                TimersMainFrameTabButton1Left:Hide();           
                arg:SetPoint("TOPLEFT","TimersMainFrame","BOTTOMLEFT",2,0);
                activeset = 4;
                configdata.activetab = 1;
        else
                TimersMainFrameTabButton1MiddleDisabled:Hide();
                TimersMainFrameTabButton1RightDisabled:Hide();
                TimersMainFrameTabButton1LeftDisabled:Hide();
                TimersMainFrameTabButton1Middle:Show();
                TimersMainFrameTabButton1Right:Show();
                TimersMainFrameTabButton1Left:Show();
                TimersMainFrameTabButton1:SetPoint("TOPLEFT","TimersMainFrame","BOTTOMLEFT",2,4);
        end
        
        -- Tab 2 bis 5 setzen   
        for i = 2, 5 do
                if arg == getglobal("TimersMainFrameTabButton"..i) then
                        getglobal("TimersMainFrameTabButton"..i.."MiddleDisabled"):Show();
                        getglobal("TimersMainFrameTabButton"..i.."RightDisabled"):Show();
                        getglobal("TimersMainFrameTabButton"..i.."LeftDisabled"):Show();
                        getglobal("TimersMainFrameTabButton"..i.."Middle"):Hide();
                        getglobal("TimersMainFrameTabButton"..i.."Right"):Hide();
                        getglobal("TimersMainFrameTabButton"..i.."Left"):Hide();
                        getglobal("TimersMainFrameTabButton"..i):SetPoint("TOPLEFT",getglobal("TimersMainFrameTabButton"..(i-1)),"TOPRIGHT",0,-4);
                        activeset = 4;
                        configdata.activetab = i;
                else
                        getglobal("TimersMainFrameTabButton"..i.."MiddleDisabled"):Hide();
                        getglobal("TimersMainFrameTabButton"..i.."RightDisabled"):Hide();
                        getglobal("TimersMainFrameTabButton"..i.."LeftDisabled"):Hide();
                        getglobal("TimersMainFrameTabButton"..i.."Middle"):Show();
                        getglobal("TimersMainFrameTabButton"..i.."Right"):Show();
                        getglobal("TimersMainFrameTabButton"..i.."Left"):Show();
                        getglobal("TimersMainFrameTabButton"..i):SetPoint("TOPLEFT",getglobal("TimersMainFrameTabButton"..(i-1)),"TOPRIGHT",0,activeset);
                        activeset = 0;
                end
        end
        Timers_TabContentControl(); 
end

function Timers_TabContentControl()

        -- creating default window sys (timerframe)
        TimersMainFrame:SetBackdropBorderColor(1, 1, 1, 1);
        TimersMainFrame:SetBackdropColor(0,0, 0, 0.8);
        TimersMainFrameTitle:Show();
        TimersMainFrameScrollFrame:Show();
        TimersMainFrameCloseButton:Show();
        TimersMainFrameMenuButton:Show();
        TimersMainFrameMinimizeButton:Show();   
        TimersMainFrameSortButton1:Show();
        TimersMainFrameSortButton2:Show();
        TimersMainFrameToggleNameBoxButton:Show();
        TimersMainFrameScrollFrame:Show();
                
        for i = 2, 5 do
                getglobal("TimersMainFrameTabButton"..i):Show();
        end
                
        TimersMainFrameTabButton1Middle:SetAlpha(1);
        TimersMainFrameTabButton1Left:SetAlpha(1);
        TimersMainFrameTabButton1Right:SetAlpha(1);
                
        for i = 1, 10 do
                getglobal("TimersMainFrameTimerRow"..i):Hide();
                getglobal("TimersMainFrameTimerRow"..i.."GrpByPlaytime"):Hide();
                getglobal("TimersMainFrameTimerRow"..i.."GrpByPlaytimeTitle"):Hide();
                getglobal("TimersMainFrameTimerRow"..i.."GrpResetCnt"):Hide();
                getglobal("TimersMainFrameTimerRow"..i.."GrpResetCntTitle"):Hide();
                getglobal("TimersMainFrameTimerRow"..i.."GrpDeleteTimer"):Hide();                                       
                getglobal("TimersMainFrameTimerRow"..i.."GrpDeleteTimerTitle"):Hide();
                getglobal("TimersMainFrameTimerRow"..i.."GrpOnStartTitle"):Hide();      
                getglobal("TimersMainFrameTimerRow"..i.."DeleteButton"):Show();                         
                getglobal("TimersMainFrameTimerRow"..i.."Active"):Hide();
                getglobal("TimersMainFrameTimerRow"..i.."MenuButton"):SetText("!");
                getglobal("TimersMainFrameTimerRow"..i.."MenuButton"):Show();
                getglobal("TimersMainFrameTimerRow"..i.."EditBox1"):SetPoint("TOPLEFT","$parentMenuButton","TOPRIGHT",0,0);
                getglobal("TimersMainFrameTimerRow"..i.."Middle"):SetWidth(80+configdata.namessize);
                getglobal("TimersMainFrameTimerRow"..i.."EditBox1"):SetWidth(configdata.namessize-40);
                getglobal("TimersMainFrameTimerRow"..i.."Middle"):SetAlpha(0.8);
                getglobal("TimersMainFrameTimerRow"..i.."Left"):SetAlpha(0.8);
                getglobal("TimersMainFrameTimerRow"..i.."Right"):SetAlpha(0.8);
                getglobal("TimersMainFrameTimerRow"..i.."EditBox2"):SetPoint("TOPLEFT","$parentEditBox1","TOPRIGHT",20,0);      
                getglobal("TimersMainFrameTimerRow"..i.."EditBox2"):Show();     
                for j = 3, 5 do
                        getglobal("TimersMainFrameTimerRow"..i.."EditBox"..j):Hide();
                end
        end
        
        TimersMainFrame:SetWidth(130+configdata.namessize);
        TimersMainFrameScrollFrame:SetWidth(95+configdata.namessize);

        TimersMainFrameSortButton1:Show();
        TimersMainFrameSortButton1:SetWidth(configdata.namessize);
        TimersMainFrameSortButton2:Show();
        for i = 3, 5 do
                getglobal("TimersMainFrameSortButton"..i):Hide();
        end     
        
        TimersMainFrameConfig:Hide();
        TimersMainFrameHelp:Hide();
        TimersMainFrameTextFrame:Hide();        
        
        if configdata.activetab == 1 then
                Timers_SetTimerData();  
        elseif configdata.activetab == 2 then
                TimersMainFrame:SetBackdropBorderColor(0, 0, 0, 0);
                TimersMainFrame:SetBackdropColor(0, 0, 0, 0);
                TimersMainFrameTitle:Hide();
                TimersMainFrameMenuButton:Hide();
                TimersMainFrameCloseButton:Hide();
                TimersMainFrameMinimizeButton:Hide();   
                TimersMainFrameSortButton1:Hide();
                TimersMainFrameSortButton2:Hide();
                TimersMainFrameToggleNameBoxButton:Hide();
                
                for i = 2, 5 do
                        getglobal("TimersMainFrameTabButton"..i):Hide();
                end
                
                TimersMainFrameTabButton1Middle:SetAlpha(0);
                TimersMainFrameTabButton1Left:SetAlpha(0);
                TimersMainFrameTabButton1Right:SetAlpha(0);
                
                for i = 1, 10 do
                        getglobal("TimersMainFrameTimerRow"..i.."Middle"):SetAlpha(0);
                        getglobal("TimersMainFrameTimerRow"..i.."Left"):SetAlpha(0);
                        getglobal("TimersMainFrameTimerRow"..i.."Right"):SetAlpha(0);
                        getglobal("TimersMainFrameTimerRow"..i.."MenuButton"):Hide();
                        getglobal("TimersMainFrameTimerRow"..i.."DeleteButton"):Hide();                                         
                end
                Timers_SetTimerData();
        elseif configdata.activetab == 3 then
                TimersMainFrame:SetWidth(710);
                TimersMainFrameScrollFrame:SetWidth(675);
                for i = 3, 5 do
                        getglobal("TimersMainFrameSortButton"..i):Show();
                end
        
        TimersMainFrameSortButton1:SetWidth(200);
        
                for i = 1, 10 do
                        getglobal("TimersMainFrameTimerRow"..i.."Active"):Show();
                        getglobal("TimersMainFrameTimerRow"..i.."DeleteButton"):Hide(); 
                        getglobal("TimersMainFrameTimerRow"..i.."EditBox1"):SetPoint("TOPLEFT","$parentMenuButton","TOPRIGHT",20,0);                    
                        getglobal("TimersMainFrameTimerRow"..i.."Middle"):SetWidth(660);
                        getglobal("TimersMainFrameTimerRow"..i.."EditBox1"):SetWidth(160);
                        getglobal("TimersMainFrameTimerRow"..i.."EditBox2"):SetPoint("TOPLEFT","$parentEditBox1","TOPRIGHT",0,0);       
                        for j = 3, 5 do
                                getglobal("TimersMainFrameTimerRow"..i.."EditBox"..j):Show();
                        end
                end
                Timers_SetTriggerData();
        elseif configdata.activetab == 4 then
                for i = 1, 10 do
                        getglobal("TimersMainFrameTimerRow"..i):Hide(); 
                end
                TimersMainFrame:SetWidth(330);
                TimersMainFrameScrollFrame:Hide();
                TimersMainFrameMenuButton:Hide();
                TimersMainFrameSortButton1:Hide();
                TimersMainFrameSortButton2:Hide();
                TimersMainFrameConfig:Show();
        elseif configdata.activetab == 5 then
                for i = 1, 10 do
                        getglobal("TimersMainFrameTimerRow"..i):Hide(); 
                end
                TimersMainFrame:SetWidth(330);
                TimersMainFrameScrollFrame:Hide();
                TimersMainFrameMenuButton:Hide();
                TimersMainFrameSortButton1:Hide();
                TimersMainFrameSortButton2:Hide();
                TimersMainFrameHelp:Show();
        end                     
end 

function Timers_ShowHelp(nr)
        TimersMainFrameHelp:Hide();
        TimersMainFrameTextFrame:Show();
        if nr == 1 then
                TimersMainFrameHelpFrameText:SetText(TIMERS_LOC_HELP_CAT1);
        elseif nr == 2 then
                TimersMainFrameHelpFrameText:SetText(TIMERS_LOC_HELP_CAT2);
        elseif nr == 3 then
                TimersMainFrameHelpFrameText:SetText(TIMERS_LOC_HELP_CAT3);
        elseif nr == 4 then
                TimersMainFrameHelpFrameText:SetText(TIMERS_LOC_HELP_CAT4);
        elseif nr == 5 then
                TimersMainFrameHelpFrameText:SetText(TIMERS_LOC_HELP_CAT5);
        elseif nr == 6 then
                TimersMainFrameHelpFrameText:SetText(TIMERS_LOC_HELP_CAT6);
        elseif nr == 7 then
                TimersMainFrameHelpFrameText:SetText(TIMERS_LOC_HELP_CAT7);
        end             
end

function Timers_WindowControl() 
        TimersMainFrame:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", configdata.mainframeposx, configdata.mainframeposy);
        TimersNameBar:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", configdata.namebarposx , configdata.namebarposy);
        TimersMinimizedFrame:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", configdata.minimizedposx , configdata.minimizedposy);
        TimersTriggersConfigFrame:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", configdata.triggerconfposx , configdata.triggerconfposy);  
        if configdata.usenamebar and not (configdata.hidenamebar) then
                TimersNameBar:Show();
        else
                TimersNameBar:Hide();
        end
        Timers_MinimizedControl();
end

function Timers_ScaleControl()
        TimersMainFrame:SetScale(configdata.framescale/100);
        TimersNameBar:SetScale(configdata.framescale/100);
        TimersMinimizedFrame:SetScale(configdata.framescale/100);
end

function Timers_MinimizedControl()
        if configdata.minimized then
                TimersMainFrame:Hide();
                TimersMinimizedFrame:Show();
                if (not (configdata.titletext)) or configdata.titletext == "" then
                        TimersMinimizedFrame:SetWidth(100);
                else
                        TimersMinimizedFrame:SetWidth(207);
                end             
        else
                TimersMainFrame:Show();
                TimersMinimizedFrame:Hide();
        end     
end

function TimersConfig_ToggleNameBar()
        if(this:GetChecked() ~= nil) then
                TimersNameBar:Show();
                configdata.usenamebar = true;
        else 
                TimersNameBar:Hide();
                configdata.usenamebar = false;
        end
end

function Timers_ToggleNamebox()
        if(configdata.hidenamebar) then
                configdata.hidenamebar = nil;
                TimersNameBar:Show();
        else
                configdata.hidenamebar = true;
                TimersNameBar:Hide();
        end
end     

function Timers_ShowAdvancedConfig()
        trigger_edit = Timers_RowToTrigger(timers_dropdown_row+FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame));
        TimersTriggersConfigFrameNameInput:SetText(triggerdata[trigger_edit].name);
        TimersTriggersConfigFrameTimeInput:SetText(Timers_TimeToText(tonumber(Timers_GetFieldValue(triggerdata[trigger_edit],"time"))));
        TimersTriggersConfigFrameTextBox:SetText(triggerdata[trigger_edit].text);
        if triggerdata[trigger_edit].mode then
                TimersTriggersConfigFrameModeBox:SetText(triggerdata[trigger_edit].mode);
        else
                TimersTriggersConfigFrameModeBox:SetText(TIMERS_LOC_DEFAULT);
        end
        if triggerdata[trigger_edit].type then  
                TimersTriggersConfigFrameTypeBox:SetText(triggerdata[trigger_edit].type);
        else
                TimersTriggersConfigFrameTypeBox:SetText(TIMERS_LOC_DEFAULT);
        end     
        if triggerdata[trigger_edit].warnchannel then   
                TimersTriggersConfigFrameWarnChanBox:SetText(triggerdata[trigger_edit].warnchannel);    
        else
                TimersTriggersConfigFrameWarnChanBox:SetText(TIMERS_LOC_DEFAULT);               
        end
        TimersTriggersConfigFrameWarnTimeInput:SetText(Timers_GetFieldValue(triggerdata[trigger_edit],"prewarn"));      
        TimersTriggersConfigFrameWarnMessInput:SetText(Timers_GetFieldValue(triggerdata[trigger_edit],"warnmessage"));  
        if triggerdata[trigger_edit].channel then       
                TimersTriggersConfigFrameExpChanBox:SetText(triggerdata[trigger_edit].channel);
        else
                TimersTriggersConfigFrameExpChanBox:SetText(TIMERS_LOC_DEFAULT);
        end
        TimersTriggersConfigFrameExpMessInput:SetText(Timers_GetFieldValue(triggerdata[trigger_edit],"message"));       
        TimersTriggersConfigFrameThresholdInput:SetText(Timers_GetFieldValue(triggerdata[trigger_edit],"threshold"));   
        TimersTriggersConfigFrameCountInput:SetText(Timers_GetFieldValue(triggerdata[trigger_edit],"count"));   
        TimersTriggersConfigFrame:Show();
end


function TimersSlash_Reset()
        configdata = Timers_cloneTable(configdata_DEFAULT);
        TimersNameBarNameBox:SetText(configdata.namebartext);
        Timers_ScaleControl();
        Timers_WindowControl();
        Timers_TabContentControl();     
        Timers_PrintText(TIMERS_LOC_RESETTED);
end

function TimersSlash_Invoke(name)
        local NotSucc = true;
        for i = 1, table.getn(triggerdata) do
                if triggerdata[i].name == name then
                        Timers_StartTimer(triggerdata[i],nil);
                        Timers_PrintText(name..TIMERS_LOC_MSGINVOKED);
                        NotSucc = false;
                        timerUpdateFlag = true;
                end
        end
        if NotSucc then
                Timers_PrintText(TIMERS_LOC_NO_TRIGGERNAME);
        end
end


function TimersConfig_Reset()
        configdata = Timers_cloneTable(configdata_DEFAULT);
        configdata.activetab = 4;
        TimersNameBarNameBox:SetText(configdata.namebartext);
        Timers_ScaleControl();
        Timers_WindowControl();
        Timers_TabContentControl();
end

function TimersEdit_ToggleDisableAll()
        if configdata.alldisabled then
                configdata.alldisabled = false;
                Timers_PrintText(TIMERS_LOC_ALLTRIGGER_ENABLED);
        else
                configdata.alldisabled = true;
                Timers_PrintText(TIMERS_LOC_ALLTRIGGER_DISABLED);
        end
end

function Timers_SetSort(arg)
        if configdata.activetab == 1 then
                if not IsShiftKeyDown() then
                        if configdata.timersortascending then
                                configdata.timersortascending = false;
                        else
                                configdata.timersortascending = true;
                        end
                        configdata.timersort = arg;
                        table.sort(timerdata, Timers_CompareTimers);
                        timerUpdateFlag = true;
                else
                        Timers_SpamOnPress(arg);
                end
        else
                if configdata.triggersortascending then
                        configdata.triggersortascending = false;
                else
                        configdata.triggersortascending = true;
                end
                configdata.triggersort = arg;
                table.sort(triggerdata, Timers_CompareTriggers);
                Timers_SetTriggerData();
        end
        if not IsShiftKeyDown() then
                Timers_UpdateSortArrows();
        end
end

function Timers_UpdateSortArrows()
        for i = 1, 5 do
                getglobal("TimersMainFrameSortButton"..i.."Arrow"):Hide();
        end
        if configdata.activetab == 1 or configdata.activetab == 2 then
                getglobal("TimersMainFrameSortButton"..configdata.timersort.."Arrow"):Show();
        else
                getglobal("TimersMainFrameSortButton"..configdata.triggersort.."Arrow"):Show();
        end
end

function Timers_MsgSendTo(msg, channel)
        if channel == TIMERS_LOC_RAID or channel == TIMERS_LOC_CTRAID then
                if GetNumRaidMembers() == 0 then
                        msg = TIMERS_LOC_NOT_IN_RAID..": "..msg;
                        channel = TIMERS_LOC_SELF;
                elseif channel == TIMERS_LOC_RAID then
                        SendChatMessage(msg,"RAID");
                else
                        CT_RA_AddMessage("MS "..msg);
                end
        end
        if channel == TIMERS_LOC_PARTY then
                if GetNumPartyMembers() == 0 then
                        msg = TIMERS_LOC_NOT_IN_PARTY..": "..msg;
                        channel = TIMERS_LOC_SELF;
                else
                        SendChatMessage(msg,"PARTY");
                end
        end
        if channel == TIMERS_LOC_SELF then
                Timers_PrintText(msg);
        end
        if channel == TIMERS_LOC_REPLY then
                SendChatMessage(msg,"WHISPER",nil,ChatEdit_GetLastTellTarget(ChatFrameEditBox));
        end
        if channel == TIMERS_LOC_OFFICER then
                SendChatMessage(msg,"OFFICER");
        end
end

function TimersSend_Timer(row, channel)
        local Offset = FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame);
        TimersSend_TimerByNr(row+Offset,channel);
end

function TimersSend_TimerByNr(i,channel)
        if not (Timers_GetFieldValue(triggerdata[Timers_TriggerNameToNumber(timerdata[i].trigger)],"mode") == TIMERS_LOC_INC) then
                msg = timerdata[i].name.." "..TIMERS_LOC_EXPIRES_IN..": "..Timers_TimeToText(timerdata[i].time-Timers_GetLocalTime());
        else
                msg = timerdata[i].name.." "..TIMERS_LOC_IS_CURRENTLY_AT..": "..Timers_TimeToText(Timers_GetLocalTime()-timerdata[i].time);
        end             
        if not channel then
                channel = Timers_GetFieldValue(triggerdata[Timers_TriggerNameToNumber(timerdata[i].trigger)],"channel");
        end
        Timers_MsgSendTo(msg, channel);
end

function TimersSend_AllTimer(channel)
        for i = 1, table.getn(timerdata) do
                TimersSend_TimerByNr(i,channel);
        end
end             

function TimersSend_ToActive(msg)
        local channel = ChatFrameEditBox.chatType;      
        if channel == "WHISPER" then
                SendChatMessage(msg,"WHISPER",nil,ChatFrameEditBox.tellTarget);
        else
                SendChatMessage(msg,ChatFrameEditBox.chatType);
        end
end

function Timers_SpamOnPress(arg)
        if arg == 1 then
                if configdata.spamonpress < table.getn(timerdata) then
                        max = configdata.spamonpress
                else
                        max = table.getn(timerdata)
                end
                for i = 1, max do
                        if not (Timers_GetFieldValue(triggerdata[Timers_TriggerNameToNumber(timerdata[i].trigger)],"mode") == TIMERS_LOC_INC) then
                                msg = timerdata[i].name.." "..TIMERS_LOC_EXPIRES_IN..": "..Timers_TimeToText(timerdata[i].time-Timers_GetLocalTime());
                        else
                                msg = timerdata[i].name.." "..TIMERS_LOC_IS_CURRENTLY_AT..": "..Timers_TimeToText(Timers_GetLocalTime()-timerdata[i].time);
                        end                     
                        TimersSend_ToActive(msg);
                end
        else
                for i = 1, table.getn(timerdata) do
                        if timerdata[i].time-Timers_GetLocalTime() < configdata.spamonpress*60 then
                                if not (Timers_GetFieldValue(triggerdata[Timers_TriggerNameToNumber(timerdata[i].trigger)],"mode") == TIMERS_LOC_INC) then
                                        msg = timerdata[i].name.." "..TIMERS_LOC_EXPIRES_IN..": "..Timers_TimeToText(timerdata[i].time-Timers_GetLocalTime());
                                else
                                        msg = timerdata[i].name.." "..TIMERS_LOC_IS_CURRENTLY_AT..": "..Timers_TimeToText(Timers_GetLocalTime()-timerdata[i].time);
                                end             
                                TimersSend_ToActive(msg);
                        end
                end
        end
end     

function Timers_SpamOnWhisper(arg,name)
        if arg == nil or arg == "" then
                arg = configdata.spamonpress;
        else
                arg = tonumber(arg);
        end
        local NotSend = true;
        for i = 1, table.getn(timerdata) do
                if timerdata[i].time-Timers_GetLocalTime() < arg*60 then
                        if not (Timers_GetFieldValue(triggerdata[Timers_TriggerNameToNumber(timerdata[i].trigger)],"mode") == TIMERS_LOC_INC) then
                                msg = timerdata[i].name.." "..TIMERS_LOC_EXPIRES_IN..": "..Timers_TimeToText(timerdata[i].time-Timers_GetLocalTime());
                        else
                                msg = timerdata[i].name.." "..TIMERS_LOC_IS_CURRENTLY_AT..": "..Timers_TimeToText(timerdata[i].time-Timers_GetLocalTime());
                        end             
                        SendChatMessage(msg,"WHISPER",nil,name);
                        NotSend = false;
                end
        end
        if NotSend then
                SendChatMessage(TIMERS_LOC_NO_TIMERS_EXPIRING,"WHISPER",nil,name);
        end
end

function Timers_GetLocalTime()
        local strtime = date("%j%H%M%S");
        local time = tonumber(string.sub(strtime,-2));
        time = time + tonumber(string.sub(strtime,-4,-3)) * 60;                 
        time = time + tonumber(string.sub(strtime,-6,-5)) * 3600;       
        time = time + tonumber(string.sub(strtime,-9,-7)) * 86400;
        return time;
end                      

-- OnEvent Functions

function Timers_OnEvent(event)
        if event == "VARIABLES_LOADED" then
                if state and state.triggerList then
                        Timers_ImportTrigger();
                end
                Timers_VersionCorrections();
                Timers_CheckForNewTrigger();
                Timers_CorrectTimerData();
                Timers_SetSort(configdata.timersort);
                Timers_WindowControl();
                Timers_TabControl(getglobal("TimersMainFrameTabButton"..configdata.activetab));
          TimersNameBarNameBox:SetText(configdata.namebartext);
        elseif event == "CHAT_MSG_WHISPER" then
                if (string.find(arg1, "showtime") ~= nil) then
                        local _,n = string.find(arg1,"showtime");
                        n = tonumber(string.sub(arg1, n+2));
                        Timers_SpamOnWhisper(n,arg2);
                end
        elseif event == "TRAINER_CLOSED" or event == "SPELLS_CHANGED" then
                Timers_CreateIconArray();       
        else
                local text;
                if (event == "SPELLCAST_START" or event == "SPELLCAST_STOP" or event == "SPELLCAST_FAILED" or event == "SPELLCAST_INTERRUPTED") then
                        Timers_SpellEvent(event,arg1,arg2);
                else
                        if (event == "CHAT_MSG_MONSTER_EMOTE") then
                                text = arg2.." "..arg1;
                        elseif (event == "ZONE_CHANGED_NEW_AREA" or event == "ZONE_CHANGED" or event == "ZONE_CHANGED_INDOORS") then
                                Timers_ZoneEvent();
                        elseif (event ~= nil) then
                                text = arg1;
                        end
                        if text then
                                Timers_EventParser(event,text);
                        end
                end
        end
end 

function Timers_OnLoad()

        Timers_OldSpellHook = CastSpell;
        Timers_OldSpellHookByName = CastSpellByName;
        Timers_OldUseAction = UseAction;
        CastSpell = Timers_SpellHook;
        CastSpellByName = Timers_SpellHookByName;
        UseAction = Timers_UseActionHook;
        this:SetBackdropColor(0.0, 0.0, 0.0, 0.8);
        
        this:RegisterEvent("CHAT_MSG_SPELL_TRADESKILLS");
        this:RegisterEvent("VARIABLES_LOADED");
        this:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_CREATURE_DAMAGE");
        this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_CREATURE_BUFFS");
        this:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_CREATURE_BUFF");
        this:RegisterEvent("CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE");
        this:RegisterEvent("CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF");
        this:RegisterEvent("CHAT_MSG_MONSTER_EMOTE");
        this:RegisterEvent("CHAT_MSG_MONSTER_SAY");
        this:RegisterEvent("CHAT_MSG_MONSTER_YELL");
        this:RegisterEvent("CHAT_MSG_MONSTER_WHISPER");
        this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE");
        this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_BUFFS");
        this:RegisterEvent("CHAT_MSG_SPELL_AURA_GONE_OTHER");
        this:RegisterEvent("CHAT_MSG_COMBAT_HOSTILE_DEATH");
        this:RegisterEvent("CHAT_MSG_WHISPER");
        this:RegisterEvent("CHAT_MSG_LOOT");
        this:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_SELF_HITS");
        this:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_SELF_MISSES");
        this:RegisterEvent("ZONE_CHANGED_NEW_AREA");
        this:RegisterEvent("ZONE_CHANGED_INDOORS");
        this:RegisterEvent("ZONE_CHANGED");
        this:RegisterEvent("SPELLCAST_START");
        this:RegisterEvent("SPELLCAST_STOP");
        this:RegisterEvent("SPELLCAST_FAILED");
        this:RegisterEvent("SPELLCAST_INTERRUPTED");
        this:RegisterEvent("TRAINER_CLOSED");
        this:RegisterEvent("SPELLS_CHANGED");
        
        SlashCmdList["TIMERCOMMANDS"] = Timers_SlashCommandHandler;
        SLASH_TIMERCOMMANDS1 = "/atimer";
        SLASH_TIMERCOMMANDS2 = "/ati";
        triggerdata_DEFAULT = Timers_cloneTable(triggerdata);
        configdata_DEFAULT = Timers_cloneTable(configdata);
        groupdata_DEFAULT = Timers_cloneTable(groupdata);
end

function Timers_CheckForOnce(name)
        for i = 1, table.getn(timerdata) do
                if timerdata[i].trigger == name then
                        return false;
                end
        end
        return true;
end

function Timers_CheckForOnceGroup(name)
        for i = 1, table.getn(timerdata) do
                if triggerdata[Timers_TriggerNameToNumber(timerdata[i].trigger)].group == name then
                        return false;
                end
        end
        return true;
end

function Timers_ZoneEvent(event)
        if event == "ZONE_CHANGED_NEW_AREA" then
                currentZone = GetZoneText();
        else
                currentZone = GetSubZoneText();
        end
        for i = 1, table.getn(triggerdata) do
                if string.find(triggerdata[i].text,currentZone) and string.find(triggerdata[i].text,TIMERS_LOC_ZONEENTER) then
                        Timers_EventParser(event,triggerdata[i].text);
                end
        end
end

function Timers_SpellEvent(event,arg1,arg2)
        if event == "SPELLCAST_FAILED" or event == "SPELLCAST_INTERRUPTED" then
                currSpellCast = nil;
        elseif event == "SPELLCAST_STOP" then
                if currSpellCast then
                        Timers_EventParser(event,currSpellCast.text);
                        currSpellCast = nil;
                end     
        end
end

function Timers_ParseSpellName(name)
        Timers_PrintDebug("Action: "..name);
        for i = 1, table.getn(triggerdata) do
                if string.find(triggerdata[i].text, TIMERS_LOC_SPELL_CAST) and string.find(triggerdata[i].text, name) then
                        currSpellCast = triggerdata[i];
                end
        end
end     

function Timers_SpellHook(ID,book)
 Timers_ParseSpellName(GetSpellName(ID,book));
 Timers_OldSpellHook(ID,book);
end

function Timers_SpellHookByName(name)
        Timers_ParseSpellName(name);
        Timers_OldSpellHookByName(name);
end

function Timers_UseActionHook(slot,arg1,arg2)
        if (not (GetActionText(slot))) and IconArray[GetActionTexture(slot)] then
                Timers_ParseSpellName(IconArray[GetActionTexture(slot)]);
        end
        Timers_OldUseAction(slot,arg1,arg2);
end
                                
function Timers_EventParser(event,msg)
        for i = 1, table.getn(triggerdata) do
                if string.find(msg,triggerdata[i].text) then
                        if (not (triggerdata[i].lastinvoked) or triggerdata[i].lastinvoked+tonumber(Timers_GetFieldValue(triggerdata[i],"threshold"))<Timers_GetLocalTime()) and not (triggerdata[i].inactive or groupdata[Timers_GroupNameToNumber(triggerdata[i].group)].inactive) then
                                if Timers_GetFieldValue(triggerdata[i],"type") == TIMERS_LOC_MULTIPLE then
                                        Timers_StartTimer(triggerdata[i],msg);
                                elseif Timers_GetFieldValue(triggerdata[i],"type") == TIMERS_LOC_ONCE and Timers_CheckForOnce(triggerdata[i].name) then
                                        Timers_StartTimer(triggerdata[i],msg);
                                elseif Timers_GetFieldValue(triggerdata[i],"type") == TIMERS_LOC_ONCEGROUP and Timers_CheckForOnceGroup(triggerdata[i].group) then
                                        Timers_StartTimer(triggerdata[i],msg);
                                elseif Timers_GetFieldValue(triggerdata[i],"type") == TIMERS_LOC_PAUSE then
                                        if Timers_CheckForOnceGroup(triggerdata[i].group) then
                                                Timers_StartTimer(triggerdata[i],msg);
                                        else
                                                for j = 1, table.getn(timerdata) do
                                                        if triggerdata[Timers_TriggerNameToNumber(timerdata[j].trigger)].group == triggerdata[i].group then
                                                                TimersEdit_TogglePaused(nil,j);
                                                                Timers_WarnOnly(triggerdata[i],msg,timerdata[j].time);
                                                        end
                                                end
                                        end
                                elseif Timers_GetFieldValue(triggerdata[i],"type") == TIMERS_LOC_STOP then
                                        for j = 1, table.getn(timerdata) do
                                                if triggerdata[Timers_TriggerNameToNumber(timerdata[j].trigger)].group == triggerdata[i].group then
                                                        TimersEdit_StopTimer(arg,j);
                                                end
                                        end                                             
                                elseif Timers_GetFieldValue(triggerdata[i],"type") == TIMERS_LOC_WARNONLY then
                                        Timers_WarnOnly(triggerdata[i],msg);
                                end     
                        end
                        timerUpdateFlag = true;
                end
        end
end

function Timers_StartTimer(trigger,msg)
        trigger.lastinvoked = Timers_GetLocalTime();
        if trigger.count then
                trigger.count = trigger.count + 1;
        else
                trigger.count = 1;
        end
        if configdata.usenamebar then
                Timers_StartByEvent(configdata.namebartext,trigger,msg);
        else
                if not (StaticPopup_Visible(TIMERS_MESSAGE_POPUP)) then
                        StaticPopupDialogs["TIMERS_MESSAGE_POPUP"].text = TIMERS_LOC_NEW_TIMER_NAME;
                        StaticPopupDialogs["TIMERS_MESSAGE_POPUP"].arg1 = trigger;
                        StaticPopupDialogs["TIMERS_MESSAGE_POPUP"].arg2 = msg;
                        Timers_OnMessageBoxAccept = Timers_StartByEvent;
                        StaticPopup_Show("TIMERS_MESSAGE_POPUP");
                elseif trigger.type == TIMERS_LOC_PAUSE then
                        if Timers_OnMessageBoxAccept == Timers_StartPausedByEvent then
                                Timers_OnMessageBoxAccept = Timers_StartByEvent;
                        else
                                Timers_OnMessageBoxAccept = Timers_StartPausedByEvent;
                        end
                end                     
        end     
end

function Timers_StartByEvent(name,trigger,msg)
        name = string.gsub(name,"!count",Timers_GetFieldValue(trigger,"count"));
        name = string.gsub(name,"!coord",TimersString_Replace_Coord());
        name = string.gsub(name,"!trigger",trigger.name);
        if Timers_GetFieldValue(trigger,"mode") == TIMERS_LOC_INC then          
                table.insert(timerdata, {name=name, time=Timers_GetLocalTime()-tonumber(Timers_GetFieldValue(trigger,"time")), trigger=trigger.name, msg = msg});
        else    
                table.insert(timerdata, {name=name, time=tonumber(Timers_GetFieldValue(trigger,"time"))+Timers_GetLocalTime(), trigger=trigger.name, msg = msg});
        end
        timerUpdateFlag = true;
end

function Timers_StartPausedByEvent(name,trigger,msg)                            
        name = string.gsub(name,"!count",Timers_GetFieldValue(trigger,"count"));
        name = string.gsub(name,"!coord",TimersString_Replace_Coord());
        name = string.gsub(name,"!trigger",trigger.name);
        if Timers_GetFieldValue(trigger,"mode") == TIMERS_LOC_INC then          
                table.insert(timerdata, {name=name, time=Timers_GetLocalTime()-tonumber(Timers_GetFieldValue(trigger,"time")), trigger=trigger.name, msg = msg, paused = Timers_GetLocalTime()});
        else    
                table.insert(timerdata, {name=name, time=tonumber(Timers_GetFieldValue(trigger,"time"))+Timers_GetLocalTime(), trigger=trigger.name, msg = msg, paused = Timers_GetLocalTime()});
        end
        timerUpdateFlag = true;
end
        
function Timers_OnUpdate(arg1)
        timeSinceUpdate = timeSinceUpdate + arg1;
        if (timeSinceUpdate > 0.25) then
                if (not UnitAffectingCombat("player")) and inCombat then
                        inCombat = false;
                        Timers_EventParser(nil,TIMERS_LOC_COMBATSTOP);
                end
                if UnitAffectingCombat("player") and not inCombat then
                        inCombat = true;
                        Timers_EventParser(nil,TIMERS_LOC_COMBATSTART);
                end
                if configdata.activetab == 1 or configdata.activetab == 2 then 
                        if timerUpdateFlag then 
                                table.sort(timerdata,Timers_CompareTimers);             
                                Timers_SetTimerData();          
                                timerUpdateFlag = false;
                        end     
                        Timers_UpdateTimes();
                end
                if timeIsCorrect then
                        TimerscurrentTime = Timers_GetLocalTime();
                end
                if TimersMainFrame:GetScale() ~= (configdata.framescale/100) then
                        Timers_ScaleControl();
                        -- Timers_WindowControl();
                end
                Timers_UpdateTitle();
                Timers_CheckWarnAllTimers();
                timeSinceUpdate = 0;
        end
end

function TimersMainFrame_OnScroll()
        if configdata.activetab == 1 then
                Timers_SetTimerData();
        elseif configdata.activetab == 3 then
                Timers_SetTriggerData();
        end
end

function TimersFrame_ToggleMinimized()
        if configdata.minimized then
                configdata.minimized = false;
        else
                configdata.minimized = true;
        end
        Timers_MinimizedControl();
end

function Timers_TriggerMenuButton()
        if configdata.activetab == 3 and not getglobal(this:GetParent():GetName().."EditBox2"):IsVisible() then
                local i = Timers_GetRow(this) + FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame);
                local k = Timers_RowToGroup(i);
                if groupdata[k].fold then
                        groupdata[k].fold = false;
                else
                        groupdata[k].fold = true;
                end
                Timers_SetTriggerData();
        else
                ToggleDropDownMenu(1, nil, getglobal(this:GetParent():GetName().."DropDownMenu"), this, 0, 0);
        end
end

function Timers_ToggleFoldAll()
        local fold = 0;
        local unfold = 0;
        for i = 1, table.getn(groupdata) do
                if groupdata[i].fold then
                        fold = fold + 1;
                else
                        unfold = unfold + 1;
                end
        end
        local set;
        if fold > unfold then
                set = false;
        else
                set = true;
        end
        for i = 1, table.getn(groupdata) do
                groupdata[i].fold = set;
        end
        Timers_SetTriggerData();
end

function Timers_ToggleActiveAll()
        local active = 0;
        local inactive = 0;
        for i = 1, table.getn(triggerdata) do
                if triggerdata[i].inactive then
                        inactive = inactive + 1;
                else
                        active = active + 1;
                end
        end
        local set;
        if inactive > active then
                set = false;
        else
                set = true;
        end
        for i = 1, table.getn(groupdata) do
                groupdata[i].inactive = set;
        end
        for i = 1, table.getn(triggerdata) do
                triggerdata[i].inactive = set;
        end
        Timers_SetTriggerData();
end

function Timers_ResetAllCnt()
        for i = 1, table.getn(timerdata) do
                timerdata[i].count = 0;
        end
        Timers_SetTriggerData();
end

function Timers_ResetCnt(arg)
        local i = Timers_GetRow(arg) + FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame);
        triggerdata[Timers_RowToTrigger(i)].count = "0";
        Timers_SetTriggerData();
end

function Timers_DeleteTrigger(arg)
        local i = Timers_GetRow(arg) + FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame);
        table.remove(triggerdata,Timers_RowToTrigger(i));
        Timers_SetTriggerData();
end



-- System functions

function Timers_CompareTimers(item1, item2)
        if configdata.timersort == 1 then       
                if configdata.timersortascending then
                        return item1.name < item2.name;
                else
                        return item1.name > item2.name;
                end
        elseif configdata.timersort == 2 then
                if configdata.timersortascending then
                        return tonumber(item1.time) < tonumber(item2.time);
                else
                        return tonumber(item1.time) > tonumber(item2.time);
                end
        end             
end

function Timers_CompareTriggers(item1, item2)
        if configdata.triggersort == 1 then     
                return Timers_SortByText(item1,item2,"name");
        elseif configdata.triggersort == 2 then
                return Timers_SortByNumber(item1,item2,"time");
        elseif configdata.triggersort == 3 then
                return Timers_SortByNumber(item1, item2,"prewarn");
        elseif configdata.triggersort == 4 then
                return Timers_SortByText(item1,item2,"text");
        elseif configdata.triggersort == 5 then
                return Timers_SortByText(item1,item2,"message");
        elseif configdata.triggersort == 6 then
                return Timers_SortByText(item1,item2,"channel");
        elseif configdata.triggersort == 7 then
                return Timers_SortByNumber(item1,item2,"count");
        elseif configdata.triggersort == 8 then
                return Timers_SortByNumber(item1,item2,"threshold");
        elseif configdata.triggersort == 9 then
                return Timers_SortByText(item1,item2,"type");
        elseif configdata.triggersort == 10 then
                return Timers_SortByText(item1,item2,"mode");
        end                                                     
end

function Timers_CompareGroups(item1, item2)
        return item1.name < item2.name;
end

function Timers_SortByNumber(item1,item2,field)
        if not tonumber(item1[field]) or not tonumber(item2[field]) then
                if not tonumber(item1[field]) and not tonumber(item2[field]) then
                        return false;
                elseif not tonumber(item1[field]) then
                        if configdata.triggersortascending then
                                return tonumber(Timers_GetDefaultValue(field)) < tonumber(item2[field]);
                        else
                                return tonumber(Timers_GetDefaultValue(field)) > tonumber(item2[field]);
                        end
                else
                        if configdata.triggersortascending then
                                return tonumber(item1[field]) < tonumber(Timers_GetDefaultValue(field));
                        else
                                return tonumber(item1[field]) > tonumber(Timers_GetDefaultValue(field));
                        end
                end                                             
        elseif configdata.triggersortascending then                             
                return tonumber(item1[field]) < tonumber(item2[field]);
        else
                return tonumber(item1[field]) > tonumber(item2[field]);
        end
end

function Timers_SortByText(item1,item2,field)
        if not item1[field] or not item2[field] then
                if not item1[field] and not item2[field] then
                        return false;
                elseif not item1[field] then
                        if configdata.triggersortascending then
                                return Timers_GetDefaultValue(field) < item2[field];
                        else
                                return Timers_GetDefaultValue(field) > item2[field];
                        end
                elseif configdata.triggersortascending then
                        return item1[field] < Timers_GetDefaultValue(field);
                else
                        return item1[field] > Timers_GetDefaultValue(field);
                end
        else
                if configdata.triggersortascending then
                        return item1[field] < item2[field];
                else
                        return item1[field] > item2[field];
                end
        end                                                                             
end

function Timers_DeleteGroup(nr)
        local hasTrigger = false;
        for i = 1, table.getn(triggerdata) do
                if triggerdata[i].group == groupdata[nr].name then
                        hasTrigger = true;
                        triggerdata[i].fromGroup = true;
                end
        end
        table.remove(groupdata, nr);
        if hasTrigger then
                StaticPopupDialogs["TIMERS_ACCEPT_POPUP"].text = TIMERS_LOC_DELETE_GROUP_NOT_EMPTY;
                Timers_OnAcceptBoxButton = Timers_SetNewGroupByBox;
                StaticPopup_Show("TIMERS_ACCEPT_POPUP");        
        else    
                Timers_SetTriggerData();
        end
end

function Timers_TextToTime(text)
        local i = 0;
        local mul = 1;
        local time = 0;
        local minus = false;
        if string.sub(text,1,1) == "-" then
                minus = true;
                text = string.sub(text,2);
        end
        while string.find(text,":") do
                Pos = string.find(text,":",-3);
                time = time + mul*tonumber(string.sub(text,Pos+1));
                text = string.sub(text,1,Pos-1);
                mul = mul*60;
                i=i+1;
        end
        if i == 3 then 
                mul = 86400;
        end
        time = time + mul*tonumber(text);       
        if minus then
                time = -time;
        end
        return time;    
end

function Timers_GetRow(arg)
        local i = 10;
        while i > 0 do
                if string.find(arg:GetName(),"Row"..i) then
                        return i;
                end
                i = i - 1;
        end
end

function Timers_ParseArguments(msg)
        local args = {};
        local tmp = {};

        -- Find all space delimited words.
        for value in string.gfind(msg, "[^ ]+") do
                table.insert(tmp, value);
        end
        
        -- Make a pass through the table, and concatenate all words that have quotes.
        local quoteOpened = false;
        local quotedArg = "";
        for i = 1, table.getn(tmp) do
                if (string.find(tmp[i], "\"") == nil) then
                        if (quoteOpened) then
                                quotedArg = quotedArg.." "..string.gsub(tmp[i], "\"", "");
                        else
                                table.insert(args, tmp[i]);
                        end
                else
                        for value in string.gfind(tmp[i], "\"") do
                                quoteOpened = not quoteOpened;
                        end

                        if (quoteOpened) then
                                quotedArg = string.gsub(tmp[i], "\"", "");
                        else
                                if (string.len(quotedArg) > 0) then
                                        quotedArg = quotedArg.." "..string.gsub(tmp[i], "\"", "");
                                else
                                        quotedArg = string.gsub(tmp[i], "\"", "");
                                end
                                
                                table.insert(args, quotedArg);
                                quotedArg = "";
                        end
                end
        end
        
        if (string.len(quotedArg) > 0) then
                table.insert(args, quotedArg);
        end
        
        return args;
end

function Timers_SlashCommandHandler(msg)
        local command;
        local args;

        args = Timers_ParseArguments(msg);

        if (args[1] ~= nil) then
                command = string.lower(args[1]);
        end     

        if (command == "add") and (args[2] ~= nil and args[3] ~=nil) then
                Timers_add(args[2], args[3], args[4]);
        elseif (command == "reset") then
                TimersSlash_Reset();
        elseif (command == "invoke" and args[2] ~= nil) then
                TimersSlash_Invoke(args[2]);            
        elseif (command == "show") then
                ShowUIPanel(TimersMainFrame);
        elseif (command == "debug") then
                Timers_ToggleDebug()
        end             
end

function Timers_ShowMainPanel()
        ShowUIPanel(TimersMainFrame);
        if configdata.minimized then
                TimersFrame_ToggleMinimized();
        end
end

function Timers_PrintDebug(text)
        if Timers_Debug then
                Timers_PrintText("[DEBUG] "..text);
        end
end

function Timers_ToggleDebug()
        if Timers_Debug then
                Timers_Debug = false;
        else
                Timers_Debug = true;
        end
end

function Timers_PrintText(text)
        DEFAULT_CHAT_FRAME:AddMessage("|cFFFFFF00[Timers]: "..text.."|r");
end

function Timers_TimeToText(time)
        local TIME_FORMAT = "%02d:%02d:%02d";
        local TIME_FORMAT_D = "%02d:%02d:%02d:%02d";
        local absTime = math.abs(time);

        local days=0;
        local hours = absTime / 3600;
        local minutes = math.mod(absTime / 60, 60);
        local seconds = math.mod(absTime, 60);
        
        if(hours>=24) then
                days = hours/24;
                hours = math.mod(hours, 24);
        end

        if (time >= 0) then
                if (days>0) then
                        return format(TIME_FORMAT_D, days, hours, minutes, seconds);
                else
                        return format(TIME_FORMAT, hours, minutes, seconds);
                end
        else
                return format("-"..TIME_FORMAT, hours, minutes, seconds);
        end
end

function Timers_GetDefaultValue(field)
        if field == "text" then
                return " ";
        end
        for i = 1, table.getn(triggerdata) do
                if triggerdata[i].name == "default" then
                        return triggerdata[i][field];
                end
        end
end

-- Core Functions

function Timers_AddGroup()
        StaticPopupDialogs["TIMERS_MESSAGE_POPUP"].text = TIMERS_LOC_NEW_GROUP_NAME;
        Timers_OnMessageBoxAccept = Timers_GetNewGroupName;
        StaticPopup_Show("TIMERS_MESSAGE_POPUP");
end

function Timers_AddTrigger()
        table.insert(triggerdata, {["name"] = "New Trigger", ["text"] = TIMERS_LOC_EMPTYTEXT, ["isnotdefault"] = true});
        groupdata[Timers_GroupNameToNumber(TIMERS_LOC_NOGROUP)].fold = false;
        Timers_SetTriggerData();
end

function Timers_ResetAllTrigger()
        StaticPopupDialogs["TIMERS_ACCEPT_POPUP"].text = TIMERS_LOC_DELETE_ALL_NON_DEFAULT;
        Timers_OnAcceptBoxButton = Timers_ResetAllTriggerMsg;
        StaticPopup_Show("TIMERS_ACCEPT_POPUP");
end

function Timers_ResetAllTriggerMsg(nondefault)
        if nondefault then
                triggerdata = {};
        end
        for i = 1, table.getn(triggerdata_DEFAULT) do
                Timers_ResetByTrigger(triggerdata_DEFAULT[i]);
        end
        table.sort(triggerdata,Timers_CompareTriggers);
        Timers_SetTriggerData();
end     

function Timers_ResetTriggerByRow(arg)
        local trigger = triggerdata_DEFAULT[Timers_TriggerNameToDefaultNumber(triggerdata[Timers_RowToTrigger(Timers_GetRow(arg)+FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame))].name)];
        Timers_ResetByTrigger(trigger);
        Timers_SetTriggerData();
end

function Timers_ResetByTrigger(trigger)
        local j = table.getn(triggerdata);
        while j > 0 do
                if triggerdata[j].name == trigger.name then
                        table.remove(triggerdata,j); 
                end
                j = j - 1;
        end
        table.insert(triggerdata,Timers_cloneTable(trigger));   
end

function Timers_cloneTable(t)            
  local new = {};             
  local i, v = next(t, nil);  
  while i do
                if type(v)=="table" then 
                        v=Timers_cloneTable(v);
                end
    new[i] = v;
    i, v = next(t, i);        
  end
  return new;
end

function Timers_GetNewGroupName(text)
        table.insert(groupdata, {["name"] = text, ["isnotdefault"] = true});
        Timers_SetTriggerData();
end

function Timers_SetNewGroupByBox(state)
        local i = table.getn(triggerdata);
        while i > 0 do
                if triggerdata[i].fromGroup then
                        if state then
                                table.remove(triggerdata,i);
                        else
                                triggerdata[i].group = nil;
                                triggerdata[i].fromGroup = nil;
                        end
                end
        i = i - 1;
        end
        Timers_SetTriggerData();
end 

function Timers_SetTriggerData()
        table.sort(groupdata,Timers_CompareGroups);
        table.sort(timerdata,Timers_CompareTimers);
        local group;
        -- create Pointer list
        Timers_Init_TriggerPointer();
        local Max = 0
        for i = 1, table.getn(triggerPointer) do
                if triggerPointer[i] then
                        Max = Max + 1;
                end
        end
        for i = 1, table.getn(triggerdata) do
                group = Timers_GroupNameToNumber(triggerdata[i].group);
                if(not(groupdata[group].fold) and not((groupdata[group].inactive or triggerdata[i].inactive) and configdata.hideinactive)) then
                        table.insert(triggerPointer[group],i);
                        Max = Max + 1;
                end 
        end     
        FauxScrollFrame_Update(TimersMainFrameScrollFrame, Max, 10, 20);
        Timers_Print_TriggerPointer();
end     

function Timers_Print_TriggerPointer()
        local Offset = FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame);
        local Alli = 1;
        for i = 1, table.getn(triggerPointer) do
                if triggerPointer[i] then
                        if Alli > Offset and Alli - Offset <= 10 then
                                getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."EditBox1"):SetText("--- "..groupdata[i].name.." ---");
                                getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."EditBox1"):SetTextColor(0.2,0.2,1,1);
                                getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."GrpByPlaytime"):Show();
                                getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."GrpByPlaytime"):SetChecked(groupdata[i].byplaytime);
                                getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."GrpByPlaytimeTitle"):Show();
                                getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."GrpResetCnt"):Show();
                                getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."GrpResetCnt"):SetChecked(groupdata[i].onstartreset);
                                getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."GrpResetCntTitle"):Show();
                                getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."GrpDeleteTimer"):Show();
                                getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."GrpDeleteTimer"):SetChecked(groupdata[i].onstartdelete);                           
                                getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."GrpDeleteTimerTitle"):Show();
                                getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."GrpOnStartTitle"):Show();
                                getglobal("TimersMainFrameTimerRow"..(Alli-Offset)):Show();
                                if groupdata[i].inactive then
                                        getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."Active"):SetChecked(false);
                                else
                                        getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."Active"):SetChecked(true);
                                end
                                if groupdata[i].fold then
                                        getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."MenuButton"):SetText("+");
                                else
                                        getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."MenuButton"):SetText("-");
                                end
                                for j = 2, 5 do
                                        getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."EditBox"..j):Hide();
                                end
                        end                                                                                                     
                        Alli = Alli + 1;
                        for j = 1, table.getn(triggerPointer[i]) do
                                if Alli > Offset and Alli - Offset <= 10 then
                                        getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."EditBox1"):SetText(triggerdata[triggerPointer[i][j]].name);
                                        getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."EditBox1"):SetTextColor(1,1,1,1);
                                        getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."GrpByPlaytime"):Hide();
                                        getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."GrpByPlaytimeTitle"):Hide();
                                        getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."GrpResetCnt"):Hide();
                                        getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."GrpResetCntTitle"):Hide();
                                        getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."GrpDeleteTimer"):Hide();                                   
                                        getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."GrpDeleteTimerTitle"):Hide();
                                        getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."GrpOnStartTitle"):Hide();  
                                        getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."MenuButton"):SetText("!");
                                        if triggerdata[triggerPointer[i][j]].inactive then
                                                getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."Active"):SetChecked(false);
                                        else
                                                getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."Active"):SetChecked(true);
                                        end
                                        for j = 2, 5 do
                                                getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."EditBox"..j):Show();
                                        end     
                                        Timers_SetEditBox(triggerdata[triggerPointer[i][j]],"time",(Alli-Offset),"2");
                                        getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."EditBox2"):SetTextColor(1,1,1,1);  
                                        Timers_SetEditBox(triggerdata[triggerPointer[i][j]],"prewarn",(Alli-Offset),"3");       
                                        Timers_SetEditBox(triggerdata[triggerPointer[i][j]],"text",(Alli-Offset),"4");                                          
                                        if triggerdata[triggerPointer[i][j]].count == nil then
                                                triggerdata[triggerPointer[i][j]].count = 0;
                                        end
                                        getglobal("TimersMainFrameTimerRow"..(Alli-Offset).."EditBox5"):SetText(triggerdata[triggerPointer[i][j]].count);                                                                                               
                                        getglobal("TimersMainFrameTimerRow"..(Alli-Offset)):Show();
                                end
                                Alli = Alli + 1;
                        end
                end
        end
        if Alli-Offset <= 10 then
                if Alli <= Offset then
                        Alli = Offset + 1;
                end 
                for k = Alli-Offset, 10 do
                        getglobal("TimersMainFrameTimerRow"..k):Hide();
                end
        end                     
end

function Timers_ToggleShowInactive()
        if configdata.hideinactive then
                configdata.hideinactive = false;
                Timers_PrintText(TIMERS_LOC_SHOWINACTIVE);
        else
                configdata.hideinactive = true;
                Timers_PrintText(TIMERS_LOC_HIDEINACTIVE);
        end
        Timers_SetTriggerData();
end

function Timers_GroupNameToNumber(name)
        if name == nil then
                name = TIMERS_LOC_NOGROUP;
        end
        for i = 1, table.getn(groupdata) do
                if groupdata[i].name == name then
                        return i;
                end
        end
        return Timers_GroupNameToNumber(nil);
end

function Timers_TriggerNameToNumber(name)
        if name == nil then
                name = "default";
        end
        for i = 1, table.getn(triggerdata) do
                if triggerdata[i].name == name then
                        return i;
                end
        end
        return Timers_TriggerNameToNumber(nil);
end

function Timers_TriggerNameToDefaultNumber(name)
        for i = 1, table.getn(triggerdata_DEFAULT) do
                if triggerdata_DEFAULT[i].name == name then
                        return i;
                end
        end
        return nil;
end

function Timers_RowToGroup(i)
        local j = 1;
        local k = 1;
        while j < i do
                j = j + 1 + table.getn(triggerPointer[k]);
                k = k + 1;
        end
        return k;
end

function Timers_RowToTrigger(i)
        local j = 0;
        local k = 0;
        while j < i do
                j = j + 1 + table.getn(triggerPointer[k+1]);
                k = k + 1;
        end
        return triggerPointer[k][(table.getn(triggerPointer[k])-(j-i))];
end

function Timers_ToggleTriggerActive()
        if getglobal(this:GetParent():GetName().."EditBox2"):IsVisible() then
                if this:GetChecked() then
                        triggerdata[Timers_RowToTrigger(Timers_GetRow(this)+FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame))].inactive = false;
                else
                        triggerdata[Timers_RowToTrigger(Timers_GetRow(this)+FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame))].inactive = true;
                end
        else
                if this:GetChecked() then
                        groupdata[Timers_RowToGroup(Timers_GetRow(this)+FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame))].inactive = false;
                else
                        groupdata[Timers_RowToGroup(Timers_GetRow(this)+FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame))].inactive = true;
                end
        end
        Timers_SetTriggerData();
end

function Timers_ToggleGrpByPlaytime()
        if this:GetChecked() then
                groupdata[Timers_RowToGroup(Timers_GetRow(this)+FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame))].byplaytime = true;
        else
                groupdata[Timers_RowToGroup(Timers_GetRow(this)+FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame))].byplaytime = nil;
        end
end

function Timers_ToggleGrpDeleteTimer()
        if this:GetChecked() then
                groupdata[Timers_RowToGroup(Timers_GetRow(this)+FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame))].onstartdelete = true;
        else
                groupdata[Timers_RowToGroup(Timers_GetRow(this)+FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame))].onstartdelete = nil;
        end
end

function Timers_ToggleGrpResetCnt()
        if this:GetChecked() then
                groupdata[Timers_RowToGroup(Timers_GetRow(this)+FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame))].onstartreset = true;
        else
                groupdata[Timers_RowToGroup(Timers_GetRow(this)+FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame))].onstartreset = nil;
        end
end

function Timers_Init_TriggerPointer()
        triggerPointer = {};
        for i = 1, table.getn(groupdata) do
                if groupdata[i].inactive and configdata.hideinactive then
                        triggerPointer[i] = false;
                else
                        triggerPointer[i] = {};
                end
        end
end

function Timers_GetFieldValue(trigger,field)
        if trigger[field] and trigger[field] ~= TIMERS_LOC_DEFAULT then 
                return trigger[field];
        else
                if field == "count" then
                        return "0";
                elseif field == "group" then
                        return TIMERS_LOC_NOGROUP;
                else
                        for i = 1, table.getn(triggerdata) do
                                if triggerdata[i].name == "default" then
                                        return triggerdata[i][field];
                                end
                        end
                end
        end
end

function Timers_SetEditBox(trigger,field,row,nr)
        if trigger[field] == nil and (field == "channel" or field == "mode" or field == "type") then
                trigger[field] = TIMERS_LOC_DEFAULT;
        end
        if trigger[field] == nil then
                for i = 1, table.getn(triggerdata) do
                        if triggerdata[i].name == "default" then
                                if field == "time" then
                                        getglobal("TimersMainFrameTimerRow"..row.."EditBox"..nr):SetText(Timers_TimeToText(tonumber(triggerdata[i][field])));
                                else            
                                        getglobal("TimersMainFrameTimerRow"..row.."EditBox"..nr):SetText(triggerdata[i][field]);
                                end
                        end
                end
        elseif field == "time" then
                getglobal("TimersMainFrameTimerRow"..row.."EditBox"..nr):SetText(Timers_TimeToText(tonumber(trigger[field])));
        else            
                getglobal("TimersMainFrameTimerRow"..row.."EditBox"..nr):SetText(trigger[field]);
        end
end
        
function Timers_add(name,time,trigger)
        if tonumber(time) then
                time = time*60;
        else
                time = Timers_TextToTime(time);
        end
        local isnotValid = true;
        for i = 1, table.getn(triggerdata) do
                if triggerdata[i].name == trigger then
                        if not time then
                                time = triggerdata[i].time;
                        end
                        isnotValid = false;
                end
        end
        if isnotValid then
                trigger = "default";
        end
        if Timers_GetFieldValue(triggerdata[Timers_TriggerNameToNumber(trigger)],"mode") == TIMERS_LOC_INC then         
                table.insert(timerdata, {name=name, time=Timers_GetLocalTime(), trigger=trigger});
        else    
                table.insert(timerdata, {name=name, time=time+Timers_GetLocalTime(), trigger=trigger});
        end
        timerUpdateFlag = true;
        Timers_PrintText(TIMERS_LOC_TIMERADDED);
end

function Timers_SetTimerData()  
        local Offset = FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame);
        local Max = table.getn(timerdata);
        for i = 1 , 10 do
                if Max < i+Offset then 
                        getglobal("TimersMainFrameTimerRow"..i):Hide();
                else
                        getglobal("TimersMainFrameTimerRow"..i.."EditBox1"):SetText(timerdata[i+Offset].name);
                        getglobal("TimersMainFrameTimerRow"..i.."EditBox1"):SetTextColor(1,1,1,1);                      
                        getglobal("TimersMainFrameTimerRow"..i):Show();
                end
        end
        FauxScrollFrame_Update(TimersMainFrameScrollFrame, table.getn(timerdata), 10, 20);
end     

function Timers_UpdateTimes()                                   
        local Offset = FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame);
        local Max = table.getn(timerdata);
        for i = 1 , 10 do
                if Max >= i+Offset then 
                        if not timerdata[i+Offset].paused and not timerdata[i+Offset].editing then      
                                if Timers_GetFieldValue(triggerdata[Timers_TriggerNameToNumber(timerdata[i+Offset].trigger)],"mode") == TIMERS_LOC_INC then             
                                        getglobal("TimersMainFrameTimerRow"..i.."EditBox2"):SetText(Timers_TimeToText(Timers_GetLocalTime()-timerdata[i+Offset].time));                                                 
                                        getglobal("TimersMainFrameTimerRow"..i.."EditBox2"):SetTextColor(1,1,1,1);      
                                else
                                        getglobal("TimersMainFrameTimerRow"..i.."EditBox2"):SetText(Timers_TimeToText(timerdata[i+Offset].time-Timers_GetLocalTime()));                 
                                        if timerdata[i+Offset].time-Timers_GetLocalTime() > 0 then
                                                getglobal("TimersMainFrameTimerRow"..i.."EditBox2"):SetTextColor(1,1,1,1);                              
                                        else
                                                getglobal("TimersMainFrameTimerRow"..i.."EditBox2"):SetTextColor(1,0,0,1);
                                        end                     
                                        if timerdata[i+Offset].paused then
                                                getglobal("TimersMainFrameTimerRow"..i.."EditBox2"):SetTextColor(1,1,0,1);
                                        end     
                                end
                        elseif timerdata[i+Offset].paused and not timerdata[i+Offset].editing then
                                getglobal("TimersMainFrameTimerRow"..i.."EditBox2"):SetText(Timers_TimeToText(timerdata[i+Offset].paused-timerdata[i+Offset].time));                                            
                                getglobal("TimersMainFrameTimerRow"..i.."EditBox2"):SetTextColor(1,1,0,1);      
                        end                                     
                end
        end
end     

function Timers_UpdateTitle()
        local Title = "Timers "..configdata.titletext;
        Title = string.gsub(Title,"!tNext",TimersString_Replace_tNext());
        Title = string.gsub(Title,"!iAll",TimersString_Replace_iAll());
        Title = string.gsub(Title,"!iExpired",TimersString_Replace_iExpired());
        Title = string.gsub(Title,"!nNext",TimersString_Replace_nNext());
        if configdata.minimized then
                TimersMinimizedFrameTitle:SetText(Title);
        else
                TimersMainFrameTitle:SetText(Title);
        end
end

function Timers_CheckForNewTrigger()
        for i = 1, table.getn(groupdata_DEFAULT) do
                local notFound = true;
                for j = 1, table.getn(groupdata) do
                        if groupdata_DEFAULT[i].name == groupdata[j].name then
                                notFound = false;
                        end
                end
                if notFound then
                        table.insert(groupdata,Timers_cloneTable(groupdata_DEFAULT[i]));
                end
        end
        for i = 1, table.getn(triggerdata_DEFAULT) do
                local notFound = true;
                for j = 1, table.getn(triggerdata) do
                        if triggerdata_DEFAULT[i].name == triggerdata[j].name then
                                notFound = false;
                        end
                end
                if notFound then
                        table.insert(triggerdata,Timers_cloneTable(triggerdata_DEFAULT[i]));
                end
        end
end

function Timers_CorrectTimerData()
        if TimerscurrentTime then
                local Div = Timers_GetLocalTime() - TimerscurrentTime;
                local i = table.getn(timerdata);
                while i > 0 do
                        if groupdata[Timers_GroupNameToNumber(triggerdata[Timers_TriggerNameToNumber(timerdata[i].trigger)].group)].byplaytime then
                                timerdata[i].time = timerdata[i].time + Div;
                                if timerdata[i].paused then
                                        timerdata[i].paused = timerdata[i].paused + Div;
                                end
                                error("corrected");
                        end
                        if groupdata[Timers_GroupNameToNumber(triggerdata[Timers_TriggerNameToNumber(timerdata[i].trigger)].group)].onstartdelete then          
                                table.remove(timerdata,i);
                        end
                        i = i -1;
                end
        end
        timeIsCorrect = true;
        for i = 1, table.getn(triggerdata) do
                if groupdata[Timers_GroupNameToNumber(triggerdata[i].group)].onstartreset then
                        triggerdata[i].count = 0;
                end
        end
end

function Timers_VersionCorrections()
-- zu 3.2 (reload default trigger vor warnmessage/channel
        if (not (Timers_GetDefaultValue("warnmessage"))) then
                local trigger;
                for i = 1, table.getn(triggerdata_DEFAULT) do
                        if triggerdata_DEFAULT[i].name == "default" then
                                trigger = triggerdata_DEFAULT[i];
                        end
                end
                Timers_ResetByTrigger(trigger);
        end
end

-- String replacements
function TimersString_Replace_tNext()
        local time;
        for i = 1, table.getn(timerdata) do
                if timerdata[i].time > Timers_GetLocalTime() and (time == nil or timerdata[i].time < time) and triggerdata[Timers_TriggerNameToNumber(timerdata[i].trigger)].mode ~= TIMERS_LOC_INC then 
                        time = timerdata[i].time;
                end
        end
        if time ~= nil then
                return Timers_TimeToText(time-Timers_GetLocalTime());
        else 
                return 0;
        end
end

function TimersString_Replace_Coord()
        local x,y = GetPlayerMapPosition("player");
        x = math.ceil(x*1000)/10;
        y = math.ceil(y*1000)/10;
        return (x.."/"..y)
end

function TimersString_Replace_iAll()
        return table.getn(timerdata);
end

function TimersString_Replace_iExpired()
        local Expired = 0;
        for i = 1, table.getn(timerdata) do
                if timerdata[i].time < Timers_GetLocalTime() then 
                        Expired = Expired + 1;
                end
        end
        return Expired;
end

function TimersString_Replace_nNext()
        local time, name;
        for i = 1, table.getn(timerdata) do
                if timerdata[i].time > Timers_GetLocalTime() and (time == nil or timerdata[i].time < time) then 
                        time = timerdata[i].time;
                        name = timerdata[i].name;
                end
        end
        if name ~= nil then
                return name;
        else 
                return "--";
        end
end

function TimersString_Replace_Msgsub(timer)
        return string.gsub(timer.msg,triggerdata[Timers_TriggerNameToNumber(timer.trigger)].text," ");
end

function TimersString_Replace_Msgsub_4Warn(trigger,msg)
        return string.gsub(msg,trigger.text," ");
end
        
-- Edit Functions

function TimersEdit_SaveName()
        if this:GetText() == "" then
                this:SetText(TIMERS_LOC_NO_NAME_SET);
        end
        if this:GetText() == "default" then
                this:SetText("newdefault");
        end
        if string.find(this:GetName(),"Row") then
                local i = Timers_GetRow(this) + FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame);
                if configdata.activetab == 1 or configdata.activetab == 2 then
                        timerdata[i].name = this:GetText();
                elseif getglobal(this:GetParent():GetName().."EditBox2"):IsVisible() then
                        triggerdata[Timers_RowToTrigger(i)].name = this:GetText();
                else
                        for j = 1, table.getn(triggerdata) do
                                if triggerdata[j].group == groupdata[Timers_RowToGroup(i)].name then
                                        triggerdata[j].group = this:GetText();
                                end
                        end
                        groupdata[Timers_RowToGroup(i)].name = this:GetText();
                end
        else
                triggerdata[trigger_edit].name = this:GetText();
        end
        Timers_SetTriggerData();        
end

function TimersEdit_DeleteAllTimer()
        timerdata = {};
        timerUpdateFlag = true;
end

function TimersEdit_DeleteExpired()
        local i = table.getn(timerdata);
        while i > 0 do
                if timerdata[i].time-Timers_GetLocalTime() < 0 then
                        table.remove(timerdata, i);
                end
                i = i - 1;
        end
        timerUpdateFlag = true;
end

function TimersEdit_DeleteByGroup(grp)
        local i = table.getn(timerdata);
        while i > 0 do
                if triggerdata[Timers_TriggerNameToNumber(timerdata[i].trigger)].group == grp or (grp == TIMERS_LOC_NOGROUP and not triggerdata[Timers_TriggerNameToNumber(timerdata[i].trigger)].group) then
                        table.remove(timerdata, i);
                end
                i = i - 1;
        end
        timerUpdateFlag = true;
end

function TimersEdit_DeleteTimer(arg)
        local i = Timers_GetRow(arg) + FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame);
        table.remove(timerdata, i);
        timerUpdateFlag = true;
end

function TimersEdit_TogglePaused(arg,i)
        if i == nil then
                i = Timers_GetRow(arg) + FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame);
        end
        if timerdata[i].paused == nil then
                timerdata[i].paused = Timers_GetLocalTime();
        else
                timerdata[i].time = timerdata[i].time + (Timers_GetLocalTime() - timerdata[i].paused);
                timerdata[i].paused = nil;
        end
end 

function TimersEdit_StopTimer(arg,i)
        if i == nil then
                i = Timers_GetRow(arg) + FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame);
        end
        timerdata[i].paused = Timers_GetLocalTime();
        timerdata[i].stopped = true;
        timerUpdateFlag = true;
end

function TimersEdit_ResetTimer(arg,i)
        if i == nil then
                i = Timers_GetRow(arg) + FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame);
        end
        TimersEdit_ResetTimerByNr(i);
        timerUpdateFlag = true;
end

function TimersEdit_ResetTimerByNr(i)
        timerdata[i].time = triggerdata[Timers_TriggerNameToNumber(timerdata[i].trigger)].time+Timers_GetLocalTime();
        timerdata[i].prewarned = nil;
        timerdata[i].warned = nil;
end

function TimersEdit_ResetExpired()
        for i = 1, table.getn(timerdata) do
                if timerdata[i].time-Timers_GetLocalTime() < 0 then
                        TimersEdit_ResetTimerByNr(i);
                end
        end                     
        timerUpdateFlag = true;
end

function TimersEdit_ResetByGroup(grp)
        for i = 1, table.getn(timerdata) do
                if triggerdata[Timers_TriggerNameToNumber(timerdata[i].trigger)].group == grp or (grp == TIMERS_LOC_NOGROUP and not triggerdata[Timers_TriggerNameToNumber(timerdata[i].trigger)].group) then
                        TimersEdit_ResetTimerByNr(i);           
                end
        end                     
        timerUpdateFlag = true;
end
        
function TimersEdit_ResetAll()
        for i = 1, table.getn(timerdata) do
                TimersEdit_ResetTimerByNr(i)
        end                     
        timerUpdateFlag = true;
end

function TimersEdit_EditTime()
        local i = Timers_GetRow(this) + FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame);  
        if configdata.activetab == 1 or configdata.activetab == 2 then
                timerdata[i].editing = true;
        end
end 

function TimersEdit_EditName()
        if not (configdata.activetab == 1 or configdata.activetab == 2) then
                if not getglobal(this:GetParent():GetName().."EditBox2"):IsVisible() then
                        if groupdata[Timers_RowToGroup(Timers_GetRow(this) + FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame))].isnotdefault then
                                this:SetText(string.sub(this:GetText(),5,-5));
                        else
                                this:ClearFocus();
                                StaticPopupDialogs["TIMERS_ERROR_POPUP"].text = TIMERS_LOC_NOT_EDIT_DEFAULT_GROUPS;
                                StaticPopup_Show("TIMERS_ERROR_POPUP");
                        end
                else
                        if this:GetText() == "default" then
                                this:ClearFocus();
                                StaticPopupDialogs["TIMERS_ERROR_POPUP"].text = TIMERS_LOC_NOT_EDIT_DEFAULT;
                                StaticPopup_Show("TIMERS_ERROR_POPUP");
                        end
                end                     
        end
end

function TimersEdit_EditNameAdv()
        if this:GetText() == "default" then
                this:ClearFocus();
                StaticPopupDialogs["TIMERS_ERROR_POPUP"].text = TIMERS_LOC_NOT_EDIT_DEFAULT;
                StaticPopup_Show("TIMERS_ERROR_POPUP");
        end
end

function TimersEdit_SaveTime()
        if this:GetText() == "" then
                this:SetText("0");
        end
        if string.find(this:GetName(),"Row") then
                local i = Timers_GetRow(this) + FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame);  
                if configdata.activetab == 1 or configdata.activetab == 2 then
                        local time = Timers_TextToTime(this:GetText());
                        timerdata[i].time = Timers_GetLocalTime()+time;
                        timerdata[i].editing = nil;
                else
                        triggerdata[Timers_RowToTrigger(i)].time = Timers_TextToTime(this:GetText());
                end
        else
                triggerdata[trigger_edit].time = Timers_TextToTime(this:GetText());
        end             
        Timers_SetTriggerData();
end

function TimersEdit_SaveChannel(caller,text)
        TimersMenu_SetEditBoxText(caller,text);
        if string.find(caller:GetName(),"Warn") then
                triggerdata[trigger_edit].warnchannel = text;
        else    
                triggerdata[trigger_edit].channel = text;
        end
        Timers_SetTriggerData();
end

function TimersEdit_SaveMode(caller, text)
        TimersMenu_SetEditBoxText(caller,text);
        triggerdata[trigger_edit].mode = text;
        Timers_SetTriggerData();
end     

function TimersEdit_SaveType(caller, text)
        TimersMenu_SetEditBoxText(caller,text);
        triggerdata[trigger_edit].type = text;
        Timers_SetTriggerData();
end     

function TimersEdit_SaveTextImplicit(arg,text)
        local i;
        if string.find(arg:GetName(),"Row") then
                i = Timers_RowToTrigger(Timers_GetRow(arg) + FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame));
        else
                i = trigger_edit;
        end
        if triggerdata[i].name == "default" then
                StaticPopupDialogs["TIMERS_ERROR_POPUP"].text = TIMERS_LOC_NOT_TEXT;
                StaticPopup_Show("TIMERS_ERROR_POPUP");
        else            
                triggerdata[i].text = text;
        end
        if i == trigger_edit then
                TimersTriggersConfigFrameTextBox:SetText(text);
        end
        Timers_SetTriggerData();
end
        
function TimersEdit_SaveText()
        local i;
        if string.find(this:GetName(),"Row") then
                i = Timers_RowToTrigger(Timers_GetRow(this) + FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame));
        else
                i = trigger_edit;
        end
        if triggerdata[i].name == "default" then
                StaticPopupDialogs["TIMERS_ERROR_POPUP"].text = TIMERS_LOC_NOT_TEXT;
                StaticPopup_Show("TIMERS_ERROR_POPUP");
        else            
                triggerdata[i].text = this:GetText();
        end
end     

function TimersEdit_SaveMessage()
        if string.find(this:GetName(),"Warn") then
                if Timers_GetDefaultValue("warnmessage") ~= this:GetText() then
                        triggerdata[trigger_edit].warnmessage = this:GetText(); 
                end
        else
                if Timers_GetDefaultValue("message") ~= this:GetText() then
                        triggerdata[trigger_edit].message = this:GetText();     
                end
        end
        Timers_SetTriggerData();
end     

function TimersEdit_SaveCount()
        triggerdata[trigger_edit].count = this:GetText();
end     

function TimersEdit_SaveThreshold()
        triggerdata[trigger_edit].threshold = this:GetText();
end     

function TimersEdit_SavePrewarn()
        triggerdata[trigger_edit].prewarn = this:GetText();
end     

function Timers_MoveToGroup(row, nr)
        local i = row + FauxScrollFrame_GetOffset(TimersMainFrameScrollFrame);
        triggerdata[Timers_RowToTrigger(i)].group = groupdata[nr].name;
        Timers_SetTriggerData();
end

function Timers_StartMoving(frame)
        if not (configdata.activetab == 2) then
                frame:StartMoving();
        end
end

function Timers_OnMessageBoxAccept(text)
end

function Timers_OnAcceptBoxButton(state)
end

function Timers_CheckWarnAllTimers()
        local msg;
        local i = table.getn(timerdata);
        while i > 0 do
                if not (Timers_GetFieldValue(triggerdata[Timers_TriggerNameToNumber(timerdata[i].trigger)],"mode") == TIMERS_LOC_INC) then
                        local currTrigger = Timers_TriggerNameToNumber(timerdata[i].trigger);
                        if (not timerdata[i].prewarned and Timers_GetFieldValue(triggerdata[currTrigger],"prewarn") ~= "0" and timerdata[i].time-Timers_GetLocalTime() <= tonumber(Timers_GetFieldValue(triggerdata[currTrigger],"prewarn"))*60) then
                                Timers_WarnTimer(timerdata[i],true);
                                timerdata[i].prewarned = true;
                        end             
                        if (not timerdata[i].warned and timerdata[i].time-Timers_GetLocalTime() <= 0) then
                                Timers_WarnTimer(timerdata[i],false);
                                timerdata[i].warned = true;
                                if Timers_GetFieldValue(triggerdata[Timers_TriggerNameToNumber(timerdata[i].trigger)],"mode") == TIMERS_LOC_DELETE then
                                        table.remove(timerdata,i);
                                        timerUpdateFlag = true;
                                elseif Timers_GetFieldValue(triggerdata[Timers_TriggerNameToNumber(timerdata[i].trigger)],"mode") == TIMERS_LOC_RESET then
                                        TimersEdit_ResetTimer(nil,i);
                                end
                        end                     
                end
        i = i - 1;
        end
end     

function Timers_ImportTrigger()
        Timers_PrintText(TIMERS_LOC_IMPORTING);
        local counter = 0;
        for index, trigger in state.triggerList do
                local notfound = true;
                for i = 1, table.getn(triggerdata) do
                        if string.tolower(triggerdata[i].name) == string.tolower(index) then
                                notfound = false;
                        end
                end
                if notfound then
                        table.insert(triggerdata,{name=index, time=state.triggerList[index].time, isnotdefault = true});
                        counter = counter + 1;
                end
        end
        Timers_PrintText(counter..TIMERS_LOC_IMPORTED);
end

function Timers_WarnTimer(timer,prewarn)
        local msg;
        local channel;
        if prewarn then
                msg = Timers_GetFieldValue(triggerdata[Timers_TriggerNameToNumber(timer.trigger)],"warnmessage");
                channel = Timers_GetFieldValue(triggerdata[Timers_TriggerNameToNumber(timer.trigger)],"warnchannel");   
        else
                msg = Timers_GetFieldValue(triggerdata[Timers_TriggerNameToNumber(timer.trigger)],"message");
                channel = Timers_GetFieldValue(triggerdata[Timers_TriggerNameToNumber(timer.trigger)],"channel");
        end
        if Timers_GetFieldValue(triggerdata[Timers_TriggerNameToNumber(timer.trigger)],"mode") == TIMERS_LOC_INC then
                msg = string.gsub(msg,"!time",Timers_TimeToText(Timers_GetLocalTime()-timer.time));
        else                    
                msg = string.gsub(msg,"!time",Timers_TimeToText(timer.time-Timers_GetLocalTime()));
        end
        msg = string.gsub(msg,"!name",timer.name);
        msg = string.gsub(msg,"!trigger",timer.trigger);
        msg = string.gsub(msg,"!count",Timers_GetFieldValue(triggerdata[Timers_TriggerNameToNumber(timer.trigger)],"count"));
        msg = string.gsub(msg,"!group",Timers_GetFieldValue(triggerdata[Timers_TriggerNameToNumber(timer.trigger)],"group"));
        if timer.msg then
                msg = string.gsub(msg,"!msgsub",TimersString_Replace_Msgsub(timer));
                msg = string.gsub(msg,"!msg",timer.msg);
        else
                msg = string.gsub(msg,"!msgsub",TIMERS_LOC_INVOKED_MANUAL);
                msg = string.gsub(msg,"!msg",TIMERS_LOC_INVOKED_MANUAL);
        end                             
        Timers_MsgSendTo(msg,channel);
end

function Timers_WarnOnly(trigger,Invokemsg,time)
        local msg = Timers_GetFieldValue(trigger,"message");
        local channel = Timers_GetFieldValue(trigger,"channel");
        msg = string.gsub(msg,"!trigger",trigger.name);
        msg = string.gsub(msg,"!count",Timers_GetFieldValue(trigger,"count"));
        msg = string.gsub(msg,"!group",Timers_GetFieldValue(trigger,"group"));
        msg = string.gsub(msg,"!msgsub",TimersString_Replace_Msgsub_4Warn(trigger,Invokemsg));
        msg = string.gsub(msg,"!msg",Invokemsg);
        if time then
                if Timers_GetFieldValue(trigger,"mode") == TIMERS_LOC_INC then
                        msg = string.gsub(msg,"!time",Timers_TimeToText(Timers_GetLocalTime()-time));
                else                    
                        msg = string.gsub(msg,"!time",Timers_TimeToText(time-Timers_GetLocalTime()));
                end
        end             
        Timers_MsgSendTo(msg,channel);
end

function Timers_CreateIconArray()
        local i = 1;
        while GetSpellName(i,BOOKTYPE_SPELL) do
                if GetSpellTexture(i,BOOKTYPE_SPELL) then
                        IconArray[GetSpellTexture(i,BOOKTYPE_SPELL)] = GetSpellName(i,BOOKTYPE_SPELL);
                end
                i = i + 1;
        end
end 
        
-- PopupBox

StaticPopupDialogs["TIMERS_MESSAGE_POPUP"] = {
        button1 = TEXT(ACCEPT),
        button2 = TEXT(CANCEL),
        hasEditBox = 1,
        maxLetters = 20,
        OnAccept = function()
                local editBox = getglobal(this:GetParent():GetName().."EditBox");
                Timers_OnMessageBoxAccept("!trigger"..editBox:GetText(),StaticPopupDialogs["TIMERS_MESSAGE_POPUP"].arg1,StaticPopupDialogs["TIMERS_MESSAGE_POPUP"].arg2);
        end,
        OnShow = function()
                getglobal(this:GetName().."EditBox"):SetFocus();
                getglobal(this:GetName().."EditBox"):SetText("");
        end,
        OnHide = function()
                if ( ChatFrameEditBox:IsVisible() ) then
                        ChatFrameEditBox:SetFocus();
                end
                getglobal(this:GetName().."EditBox"):SetText("");
        end,
        EditBoxOnEnterPressed = function()
                local editBox = getglobal(this:GetParent():GetName().."EditBox");
                Timers_OnMessageBoxAccept("!trigger"..editBox:GetText(),StaticPopupDialogs["TIMERS_MESSAGE_POPUP"].arg1,StaticPopupDialogs["TIMERS_MESSAGE_POPUP"].arg2);
                this:GetParent():Hide();
        end,
        EditBoxOnEscapePressed = function()
                this:GetParent():Hide();
        end,
        timeout = 0,
        exclusive = 1,
        whileDead = 1
};

StaticPopupDialogs["TIMERS_ACCEPT_POPUP"] = {
        button1 = TEXT(ACCEPT),
        button2 = TEXT(CANCEL),
        OnAccept = function()
                Timers_OnAcceptBoxButton(true);
        end,
        OnCancel = function()
                Timers_OnAcceptBoxButton(false);
        end,
        timeout = 0,
        exclusive = 1,
        whileDead = 1
};

StaticPopupDialogs["TIMERS_ERROR_POPUP"] = {
        button1 = TEXT(OKAY),
        timeout = 0,
        exclusive = 1,
        whileDead = 1
};

Generated by GNU Enscript 1.6.5.90.