local DAS = DailyAutoShare
local visibilityStateCached = false
local stateIsHidden 		= false
local stateIsMinimised 		= false
local visibleButtonIndex	= 0
DAS.sublabels = {}
DAS.labels = {}
local numLabels             = 0


local labelTexts = {}

local p = DAS.DebugOut

local function isHidden()
	return (not DAS.GetActiveIn()) or DAS.GetHidden() or (DAS.GetAutoHide() and (not DAS.OpenDailyPresent()))
end

local function isMinimised()
	return DAS.GetUserMinimised() or (not isHidden()) and (DAS.GetAutoMinimize() and (not DAS.OpenDailyPresent()))
end

local function cacheVisibilityStatus(forceOverride)
	stateIsHidden				= isHidden()
	stateIsMinimised			= isMinimised()
end

function DAS.RefreshControl(refreshQuestCache)

  -- p("DAS.RefreshControl(" .. tostring(refreshQuestCache).. ")")
	if not DAS.HasActiveDaily() then
		DAS.SetAutoInvite(false)
  end

	cacheVisibilityStatus()
	DasHandle:SetHidden(  stateIsHidden)
	DasControl:SetHidden( stateIsHidden)
	DasList:SetHidden(    stateIsMinimised or stateIsHidden)
  DAS.RefreshLabelsWithDelay()

end
local function SetAlpha(control, value)
	if not control then return end
	if value then
		control:SetAlpha(1)
    else
		control:SetAlpha(0.3)
  end
end

local function SetAutoInviteButton(value)
	if value then
		DasButtonInvite:SetAlpha(1)
		DasButtonInvite:SetNormalTexture("/DailyAutoShare/textures/invite_active.dds")
		DasList_BG:SetEdgeColor(ZO_SELECTED_TEXT:UnpackRGBA())
    else
		DasButtonInvite:SetAlpha(0.5)
		DasButtonInvite:SetNormalTexture("/DailyAutoShare/textures/invite_up.dds")
		DasList_BG:SetEdgeColor(ZO_DEFAULT_TEXT:UnpackRGBA())
  end

end

local function SetLockedButton(value)
	if value then
		DasButtonLock:SetNormalTexture("/esoui/art/miscellaneous/locked_up.dds")
		DasButtonLock:SetMouseOverTexture("/esoui/art/miscellaneous/unlocked_down.dds")
		DasButtonLock:SetPressedTexture("/esoui/art/miscellaneous/unlocked_down.dds")
		DasControl:SetMovable(false)
    else
		DasButtonLock:SetNormalTexture("/esoui/art/miscellaneous/unlocked_up.dds")
		DasButtonLock:SetMouseOverTexture("/esoui/art/miscellaneous/locked_down.dds")
		DasButtonLock:SetPressedTexture("/esoui/art/miscellaneous/locked_down.dds")
		DasControl:SetMovable(true)
  end
end

local function SetMinimizedButton(value)

	local minimizedTex = "/esoui/art/buttons/plus"
	local maximizedTex = "/esoui/art/buttons/minus"
	local tex = (value and minimizedTex) or maximizedTex
	DasButtonMinmax:SetNormalTexture(tex.. "_up.dds")
	DasButtonMinmax:SetMouseOverTexture(tex.. "_over.dds")
	DasButtonMinmax:SetPressedTexture(tex.. "_down.dds")

end


local function setButtonStates()
	SetAutoInviteButton(DAS.GetAutoInvite())
	SetLockedButton(DAS.GetLocked())

	SetAlpha(DasButtonAccept, DAS.GetAutoAcceptShared())
	SetAlpha(DasButtonShare, DAS.GetAutoShare())

	DasButtonSpam:SetAlpha(0.7)
end
DAS.SetButtonStates = setButtonStates

function DAS.QuestLabelClicked(control, mouseButton)

  DAS.SetSubLabels(control.dataQuestList)

  if mouseButton == MOUSE_BUTTON_INDEX_RIGHT then -- and isValidJournalIndex then
		return DAS.OnRightClick(control)
  end

	local journalIndex          = control.dataJournalIndex or 99

	if IsValidQuestIndex(journalIndex) then
    if journalIndex ~= DAS.trackedIndex then
      FOCUSED_QUEST_TRACKER:ForceAssist(journalIndex)
      else
      ShareQuest(journalIndex)
    end
  end
