DailyAutoShare              = DailyAutoShare or {}
DAS                         = DailyAutoShare
local DailyAutoShare        = DailyAutoShare

DAS.name                    = "DailyAutoshare"
DAS.version                 = "3.3.0"
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

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('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("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()
    ZO_PreHook(FOCUSED_QUEST_TRACKER, "ForceAssist", DAS.questTrackerUpdate)

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)
    local allLogs = DAS.globalSettings.completionLog
    local currentDate = tonumber(GetDate())
    DAS.globalSettings.completionLog[currentDate] = DAS.globalSettings.completionLog[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 ~="DailyAutoShare" then return end

	DailyAutoShare.settings = ZO_SavedVars:New("DAS_Settings", 0.2, nil, defaults)
	DailyAutoShare.globalSettings = ZO_SavedVars:NewAccountWide("DAS_Globals", 0.2, "DAS_Global", defaults)
    DAS.pdn = GetUnitDisplayName('player')

	RegisterEventHooks()

	DailyAutoShare.CreateMenu(DailyAutoShare.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)