DailyAutoShare              = DailyAutoShare or {}
DAS                         = DailyAutoShare

DAS.name                    = "DailyAutoShare"
DAS.version                 = "3.3.1"
DAS.author                  = "manavortex"
DAS.settings                = {}
DAS.globalSettings          = {}

DAS.shareables   	        = {}
DAS.bingo 			        = {}
DAS.bingoFallback           = {}
DAS.subzones 		        = {}
DAS.activeZoneQuests        = {}

DAS.questFinisher           = {}
DAS.questStarter            = {}
DAS.questIds                = {}
DAS.channelTypes 	        = {
    [CHAT_CHANNEL_PARTY]    = true,
    [CHAT_CHANNEL_SAY ]     = false,
    [CHAT_CHANNEL_YELL]     = false,
    [CHAT_CHANNEL_ZONE]     = false,
    [CHAT_CHANNEL_WHISPER]  = false,
}

DAS.locale 			    = GetCVar("language.2")
DAS.autoInviting        = false
DAS.guildInviteText     = nil

DAS_STATUS_COMPLETE 	= 0
DAS_STATUS_OPEN 		= 1
DAS_STATUS_ACTIVE		= 2
DAS_STATUS_TRACKED	    = 3

local activeInCurrentZone   = false
DAS.fullBingoString         = ""
local fullBingoString       = DAS.fullBingoString

UNITTAG_PLAYER              = UNITTAG_PLAYER or "player"

local defaults = {

	["singleDailies"]               = {},
	["shareableDailies"]            = {},
	["speakStupid"]                 = false,
	["debug"] 		                = false,
	["keepInviteUpOnDegroup"] 		= false,

	["DasControl"] = {
		["x"] = 0,
		["y"] = 0,
	},
	["DasButton"] = {
		["x"] = 0,
		["y"] = 0,
	},
	["inactiveZones"]			= {
		["hide"]				= true,
	},
	[849] = {
		["relic"] = {
			["invisible"] = false,
			["active"] = true,
		},
		["hunt"] = {
			["invisible"] = false,
			["active"] = true,
		},
		["delve"] = {
			["invisible"] = false,
			["active"] = true,
		},
		["boss"] = {
			["invisible"] = false,
			["active"] = true,
		},
	},
	[980] = {
		["crow"] = {
			["invisible"] = false,
			["active"] = true,
		},
		["craft"] = {
			["invisible"] = false,
			["active"] = true,
		},
		["delve"] = {
			["invisible"] = false,
			["active"] = true,
		},
		["boss"] = {
			["invisible"] = false,
			["active"] = true,
		},
	},
    questShareString            = "I can give a DailyAutoShare for <<1>>, type <<2>> for an instant invite",
	debugOutput		   			= false,
	currentlyWithQuest 			= false,
	currentQuestIndex 			= nil,
	currentQuestName 			= nil,
	autoTrack 					= false,
	autoAcceptInvite 			= false,
	autoAcceptInviteInterval 	= 5,
	autoAcceptQuest		        = true,
	autoAcceptShared 			= true,
	autoDeclineShared 			= false,
	autoHide 					= false,
	autoMinimize 				= false,
	autoShare 					= true,
	autoAcceptAllDailies 		= false,
	autoInvite 					= false,
	autoLeave 					= false,
	useGlobalSettings 			= true,
	minimised 					= false,
	locked 						= false,
	hidden 						= false,
	fontScale					= 1,
	tooltipRight 				= false,
	upsideDown 					= false,
    hideCompleted				= false,
	startupMinimized			= true,
	resetAutoShareOnNewGroup    = true,
	lastLookingFor 				= "",
	guildInviteNumber 			= 1,
	groupInviteDelay			= 500,
	questShareDelay				= 500,
	guildInviteText,
    questShareString            = "I can give a DailyAutoShare for <<1>>, type <<2>> for an instant invite",
	listenInGuilds,
    whisperOnly                 = false,
    whisperString               = "whisper + for an instant invite",
    tracked = {
		[684] = true,
		[823] = true,
		[849] = true,	    -- Vvardenfell
		[181] = false,
		[1011] = false,     -- Summerset
	},
}