end

function DAS.Donate(control, mouseButton)
	local amount = 2000
	if mouseButton == 2 then
		amount = 1000
    elseif mouseButton == 3 then
		amount = 25000
  end

	SCENE_MANAGER:Show('mailSend')
	zo_callLater(function()
		ZO_MailSendToField:SetText("@manavortex")
		ZO_MailSendSubjectField:SetText("Thank you for DailyAutoShare!")
		QueueMoneyAttachment(amount)
		ZO_MailSendBodyField:TakeFocus()
  end, 200)
end

function DAS.MinMaxButton()
	local newMinimisedValue = not (isMinimised())
	SetMinimizedButton(newMinimisedValue)
	DAS.SetUserMinimised(newMinimisedValue)
	local stateIsMinimised = newMinimisedValue
	DAS.RefreshControl()
end

local function shouldHideLabel(questName, zoneId)
  local questLists = DAS.GetZoneQuests(zoneId) or {}
	-- d(zo_strformat("should <<1>> be hidden?", questName))
	for questListName, questListData in pairs(questLists) do
		if questListData[questName] then
      -- d(questName)
      -- d("active: " .. tostring(DAS.GetQuestListItem(zoneId, questListName, "active")))
      -- d("hidden: " .. tostring(DAS.GetQuestListItem(zoneId, questListName, "invisible")))
			return  (
				(not DAS.GetQuestListItem(zoneId, questListName, "active")) or
      DAS.GetQuestListItem(zoneId, questListName, "invisible"))
    end
  end
	return false
end

local function setControlText(label, hidden)
  local state = label.dataQuestState
  if label.dataJournalIndex == DAS.trackedIndex then
    label:SetText("* " .. label.dataTitle)
    elseif hideLabel then
    label:SetText("")
    label:SetVisible(false)
    return
    else
    label:SetText(label.dataTitle)
  end

  if label.dataQuestState == DAS_STATUS_COMPLETE then
    label:SetState(BSTATE_DISABLED)
    elseif label.dataQuestState == DAS_STATUS_ACTIVE then
    label:SetState(BSTATE_PRESSED)
    else --if label.dataQuestState == DAS_STATUS_OPEN then
    label:SetState(BSTATE_NORMAL)
  end

end

function setLabelTable(questTable)

  local status = DAS_STATUS_COMPLETE
  local index = 1
  local questName, tmpStatus = nil

  for idx, tmpQuestName in pairs(questTable) do

    labelTexts[tmpQuestName] = true
    questName = questName or tmpQuestName
    tmpStatus = DAS.GetQuestStatus(tmpQuestName)
    if tmpStatus == DAS_STATUS_ACTIVE then
      status = tmpStatus
      questName = tmpQuestName
      elseif status ~= DAS_STATUS_ACTIVE and status ~= DAS_STATUS_OPEN then
      status = tmpStatus
    end
  end
  questName = questName or ""
  return questName, status
end


local sep = "%s%w%w%s"
local function makeSubLabelTitle(str, str2)
  if not str then return end
  local idx = string.find(str, sep)
  if nil == idx then return str end
  return string.sub(str, 0, idx+3) .. "..."
end

function DAS.SetSubLabels(questTable)
  DasSubList:SetHidden(nil == questTable or {} == questTable)
  if DasSubList:IsHidden() then return end

  local status = DAS_STATUS_COMPLETE
  local index = 1
  for idx, questName in pairs(questTable) do
    index = idx
    local label = DAS.sublabels[idx]

    label.dataJournalIndex 	= DAS.GetLogIndex(questName)
    local bingoString, bingoIndex = DAS.GetBingoStringFromQuestName(questName)
    label.dataBingoString 	= bingoString
    label.dataBingoIndex 	  = bingoIndex
    label.dataQuestName		  = questName
    label.dataTitle         = questName
    label.dataQuestState    = DAS.GetQuestStatus(questName)
    label:SetHidden(false)
    if label.dataQuestState == DAS_STATUS_ACTIVE then
      table.insert(activeZoneQuests, label.dataJournalIndex)
      status = label.dataQuestState
      elseif status ~= DAS_STATUS_ACTIVE and status ~= DAS_STATUS_OPEN then
      status = label.dataQuestState
    end
    setControlText(label)
  end
  for idx=index, #DAS.sublabels do
    local label = DAS.sublabels[idx]
    label.dataJournalIndex 	= nil
    label.dataBingoString 	= nil
    label.dataQuestName		= nil
    label.dataQuestState   = DAS_STATUS_OPEN
    label:SetText("")
    label:SetHidden(true)
  end

  DAS.SetLabelFontSize()
  return status
