-- Copyright (C) 2010 Tyson Brown
-- 
-- This file is part QuestHelper2, an AddOn for World of Warcraft.
-- 
-- QuestHelper2 is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
-- 
-- QuestHelper2 is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
-- 
-- You should have received a copy of the GNU General Public License
-- along with QuestHelper2. If not, see <http://www.gnu.org/licenses/>.

if LibDebug then LibDebug() end
local shared = select(2, ...)

-- This file is in charge of creating the frames for automatically accepting or completing quests, and
-- adding them to the tracker.

-- Quests the player actually has.
local quest_set = {}

-- Quest offers and what-not.
local offer_set, complete_set = {}, {}

local unused_frames = {}
local offer_frames = {}
local complete_frames = {}

local function onClick(self)
  self.doIt(GetQuestLogIndexByID(self.quest_id))
end

local old_setWidth
local function setWidth(frame, w)
  old_setWidth(frame, w)
  frame.text:SetWidth(w-24)
  frame:SetHeight(math.max(33, frame.text:GetStringHeight()))
end

local function shineUpdate(self, delta)
  local a = self.a - delta*0.02
  
  if a < 0 then
    self:SetScript("OnUpdate", nil)
    return
  end
  
  self.a = a
  self.shine0:SetAlpha(a)
  self.shine1:SetAlpha(a*.3)
  
  self.shine0:SetTexCoord(a*6,a*6+1,0,1)
  self.shine1:SetTexCoord(a*-10+.2,a*-10+1.4,0,1)
end

local function createFrame(quest_id, method)
  local title = GetQuestLogTitle(GetQuestLogIndexByID(quest_id))
  
  if not title or title == "" then
    -- Blizzard checks for this too, I think it's a kludge.
    return
  end
  
  local frame = next(unused_frames)
  
  if frame then
    unused_frames[frame] = nil
  else
    frame = CreateFrame("Button", nil, UIParent)
    
    old_setWidth = frame.SetWidth
    frame.SetWidth = setWidth
    frame:SetScript("OnClick", onClick)
    frame.text = frame:CreateFontString(nil, "OVERLAY", "QuestTitleFontBlackShadow")
    frame.text:SetPoint("LEFT", 24, 0)
    frame.text:SetJustifyH("LEFT")
    frame.icon = frame:CreateTexture(nil, "ARTWORK")
    frame.icon:SetWidth(19)
    frame.icon:SetHeight(33)
    frame.icon:SetPoint("LEFT")
    frame.icon:SetTexture("Interface\\QuestFrame\\AutoQuest-Parts.blp")
    
    frame.shine0 = frame:CreateTexture(nil, "BACKGROUND")
    frame.shine0:SetAllPoints()
    frame.shine0:SetBlendMode("ADD")
    frame.shine0:SetTexture("Interface\\AddOns\\QuestHelper2\\AutoQuest\\Shine.tga", true)
    frame.shine0:SetVertexColor(1,.75,.5)
    
    frame.shine1 = frame:CreateTexture(nil, "BACKGROUND")
    frame.shine1:SetAllPoints()
    frame.shine1:SetBlendMode("ADD")
    frame.shine1:SetTexture("Interface\\AddOns\\QuestHelper2\\AutoQuest\\Shine.tga", true)
    frame.shine1:SetVertexColor(.5,.75,1)
  end
  
  frame.text:SetText(GetQuestLogTitle(GetQuestLogIndexByID(quest_id)) or ("Quest #"..quest_id))
  
  frame.quest_id = quest_id
  frame.doIt = method
  
  frame.a = .5
  frame:SetScript("OnUpdate", shineUpdate)
  
  return frame
end

local function releaseFrame(frame)
  shared.removeFrameFromTracker(frame)
  unused_frames[frame] = true
end

local visited_quests = {}
local function updateAutoQuestFrames(quest_complete_id)
  for i = 1,GetNumAutoQuestPopUps() do
    local quest_id, popup_type = GetAutoQuestPopUp(i)
    
    visited_quests[quest_id] = popup_type
    
    if popup_type == "OFFER" then
      offer_set[quest_id] = true
    elseif popup_type == "COMPLETE" then
      complete_set[quest_id] = true
    else
      print("Warning: Unknown popup type: "..popup_type)
    end
  end
  
  if quest_complete_id then
    -- This is pretty much a hack, because GetAutoQuestPopUp doesn't seem to include the quest announced by QUEST_AUTOCOMPLETE.
    -- If a quest_id is included in this call, we'll pretend it was included, even though it wasn't.
    visited_quests[quest_complete_id] = "COMPLETE"
    complete_set[quest_complete_id] = true
  end
  
  for quest_id in pairs(offer_set) do
    if visited_quests[quest_id] ~= "OFFER" then
      offer_set[quest_id] = nil
    end
  end
  
  for quest_id in pairs(complete_set) do
    if visited_quests[quest_id] ~= "COMPLETE" then
      complete_set[quest_id] = nil
    end
  end
  
  table.wipe(visited_quests)
  
  for quest_id in pairs(offer_set) do
    if quest_set[quest_id] then
      local frame = offer_frames[quest_id]
      if frame then
        -- The player is on this quest, remove the offer for it.
        offer_frames[quest_id] = nil
        releaseFrame(frame)
      end
    else
      if not offer_frames[quest_id] then
        -- Create an offer frame for this quest.
        local frame = createFrame(quest_id, ShowQuestOffer)
        if frame then
          frame.icon:SetTexCoord(0.13476563, 0.171875, 0.015625, 0.53125)
          shared.addFrameToTracker(frame, 0, true)
          offer_frames[quest_id] = frame
        end
      end
    end
  end
  
  for quest_id in pairs(complete_set) do
    if quest_set[quest_id] then
      if not complete_frames[quest_id] then
        -- The player is on this quest, and there is an offer to complete it, create a frame to show this.
        local frame = createFrame(quest_id, ShowQuestComplete)
        if frame then
          frame.icon:SetTexCoord(0.17578125, 0.21289063, 0.015625, 0.53125)
          shared.addFrameToTracker(frame, -1, true)
          complete_frames[quest_id] = frame
        end
      end
    else
      local frame = complete_frames[quest_id]
      if frame then
        -- The player isn't on the quest we were offering to complete, remove the frame showing it.
        complete_frames[quest_id] = nil
        releaseFrame(frame)
      end
    end
  end
  
  for quest_id, frame in pairs(offer_frames) do
    if not offer_set[quest_id] then
      offer_frames[quest_id] = nil
      releaseFrame(frame)
    end
  end
  
  for quest_id, frame in pairs(complete_frames) do
    if not complete_set[quest_id] then
      complete_frames[quest_id] = nil
      releaseFrame(frame)
    end
  end
end

shared.onQuestAdd(function (quest_id)
  quest_set[quest_id] = true
  shared.callOnce(updateAutoQuestFrames)
end)

shared.onQuestRemove(function (quest_id)
  quest_set[quest_id] = nil
  shared.callOnce(updateAutoQuestFrames)
end)

shared.onEvent("QUEST_AUTOCOMPLETE", updateAutoQuestFrames)
shared.onEvent("QUEST_DETAIL", shared.callOnce, updateAutoQuestFrames)
shared.onEvent("QUEST_LOG_UPDATE", shared.callOnce, updateAutoQuestFrames)
shared.onLoad(updateAutoQuestFrames)
