------------------------------------------------
--                  CT_Core                   --
--                                            --
-- Core addon for doing basic and popular     --
-- things in an intuitive way.                --
-- Please do not modify or otherwise          --
-- redistribute this without the consent of   --
-- the CTMod Team. Thank you.                 --
------------------------------------------------

local _G = getfenv(0);
local module = _G.CT_Core;
local NUM_CHAT_WINDOWS = NUM_CHAT_WINDOWS;

--------------------------------------------
-- Chat Arrows

local hide = true;
local menuButton = _G.ChatFrameMenuButton;

-- Generic function to toggle a given ChatFrame's buttons
local function toggleButtons(self, hide)
	local name = self:GetName();
	if ( hide ) then
		_G[name.."BottomButton"]:Hide();
		_G[name.."UpButton"]:Hide();
		_G[name.."DownButton"]:Hide();
	else
		_G[name.."BottomButton"]:Show();
		_G[name.."UpButton"]:Show();
		_G[name.."DownButton"]:Show();
	end
end

-- Hide/Show all ChatFrames' buttons
local function toggleChatFrameButtons(hide)
	for i = 1, NUM_CHAT_WINDOWS, 1 do
		toggleButtons(_G["ChatFrame"..i], hide);
	end
	if ( hide ) then
		menuButton:Hide();
	else
		menuButton:Show();
	end
end

--------------------------------------------
-- Chat Scrolling

local shift, control = IsShiftKeyDown, IsControlKeyDown;

-- Function to scroll the ChatFrame according to the defined mode
local function onChatScroll(self, direction)
	if ( tonumber(direction) > 0 ) then
		if ( shift() ) then
			self:ScrollToTop();
		elseif ( control() ) then
			self:PageUp();
		else
			self:ScrollUp();
		end
	else
		if ( shift() ) then
			self:ScrollToBottom();
		elseif ( control() ) then
			self:PageDown();
		else
			self:ScrollDown();
		end
	end
end

-- Toggles Chat Scrolling on a given ChatFrame
local function toggleScrolling(self, enable)
	if ( enable ) then
		self:EnableMouseWheel(true);
		self:SetScript("OnMouseWheel", onChatScroll);
	else
		self:EnableMouseWheel(false);
		self:SetScript("OnMouseWheel", nil);
	end
end

-- Enable/Disable scrolling on all ChatFrames
local function toggleChatFrameScrolling(enable)
	for i = 1, NUM_CHAT_WINDOWS, 1 do
		toggleScrolling(_G["ChatFrame"..i], enable);
	end
end

--------------------------------------------
-- Chat Edit Move

local function toggleChatEditMove(move, initial)
	if ( move ) then
		local editBox = _G.ChatFrameEditBox;
		editBox:ClearAllPoints();
		editBox:SetPoint("BOTTOMLEFT", "ChatFrame1", "TOPLEFT", -5, 2);
		editBox:SetPoint("BOTTOMRIGHT", "ChatFrame1", "TOPRIGHT", 5, 2);
	elseif ( not initial ) then
		local editBox = _G.ChatFrameEditBox;
		editBox:ClearAllPoints();
		editBox:SetPoint("TOPLEFT", "ChatFrame1", "BOTTOMLEFT", -5, -2);
		editBox:SetPoint("TOPRIGHT", "ChatFrame1", "BOTTOMRIGHT", 5, -2);
	end
end

--------------------------------------------
-- Chat Timestamps

local stamp;
local savedMessageFunction = {};
local date, tonumber = date, tonumber;

-- Displays a message with a timestamp in various formats
local function addMessageTimestamp(self, msg, ...)
	if (stamp == 1) then
		-- 12h
		return savedMessageFunction[self](self, "["..tonumber(date("%I"))..date(":%M] ") .. (msg or ""), ...);
	elseif (stamp == 2) then
		-- 12hs
		return savedMessageFunction[self](self, "["..tonumber(date("%I"))..date(":%M:%S] ") .. (msg or ""), ...);
	elseif (stamp == 3) then
		-- 24h
		return savedMessageFunction[self](self, date("[%H:%M] ") .. (msg or ""), ...);
	elseif (stamp == 4) then
		-- 24hs
		return savedMessageFunction[self](self, date("[%H:%M:%S] ") .. (msg or ""), ...);
	else
		return savedMessageFunction[self](self, (msg or ""), ...);
	end
end

-- Toggle chat timestamps for a given ChatFrame
local function toggleTimestamps(frame, mode)
	stamp = mode;
	if (frame == COMBATLOG) then
		return;
	end
	if ( mode > 0 ) then
		if ( not savedMessageFunction[frame] ) then
			-- Cache the current AddMessage function
			savedMessageFunction[frame] = frame.AddMessage;
			-- Hook the function
			frame.AddMessage = addMessageTimestamp;
		end
	elseif ( savedMessageFunction[frame] ) then
		-- Only restore the original function if no one else has hooked it.
		if (frame.AddMessage == addMessageTimestamp) then
			frame.AddMessage = savedMessageFunction[frame];
			-- Forget what we had hooked (might be different next time).
			savedMessageFunction[frame] = nil;
		end
	end
end

-- Toggle chat timestamps for all ChatFrames
local function toggleChatFrameTimestamps(mode)
	for i = 1, NUM_CHAT_WINDOWS, 1 do
		toggleTimestamps(_G["ChatFrame"..i], mode);
	end
end

-- /pri
module:setSlashCmd(function(msg) RunScript("ChatFrame1:AddMessage("..msg..", 1, 1, 0);"); end, "/pri");

--------------------------------------------
-- General Initializer

module.chatupdate = function(self, type, value)
	if ( type == "init" ) then
		local frame;
		
		local chatScrolling, chatTimestamp, chatTimestampFormat = self:getOption("chatScrolling"), 
			self:getOption("chatTimestamp"), self:getOption("chatTimestampFormat");
		for i = 1, NUM_CHAT_WINDOWS, 1 do
			frame = _G["ChatFrame"..i];
			if ( frame ) then
				local onShow = frame:GetScript("OnShow");
				frame:SetScript("OnShow", function(self)
					if (not self) then
						self = this;
					end
					if ( onShow ) then
						onShow(self);
					end
					local chatArrows = module:getOption("chatArrows");
					if ( chatArrows ) then
						toggleButtons(self, chatArrows );
					end
				end);
				toggleScrolling(frame, chatScrolling);
				toggleTimestamps(frame, ( chatTimestamp and (chatTimestampFormat or 1) ) or 0);
			end
		end
		toggleChatFrameButtons(self:getOption("chatArrows"));
		toggleChatEditMove(self:getOption("chatEditMove"), true);
	else
		if ( type == "chatArrows" ) then
			toggleChatFrameButtons(value);
		elseif ( type == "chatScrolling" ) then
			toggleChatFrameScrolling(value);
		elseif ( type == "chatTimestamp" ) then
			toggleChatFrameTimestamps(( value and (self:getOption("chatTimestampFormat") or 1) ) or 0);
		elseif ( type == "chatTimestampFormat" ) then
			toggleChatFrameTimestamps(( self:getOption("chatTimestamp") and value ) or 0);
		elseif ( type == "chatEditMove" ) then
			toggleChatEditMove(value);
		end
	end
end