local _, addon = ...
local API = addon.API;
local L = addon.L;

local time = time;
local SearchChatHistory = API.SearchChatHistory;
local SecondsToTime = API.SecondsToTime;

local COOLDOWN_ANNOUNCE = 20;
local CAN_SEND_MESSAGE = false;

local DELENSION = "";

local HornButton = CreateFrame("Button");
HornButton:Hide();
HornButton:SetSize(20, 20);
HornButton:SetMotionScriptsWhileDisabled(true);
HornButton:RegisterForClicks("LeftButtonUp");


local PrivateFrame = CreateFrame("Frame");
PrivateFrame:Hide();

local function AlwaysFalse()
	return false
end
PrivateFrame.validateFunc = AlwaysFalse;

function PrivateFrame:GetGlobalUnlockTime()
	--This time is stored in our SavedVariable
	local db = PlumberDB;

	if db and db.announceButtonLockUntil and type(db.announceButtonLockUntil) == "number" then
		local currentTime = time();
		if db.announceButtonLockUntil - currentTime > 60 then
			db.announceButtonLockUntil = currentTime + COOLDOWN_ANNOUNCE;
		end
		return db.announceButtonLockUntil
	else
		return 0
	end
end

function PrivateFrame:SetGlobalUnlockTime(endTime)
	local db = PlumberDB;

	if db then
		if endTime then
			db.announceButtonLockUntil = endTime;
		else
			local currentTime = time();
			db.announceButtonLockUntil = currentTime + COOLDOWN_ANNOUNCE;
		end
	end
end

function PrivateFrame:OnUpdate(elapsed)
	self.t = self.t + elapsed;
	if self.t >= 0 then
		self:SetScript("OnUpdate", nil);
		self.t = nil;
		self.endTime = nil;
		if HornButton:IsVisible() then
			self:UpdateValidity();
		end
	end
end

function PrivateFrame:StartLockTimer(forceRestart)
	if (not self.endTime) or forceRestart then
		self.t = -COOLDOWN_ANNOUNCE;
		self.endTime = time() + COOLDOWN_ANNOUNCE;
		PrivateFrame:SetGlobalUnlockTime(self.endTime);
		self:SetScript("OnUpdate", self.OnUpdate);
	end
end

function PrivateFrame:GetLockEndTime()
	return self.endTime or self:GetGlobalUnlockTime();
end

function PrivateFrame:GetLockRemainingSeconds()
	local seconds = self:GetLockEndTime() - time();
	if seconds < 0 then
		seconds = 0;
	end
	return seconds
end

function PrivateFrame:IsButtonInCooldown()
	return self:GetLockRemainingSeconds() > 0
end

function PrivateFrame:CalibrateTimer()
	local remainingSeconds = self:GetLockRemainingSeconds()
	if remainingSeconds <= 0 then
		self:UnlockButton();
		self:SetScript("OnUpdate", nil);
	else
		self:LockButton(1, true);
		self.t = -remainingSeconds;
		self.endTime = time() + remainingSeconds;
		self:SetScript("OnUpdate", self.OnUpdate);
	end
end

function PrivateFrame:UpdateValidity()
	local messageFound = SearchChatHistory(self.validateFunc);
	if messageFound then
		self:LockButton(2, true);
	else
		if not self:IsButtonInCooldown() then
			self:UnlockButton();
		end
	end
end

function PrivateFrame:LockButton(reason, overridePreviousReason)
	if (not self.disableReason) or overridePreviousReason then
		self.disableReason = reason;
	end

	CAN_SEND_MESSAGE = false;
	HornButton:Disable();

	--Disable Reason
	--#1 In cooldown (start OnClick)
	--#2 Shared by another player (search chat)
	--#3 Target soon despawn
end

function PrivateFrame:GetLockReason()
	local reason, hasTimer;

	if self.disableReason == 1 then
		reason = L["Announce Forbidden Reason In Cooldown"];
		hasTimer = true;
	elseif self.disableReason == 2 then
		reason = L["Announce Forbidden Reason Duplicate Message"];
	elseif self.disableReason == 3 then
		reason = L["Announce Forbidden Reason Soon Despawn"];
	else
		reason = TOKEN_MARKET_PRICE_NOT_AVAILABLE or "Not Available";
	end

	return reason, hasTimer