end
local typeTable = "table"

function DAS.setLabels(zoneQuests)

  zoneQuests = zoneQuests or DAS.GetZoneQuests()
  labelTexts = {}

  -- p("DAS.setLabels")
  DAS.activeZoneQuests = {}
  numLabels = 1
  local questName
	for index, questNameOrTable in pairs(zoneQuests) do

    if not labelTexts[questNameOrTable] then
      label = DAS.labels[numLabels] -- despite the name these are actually buttons

      if nil ~= label then
        local status                      = DAS_STATUS_OPEN
        visibleButtonIndex 			          = visibleButtonIndex +1

        if type(questNameOrTable) == typeTable then
          label.dataQuestList 	          = ZO_DeepTableCopy(questNameOrTable, {})
          label.dataQuestName, status     = setLabelTable(questNameOrTable)
          label.dataQuestState            = status or DAS_STATUS_OPEN
          label.dataTitle                 = makeSubLabelTitle(label.dataQuestList[1], label.dataQuestList[2]) or questName

          else
          label.dataQuestList 	  = nil
          label.dataTitle         = questNameOrTable
          label.dataQuestName     = questNameOrTable
          label.dataQuestState    = DAS.GetQuestStatus(label.dataQuestName)
        end

        local hideLabel = (hideCompleted and label.dataQuestState == DAS_STATUS_COMPLETE) or shouldHideLabel(label.dataQuestName, zoneId)

        -- d(zo_strformat("DAS: <<1>> state <<2>>", label.dataQuestName, label.dataQuestState))
        label:SetHidden(hideLabel)
        label.dataJournalIndex 	= DAS.GetLogIndex(label.dataQuestName)
        bingoString, bingoIndex = DAS.GetBingoStringFromQuestName(label.dataQuestName)
        label.dataBingoString 	= bingoString
        label.dataBingoIndex 	= bingoIndex
        label.dataTitle         = label.dataTitle or ""

        if label.dataQuestState == DAS_STATUS_ACTIVE then
          table.insert(DAS.activeZoneQuests, label.dataJournalIndex)
        end


        labelTexts[label.dataQuestName] = true
        setControlText(label, hideLabel)

        numLabels = numLabels + 1


      end -- nil check end
    end
  end -- for loop end

  return numLabels
end

function DAS.RefreshLabelsWithDelay() zo_callLater(DAS.RefreshLabels, 500) end

function DAS.RefreshLabels(forceQuestRefresh, forceSkipQuestRefresh)


  forceQuestRefresh = forceQuestRefresh or DAS.questCacheNeedsRefresh
  p("DAS.RefreshLabels(" .. tostring(forceQuestRefresh) .. ", " .. tostring(forceSkipQuestRefresh) .. ")")
  -- error("RefreshLabels called")

	cacheVisibilityStatus()
	setButtonStates()

	local hideCompleted = DAS.GetHideCompleted()
	local hidden 		= DasList:IsHidden()
	local label, questIndex, tracked
	if not forceSkipQuestRefresh then
		DAS.RefreshQuestLogs(forceQuestRefresh)
    if FOCUSED_QUEST_TRACKER and FOCUSED_QUEST_TRACKER.assistedData then
      DAS.trackedIndex = FOCUSED_QUEST_TRACKER.assistedData.arg1
    end
  end

	local questList = DAS.QuestLists[DAS.GetZoneId()]
  local zoneQuests = DAS.GetZoneQuests()

  DAS.setLabels(zoneQuests)

	for bIndex=#DAS.GetZoneQuests()+1, #DAS.labels do
		if DAS.labels[bIndex] then
			DAS.labels[bIndex]:SetHidden(true)
      DAS.labels[bIndex]:SetText("")
    end
  end
	DAS.RefreshFullBingoString()
	DAS.SetLabelFontSize()
end