local function pointerUpSubzones()

      -- Summerset
    defaults[1012]                      = defaults[1011]
    defaults[1013]                      = defaults[1011]
    defaults[1014]                      = defaults[1011]
    defaults[1015]                      = defaults[1011]
    defaults[1016]                      = defaults[1011]
    defaults[1017]                      = defaults[1011]
    defaults[1018]                      = defaults[1011]
    defaults[1019]                      = defaults[1011]
    defaults.tracked[1012]              = defaults.tracked[1011]
    defaults.tracked[1013]              = defaults.tracked[1011]
    defaults.tracked[1014]              = defaults.tracked[1011]
    defaults.tracked[1015]              = defaults.tracked[1011]
    defaults.tracked[1016]              = defaults.tracked[1011]
    defaults.tracked[1017]              = defaults.tracked[1011]
    defaults.tracked[1018]              = defaults.tracked[1011]
    defaults.tracked[1019]              = defaults.tracked[1011]

    -- Gold Coast
    defaults[825]                       = defaults[823]
    defaults[826]                       = defaults[823]
    defaults.tracked[825]               = defaults.tracked[823]
    defaults.tracked[826]               = defaults.tracked[823]

    -- Capitals
    defaults[19]                       = defaults[57]
    defaults[383]                      = defaults[57]
    defaults.tracked[19]               = defaults.tracked[57]
    defaults.tracked[383]              = defaults.tracked[57]

    -- Clockwork City
    defaults[981]                       = defaults[980]
    defaults[981]                       = defaults[980]
    defaults[982]                       = defaults[980]
    defaults.tracked[982]               = defaults.tracked[980]
    defaults.tracked[983]               = defaults.tracked[980]
    defaults.tracked[983]               = defaults.tracked[980]

    -- Morrowind
    defaults[921]                       = defaults[849]
    defaults[922]                       = defaults[849]
    defaults[923]                       = defaults[849]
    defaults[924]                       = defaults[849]
    defaults[925]                       = defaults[849]
    defaults[961]                       = defaults[849]
    defaults.tracked[921]               = defaults.tracked[849]
    defaults.tracked[922]               = defaults.tracked[849]
    defaults.tracked[923]               = defaults.tracked[849]
    defaults.tracked[924]               = defaults.tracked[849]
    defaults.tracked[925]               = defaults.tracked[849]
    defaults.tracked[961]               = defaults.tracked[849]

    -- Wrothgar
    defaults[689]                       = defaults[684]
    defaults[690]                       = defaults[684]
    defaults[691]                       = defaults[684]
    defaults[692]                       = defaults[684]
    defaults[693]                       = defaults[684]
    defaults[694]                       = defaults[684]
    defaults.tracked[689]               = defaults.tracked[684]
    defaults.tracked[690]               = defaults.tracked[684]
    defaults.tracked[691]               = defaults.tracked[684]
    defaults.tracked[692]               = defaults.tracked[684]
    defaults.tracked[693]               = defaults.tracked[684]
    defaults.tracked[694]               = defaults.tracked[684]
end
pointerUpSubzones()

local characterName     = zo_strformat(GetUnitName(UNITTAG_PLAYER))

local allDailyQuestIds = DAS_QUEST_IDS

local em = EVENT_MANAGER

local function debugOut(p1, p2, p3, p4, p5, p6, p7, p8)
    if not DAS.GetDebugMode() then return end
    if (not p2) then d(p1); return; end
    if p8 then
        d(zo_strformat("<<1>> <<2>> <<3>> <<4>> <<5>> <<6>> <<7>> <<8>>", p1, p2, p3, p4, p5, p6, p7, p8))
    elseif p7 then
        d(zo_strformat("<<1>> <<2>> <<3>> <<4>> <<5>> <<6>> <<7>>", p1, p2, p3, p4, p5, p6, p7))
    elseif p6 then
        d(zo_strformat("<<1>> <<2>> <<3>> <<4>> <<5>> <<6>>", p1, p2, p3, p4, p5, p6))
    elseif p5 then
        d(zo_strformat("<<1>> <<2>> <<3>> <<4>> <<5>>", p1, p2, p3, p4, p5))
    elseif p4 then
        d(zo_strformat("<<1>> <<2>> <<3>> <<4>>", p1, p2, p3, p4))
    elseif p3 then
        d(zo_strformat("<<1>> <<2>> <<3>>", p1, p2, p3))
    else
        d(zo_strformat("<<1>> <<2>>", p1, p2))
    end
end
DAS.DebugOut = debugOut
local p = debugOut

function DAS.Report(text)
	if not DAS.GetShutUp() then d(text) end
end

--==============================
--======= Event hooks  =========
--==============================

local function OnGroupTypeChanged(eventCode, unitTag)
	if IsUnitGrouped(UNITTAG_PLAYER) then
        if not DAS.GetAutoShare() and DAS.GetResetAutoShareOnNewGroup() then
            DAS.SetAutoShare(true)
        end
        return
    end

    if DAS.GetStopInviteOnDegroup() then DAS.SetAutoInvite(false) end

end

local function forceRefreshControl()
    DAS.RefreshControl(true)
end