end

function PrivateFrame:UnlockButton()
	CAN_SEND_MESSAGE = true;
	HornButton:Enable();
	self.disableReason = nil;
end

function PrivateFrame:ListenEvents(state)
	if state then
		self:RegisterEvent("CHAT_MSG_CHANNEL");
	else
		self:UnregisterEvent("CHAT_MSG_CHANNEL");
	end
end

function PrivateFrame:OnShow()
	self:CalibrateTimer();
	self:ListenEvents(true);
	self:UpdateValidity();
end

function PrivateFrame:OnHide()
	self:ListenEvents(false);
end

PrivateFrame:SetScript("OnShow", PrivateFrame.OnShow);
PrivateFrame:SetScript("OnHide", PrivateFrame.OnHide);

PrivateFrame:SetScript("OnEvent", function(self, event, ...)
	local text = ...
	if text and self.validateFunc(text) then
		self:LockButton(2, true);
	end
end);


function HornButton:OnMouseDown(button)
	if self:IsEnabled() and button == "LeftButton" then
		self.Icon:SetPoint("CENTER", self, "CENTER", 0, -1);
	end
end

function HornButton:OnMouseUp()
	self.Icon:SetPoint("CENTER", self, "CENTER", 0, 0);
end

function HornButton:GetAnnounceText()
	if self.sourceFunction then
		return self.sourceFunction()
	end
end

function HornButton:SetAnnouceTextSource(sourceFunction)
	self.sourceFunction = sourceFunction;
end

function HornButton:OnClick()
	local success, msg = self:GetAnnounceText();

	if not success then
		local reasonCode = msg;
		PrivateFrame:LockButton(reasonCode, true);
		return
	end

	if CAN_SEND_MESSAGE and msg then
		--print(msg);
		local channelID = C_ChatInfo.GetGeneralChannelID();
		if channelID then
			C_ChatInfo.SendChatMessage(msg, "CHANNEL", nil, channelID);
		else
			UIErrorsFrame:AddExternalErrorMessage("Could not find General Chat channel.");
		end
		PrivateFrame:LockButton(1, true);
		PrivateFrame:StartLockTimer(true);
	end
end

function HornButton:OnEnable()
	self.Icon:SetDesaturated(false);
	self.Icon:SetVertexColor(1, 1, 1);
	self.Icon:SetPoint("CENTER", self, "CENTER", 0, 0);
	self:RefreshOnEnter();
end

function HornButton:OnDisable()
	self.Icon:SetDesaturated(true);
	self.Icon:SetVertexColor(0.8, 0.8, 0.8);
	self.Icon:SetPoint("CENTER", self, "CENTER", 0, 0);
	self.Highlight:Hide();
	self:RefreshOnEnter();
end

function HornButton:RefreshOnEnter()
	if self:IsVisible() and self:IsMouseOver() then
		self:OnEnter();
	end
end

function HornButton:OnShow()
	--PrivateFrame:Show();
end

function HornButton:OnHide()
	self:SetScript("OnUpdate", nil);
	PrivateFrame:Hide();
end

function HornButton:UpdateTooltipTimer()
	self:OnEnter();
end

function HornButton:OnEnter()
	local tooltip = GameTooltip;
	tooltip:Hide();
	tooltip:SetOwner(self, "ANCHOR_RIGHT");
	tooltip:SetText(BATTLENET_BROADCAST or "Broadcast", 1, 1, 1);

	if self:IsEnabled() and CAN_SEND_MESSAGE then
		self.Highlight:Show();
		tooltip:AddLine(L["Announce Location Tooltip"], 1, 0.82, 0, true);
		self.UpdateTooltip = nil;
	else
		self.Highlight:Hide();
		local lockReason, hasTimer = PrivateFrame:GetLockReason();
		tooltip:AddLine(lockReason, 1.000, 0.282, 0.000, true); --WARNING_FONT_COLOR
		if hasTimer then
			local seconds = PrivateFrame:GetLockRemainingSeconds();
			if seconds and seconds > 0 then
				local remainingTime = string.format(L["Available In Format"], SecondsToTime(seconds, true));
				tooltip:AddLine(remainingTime, 1, 0.82, 0, true);
				self.UpdateTooltip = self.UpdateTooltipTimer;
			else
				self.UpdateTooltip = nil;
			end
		else
			self.UpdateTooltip = nil;
		end
	end
	tooltip:Show();