function DAS.RefreshGui(hidden)
  -- p("DAS.RefreshGui")
  if not DAS.GetActiveIn() then
    DasControl:SetHidden(true)
    return
  end

	hidden = hidden or (DAS.GetHidden() or (DAS.GetAutoHide() and not DAS.OpenDailyPresent()) or #DAS.GetZoneQuests(zoneId) == 0)
	local minmaxed = stateIsMinimised
	SetMinimizedButton(minmaxed)
	DasList:SetHidden(minmaxed)
	DasControl:SetHidden(hidden)
	DasHandle:SetMovable(not DAS.GetLocked())
  DAS.RefreshLabelsWithDelay()
end

function DAS.AnchorList()
  DasList:ClearAnchors()
  if DAS.GetUpsideDown() then
    DasList:SetAnchor(BOTTOM, DasHandle, TOP)
    else
    DasList:SetAnchor(TOP, DasHandle, BOTTOM)
  end
  DasSubList:ClearAnchors()
  if DAS.GetSettings().tooltipRight then
    DasSubList:SetAnchor(LEFT, DasList, RIGHT)
    else
    DasSubList:SetAnchor(RIGHT, DasList, LEFT)
  end
end

local function setFontSize(labelList)
  local labelHeight 	= 30
  local fontScale 	= DAS.GetFontSize()

  local totalHeight 	= 0
  local hidden		= false
  local parent        = nil
  local maxWidth      = DasHandle:GetWidth()

  for index, control in pairs(labelList) do
    parent = parent or control:GetParent()
    maxWidth = math.max(maxWidth, control:GetWidth())
    control:SetScale(fontScale)
    if control:IsHidden() then
      control:SetHeight(0)
      else
      control:SetHeight(labelHeight)
      control:SetScale(fontScale)
    end
  end
  parent:SetWidth(maxWidth)
end
DAS.setFontSize = setFontSize

local function setGuiHeight()
  local buttonIndex = numLabels or 0
  local listHeight = DasHeader:GetHeight() + buttonIndex*(DAS.labels[1]:GetHeight() + 2)
  DasList:SetHeight(listHeight)
  DasControl:SetHeight(listHeight + DasHandle:GetHeight())
end
DAS.SetGuiHeight = setGuiHeight

function DAS.SetLabelFontSize()

  setFontSize(DAS.labels)
  setFontSize(DAS.sublabels)
  DAS.SetGuiHeight()
end


function DAS.CreateGui()

  local function setupGuiLabels()

    local predecessor 	    = DasHeader
    local offsetX, offsetY  = 10, 10

    for i=1, 28 do
      local button 	= WINDOW_MANAGER:CreateControlFromVirtual("Das_Label_"..tostring(i), DasList, "Das_Label")
      button:SetAnchor(TOPLEFT, predecessor, BOTTOMLEFT, 0, offsetY)
      predecessor 	= button
      offsetY 		= 0
      table.insert(DAS.labels, button)
    end

    local spacer = WINDOW_MANAGER:CreateControlFromVirtual("Das_Spacer_1", DasList, "DasInvisibleFooterSpacer")
    spacer:SetAnchor(TOPLEFT, predecessor, BOTTOMLEFT, 0, offsetY)

    predecessor 	    = DasSubList
    offsetY 		    = 10

    local anchor        = TOPLEFT
    for i=1, 15 do
      local button 	= WINDOW_MANAGER:CreateControlFromVirtual("Das_Sublabel_"..tostring(i), DasSubList, "Das_Label")
      button:SetAnchor(TOPLEFT, predecessor, anchor, offsetX, offsetY)
      predecessor 	= button
      offsetY 		= 0
      offsetX 		= 0
      anchor 		    = BOTTOMLEFT

      table.insert(DAS.sublabels, button)
    end
    local spacer = WINDOW_MANAGER:CreateControlFromVirtual("Das_Spacer_2", DasSubList, "DasInvisibleFooterSpacer")
    spacer:SetAnchor(TOPLEFT, predecessor, BOTTOMLEFT, 0, offsetY)

    DAS.SetLabelFontSize()
  end

  setupGuiLabels()
  DAS.LoadControlLocation(DasControl)
  -- DAS.LoadControlLocation(DasButton)

  DAS.AnchorList()
  SetMinimizedButton(DAS.GetMinimized())

  DAS.RefreshGui()
  zo_callLater(function() DAS.SetLabelFontSize() end, 2000)
end