local function OnQuestAdded(eventCode, journalIndex, questName, objectiveName)

	local zoneId = DAS.GetZoneId()
	if not DAS.GetActiveIn(zoneId) 			then return end
	if not GetIsQuestSharable(journalIndex) then return end
	local shareables = DAS.shareables[zoneId] or {}

	if nil ~= shareables[questName] then
		DAS.LogQuest(questName, false)
		zo_callLater(forceRefreshControl, 700)
	end
end

local function OnQuestShared(eventCode, questId)
    p(zo_strformat("<<1>> \t <<2>>", questId, questName))
	if not allDailyQuestIds[questId] then return end
	local zoneQuests = DAS.questIds[DAS.GetZoneId()] or {}

	if zoneQuests[questId] then
        if DAS.GetAutoDeclineShared() then
            DAS.Report("DailyAutoShare declined a quest for you. Type /DailyAutoShare disabledecline to stop it from doing so.")
            DeclineSharedQuest(questId)
        else
            AcceptSharedQuest(questId)
            zo_callLater(forceRefreshControl, 500)
        end
    end
end

local function OnChatMessage(eventCode, channelType, fromName, messageText, _, fromDisplayName)
    return DAS.OnChatMessage(eventCode, channelType, fromName, messageText, _, fromDisplayName)
end

local function OnPlayerActivated(eventCode)
	local active 		= DAS.GetActiveIn()
	DAS.SetHidden(not active)
    DAS.SetAutoInvite(DAS.GetAutoInvite()) -- disables if we aren't group lead
    DAS.SetChatListenerStatus(DAS.autoInviting)
    DAS.guildInviteText = DAS.GetGuildInviteText()
    DAS.cacheChatterData()
end

local function OnUnitCreated(eventCode, unitTag)
    local unitZone = GetZoneId(GetUnitZoneIndex(unitTag))
    if not DAS.GetActiveIn(unitZone) then return end
    if GetUnitDisplayName(unitTag) == cachedDisplayName then return end
    DAS.TryShareActiveDaily(unitZone)
end

local function OnQuestToolUpdate()
	forceRefreshControl()
end

local function OnQuestRemoved(eventCode, isCompleted, journalIndex, questName, zoneIndex, poiIndex, questId)

    local zoneId = DAS.GetZoneId()
    local zoneIds = DAS.questIds[zoneId] or {}
    -- is it a daily quest, and are we logging?
    if not (zoneIds[questId] and DAS.GetActiveIn(zoneId)) then return end

	DAS.LogQuest(questName, isCompleted)

    -- set auto invite off until the questlog has refreshed
	local autoInvite = DAS.GetAutoInvite()
    DAS.SetAutoInvite(false)

    zo_callLater(function()
        DAS.SetAutoInvite(autoInvite)
        forceRefreshControl()
    end, 5000)
end

local function deleteYesterdaysLog()
	-- kill yesterday's log, we don't need it
	local currentDate = tonumber(GetDate())
	if (nil ~= DAS.globalSettings and nil ~= DAS.globalSettings.lastLogDate) and (DAS.globalSettings.lastLogDate < currentDate) then
	if nil == DAS.Log then DAS.Log = {} end
		DAS.Log[DAS.globalSettings.lastLogDate] = nil
		DAS.globalSettings.lastLogDate = currentDate
	end
end

local alreadyRefreshing = false
local function questRefresh()
    alreadyRefreshing = false
    DAS.RefreshControl(true)
end
local function queueQuestRefresh()
    if alreadyRefreshing then return end
    alreadyRefreshing = true
    zo_callLater(questRefresh, 600)
end

local function hookQuestTracker()
    if FOCUSED_QUEST_TRACKER and FOCUSED_QUEST_TRACKER.ForceAssist then
        ZO_PreHook(FOCUSED_QUEST_TRACKER, "ForceAssist", queueQuestRefresh)
    end

end

--==============================
--= DailyAutoShare_Initialize ==
--==============================