end

function HornButton:OnLeave()
	GameTooltip:Hide();
	self.Highlight:Hide();
end

function HornButton:EnableCursorBlocker(state)
	self.CursorBlocker:SetShown(state);
end

function HornButton:Init()
	local tex = "Interface/AddOns/Plumber/Art/Button/HornButton";

	self.Highlight = self:CreateTexture(nil, "OVERLAY");    --HIGHLIGHT layers doesn't work well when SetMotionScriptsWhileDisabled = true
	self.Highlight:Hide();
	self.Highlight:SetSize(32, 32);
	self.Highlight:SetPoint("CENTER", self, "CENTER", 0, 0);
	self.Highlight:SetTexture(tex);
	self.Highlight:SetTexCoord(0.5, 1, 0, 1);

	self.Icon = self:CreateTexture(nil, "ARTWORK");
	self.Icon:SetSize(32, 32);
	self.Icon:SetPoint("CENTER", self, "CENTER", 0, 0);
	self.Icon:SetTexture(tex);
	self.Icon:SetTexCoord(0, 0.5, 0, 1);

	self:SetScript("OnMouseDown", self.OnMouseDown);
	self:SetScript("OnMouseUp", self.OnMouseUp);
	self:SetScript("OnClick", self.OnClick);
	self:SetScript("OnEnable", self.OnEnable);
	self:SetScript("OnDisable", self.OnDisable);
	self:SetScript("OnShow", self.OnShow);
	self:SetScript("OnHide", self.OnHide);
	self:SetScript("OnEnter", self.OnEnter);
	self:SetScript("OnLeave", self.OnLeave);

	local CursorBlocker = CreateFrame("Frame", nil, self);
	self.CursorBlocker = CursorBlocker;
	CursorBlocker:SetSize(40, 40);
	CursorBlocker:Hide();
	CursorBlocker:SetPoint("CENTER", self, "CENTER", 0, 0);
	CursorBlocker:SetFrameStrata("BACKGROUND");
	CursorBlocker:SetFixedFrameStrata(true);
	CursorBlocker:EnableMouse(true);

	self.Init = nil;
end

function HornButton:SetValidityCheck(validateFunc)
	PrivateFrame.validateFunc = validateFunc or AlwaysFalse;
end

function HornButton:OnUpdate(elapsed)
	self.t = self.t + elapsed;
	if self.t >= 0.5 then
		self:SetScript("OnUpdate", nil);
		if self.callback then
			self.callback();
			self.callback = nil;
		end
		PrivateFrame:Show();
		PrivateFrame:UpdateValidity();
	end
end

function HornButton:ShowAndRequestUpdate(optionalCallback)
	self:Disable();
	self.t = 0;
	self.callback = optionalCallback;
	self:SetScript("OnUpdate", self.OnUpdate);
	self:Show();
end

local function GetAnnounceButton()
	if HornButton.Init then
		HornButton:Init();
	end
	HornButton:Hide();

	return HornButton
end
addon.GetAnnounceButton = GetAnnounceButton;



do
	local locale = GetLocale();
	if locale == "ruRU" then
		DELENSION = ": ";
	end
end
--Debug
--[[
local function ProcessChatMessage(msg)
	local uiMapID, x, y = GetWaypointFromText(msg);
	if uiMapID then
		print(uiMapID, x, y)
	end
end

function PrintChatWaypoints()
	SearchChatHistory(ProcessChatMessage);
end

function Debug_WaypointsMatch()
	local uiMapID = C_Map.GetBestMapForUnit("player");
	local posVector = C_Map.GetUserWaypointPositionForMap(uiMapID);

	if posVector then
		local x, y = posVector:GetXY();
		local LocationDataProvider = API.DreamseedUtil;
		local isClose;

		for creatureID, position in LocationDataProvider:EnumerateSpawnLocations() do
			isClose = AreWaypointsClose(x, y, position[1], position[2]);
			if isClose then
				local name = LocationDataProvider:GetPlantNameByCreatureID(creatureID);
				print(name)
				break
			end
		end
	end
end
--]]