local function RegisterEventHooks()

	DailyAutoShare.Fragment 	= ZO_HUDFadeSceneFragment:New(DasControl)

	SCENE_MANAGER:GetScene("hud"  ):AddFragment(DailyAutoShare.Fragment)
	SCENE_MANAGER:GetScene("hudui"):AddFragment(DailyAutoShare.Fragment)
	hookQuestTracker()

	em:RegisterForEvent(DAS.name, EVENT_PLAYER_ACTIVATED, 		OnPlayerActivated)

	em:RegisterForEvent(DAS.name, EVENT_QUEST_ADDED, 			OnQuestToolUpdate)
	em:RegisterForEvent(DAS.name, EVENT_QUEST_REMOVED, 			OnQuestRemoved)
	em:RegisterForEvent(DAS.name, EVENT_TRACKING_UPDATE, 		OnQuestToolUpdate)

	em:RegisterForEvent(DAS.name, EVENT_QUEST_ADDED, 			OnQuestAdded)
	em:RegisterForEvent(DAS.name, EVENT_QUEST_REMOVED, 			OnQuestRemoved)
	em:RegisterForEvent(DAS.name, EVENT_QUEST_SHARED, 			OnQuestShared)

	em:RegisterForEvent(DAS.name, EVENT_GROUP_TYPE_CHANGED,     OnGroupTypeChanged)
	em:RegisterForEvent(DAS.name, EVENT_UNIT_CREATED,	 		OnUnitCreated)
	em:RegisterForEvent(DAS.name, EVENT_UNIT_DESTROYED, 		OnGroupTypeChanged)

	em:RegisterForEvent(DAS.name, EVENT_CHAT_MESSAGE_CHANNEL,   OnChatMessage)
	-- DasControl:OnMoveStop
	-- DailyAutoShare.SaveControlLocation(self)
end


local function resetQuests()
    local currentDate = tonumber(GetDate())
    DAS.todaysLog = {}
    DAS.globalSettings.completionLog[currentDate] = DAS.todaysLog
    forceRefreshControl()
end
local typeTable = "table"
local function isEmpty(tbl)
    if not tbl then return true end
    local ret = true
    for key, value in pairs(tbl) do
        if type(value) == typeTable then
            ret = ret and isEmpty(value)
        else
            ret = false
        end
    end
    return ret
end
-- has to be a local var, lua error if not
-- Keep outside of function namespace so we can overwrite it for debugging
local afterEight = tonumber(GetTimeString():sub(0, 2)) >= 08
local function handleLog(forceReset)
    DAS.globalSettings.completionLog = DAS.globalSettings.completionLog or {}
    local allLogs = DAS.globalSettings.completionLog
    local currentDate = tonumber(GetDate())
    allLogs[currentDate] = allLogs[currentDate] or {}

    local logSize, lastDate = NonContiguousCount(DAS.globalSettings.completionLog)

    if forceReset then
        return resetQuests()
    end
    local counter = 0
    for dateNumber, dateLog in pairs(DAS.globalSettings.completionLog) do
        counter = counter + 1
        if dateNumber < currentDate then
            lastDate = dateNumber
        end
        if counter < logSize-2 then
            DAS.globalSettings.completionLog[dateNumber] = nil
        end
    end

    local afterEight = tonumber(GetTimeString():sub(0, 2)) >= 08 -- has to be a local var, lua error if not
    if (not afterEight) and isEmpty(DAS.todaysLog) and lastDate ~= currentDate then
        DAS.globalSettings.completionLog[currentDate] = ZO_DeepTableCopy(DAS.globalSettings.completionLog[lastDate], {})
        for charName, charLog in pairs(DAS.globalSettings.completionLog[currentDate]) do
            for questName, questData in pairs(charLog) do
                questData.afterEight = false
            end
        end
    end

    DAS.todaysLog = DAS.globalSettings.completionLog[currentDate]
end
DAS.handleLog = handleLog

local function minimiseOnStartup()
	DAS.SetMinimized(DAS.GetSettings().startupMinimized)
end
--==============================
--===== Rise, my minion!  ======
--==============================

function DailyAutoShare_Initialize(eventCode, addonName)

	if addonName ~= DAS.name then return end

	DAS.settings        = ZO_SavedVars:New("DAS_Settings", 1, "DAS_Settings", defaults)
	DAS.globalSettings  = ZO_SavedVars:NewAccountWide("DAS_Globals", 1, "DAS_Global", defaults)
    DAS.pdn = GetUnitDisplayName(UNITTAG_PLAYER)

	RegisterEventHooks()

	DAS.CreateMenu(DAS.settings, defaults)
	DAS.CreateGui()

    -- local timetoreset = (GetTimeStamp() - 60*60*7)%86400
    -- zo_callLater(resetQuests, timetoreset)


    handleLog()
    zo_callLater(OnPlayerActivated, 5000)
    zo_callLater(minimiseOnStartup, 5500)
	EVENT_MANAGER:UnregisterForEvent("DailyAutoShare", EVENT_ADD_ON_LOADED)

end


ZO_CreateStringId("SI_BINDING_NAME_TOGGLE_DAS_GUI",  GetString(DAS_SI_TOGGLE))
ZO_CreateStringId("SI_BINDING_NAME_TOGGLE_DAS_LIST", GetString(DAS_SI_MINIMISE))
EVENT_MANAGER:RegisterForEvent("DailyAutoShare", EVENT_ADD_ON_LOADED, DailyAutoShare_Initialize)