-- This file is a private addition by Portalz - officialportalz@gmail.com.
-- its an absolute monstrosity of a mess, but its my mess i coded quickly but carefully
-- It is not part of the GuildMap MPL 2.0 codebase.
-- All rights reserved.

-- local GuildMapUI = {}
-- _G["GuildMapTest"] = GuildMapTest

-- working on getting cross guild working but its painful

local AceGUI = LibStub("AceGUI-3.0")
GMMW= GMMW or {}
GuildMapDB=GuildMapDB or {}
GuildMapDB.GMMW=GuildMapDB.GMMW or {}
local lastHealth=UnitHealth("player")
local deadPlayers={}
local groupList={}
guild_map_folder_name="GuildMap"
-- hooksecurefunc("UseItemByName", function(itemName)
--     SendChatMessage("Using my Healthstone!", "SAY")
-- end)

-- local castFrameCheck = CreateFrame("Frame")
-- castFrameCheck:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")
-- castFrameCheck:SetScript("OnEvent", function(self, event, unit, spellName)
--     SendChatMessage("TEST", "CHANNEL", nil, GetChannelName(GuildMapDB.crossMyGuild))
--     -- if timeSinceLastUpdate > maxTimeBetweenUpdate then
--     --     sendPositionChat()
--     -- end
-- end)

function guild_map_redraw_curr_pins()
    for waypoint,pin in pairs(guild_map_pins) do
        GuildMap:RemovePinsByTitle(pin.wp.title)
        GuildMap:CreateMapPin(waypoint, pin.wp.healthPercent, pin.remainingData.rank, pin.remainingData.targetLevel, pin.remainingData.className, pin.wp.layer)
    end
end



function guild_map_clear_all_dbm()
    for _, pinSet in pairs(guild_map_pins) do
        if pinSet.title then
            guild_map_remove_dbm_waypoint(pinSet.title)
        end
    end
end

function guild_map_onlyfangs_check()
    local guildName, guildRank, guildRankIndex, guildID = GetGuildInfo("player")
    if guildName=="OnlyFangs" then
        guild_map_addon_onlyfangs_warning_frame()
    end
end

function guild_map_addon_onlyfangs_warning_frame()
    local addon_warning_frame = AceGUI:Create("Frame")
    addon_warning_frame:SetLayout("Flow")
    addon_warning_frame:SetTitle("GUILDMAP  "..guild_map_version.."  WARNING")
    addon_warning_frame:SetWidth(800)
    addon_warning_frame:SetHeight(300)

    local warning_text_label = AceGUI:Create("Label")
    warning_text_label:SetText("You have the public version of GuildMap installed\n as an OnlyFangs member.\n\n Delete this addon folder ('GuildMap') and go install:\n Then /reload somewhere safe.")
    warning_text_label:SetColor(1, .16, .16) 
    warning_text_label:SetWidth(800)
    warning_text_label:SetHeight(175)
    local fontName, fontHeight, fontFlags = GameFontNormal:GetFont()
    local newFontHeight = 30
    warning_text_label.label:SetFont(fontName, newFontHeight, fontFlags)
    addon_warning_frame:AddChild(warning_text_label)

    local guildMapOFURL = AceGUI:Create("EditBox")
    guildMapOFURL:SetText("https://www.curseforge.com/wow/addons/guildmapof")
    guildMapOFURL:SetWidth(350)
    addon_warning_frame:AddChild(guildMapOFURL)
end

function guild_map_draw_dbm_pins()
    for _, pinSet in pairs(guild_map_pins) do
        local player_mapID = C_Map.GetBestMapForUnit("player")
        if GuildMapDB.guild_map_DBM_menu_render and DBM and DBM.HudMap and not DBM:HasMapRestrictions() then
            if pinSet.title and player_mapID == pinSet.wp.mapID then
                if pinSet.remainingData.className and RAID_CLASS_COLORS[pinSet.remainingData.className] then
                    local r, g, b = RAID_CLASS_COLORS[pinSet.remainingData.className].r, RAID_CLASS_COLORS[pinSet.remainingData.className].g, RAID_CLASS_COLORS[pinSet.remainingData.className].b
                    -- DBM.HudMap:FreeEncounterMarkerByTarget(pinSet.title, "GuildMap")--Basically equiv of GuildMap:RemovePinsByTitle(title)
                    DBM.HudMap:RegisterPositionMarker(pinSet.title, "GuildMap", "party", pinSet.wp.x * 100, pinSet.wp.y * 100, 1.5, nil, r, g, b, 1, nil, true, pinSet.wp.mapID):Appear():RegisterForAlerts()
                end
            end
        end
    end
end



function guild_map_remove_dbm_waypoint(title)
    if DBM and DBM.HudMap then
        DBM.HudMap:FreeEncounterMarkerByTarget(title, "GuildMap")--Basically equiv of GuildMap:RemovePinsByTitle(title)
    end
end


function guild_map_check_group_member(name)
    return groupList[name]
end

local function updateGroupList()
    groupList={}
    local raidModifier=1
    local unitPrefix="party"
    if IsInRaid() then
        raidModifier=0
        unitPrefix="raid"
    end
    for i = 1, GetNumGroupMembers() - raidModifier do
        local unitID= unitPrefix .. i
        local name = UnitName(unitID)
        groupList[name]=true
        GuildMap:RemovePinsByTitle(name)
    end
end

local groupUpdate = CreateFrame("Frame")
groupUpdate:RegisterEvent("GROUP_ROSTER_UPDATE")

groupUpdate:SetScript("OnEvent", function(self, event, ...)
    if event == "GROUP_ROSTER_UPDATE" then
        if IsInGroup() then
            updateGroupList()
        else
            groupList={}
        end
    end
end)


function guild_map_feign_death_handle(class)
    if class=="HUNTER" and UnitIsFeignDeath("player") then
        return lastHealth
    else
        return nil
    end
end

function guild_map_check_received_healthPercent(name,healthPercent)
    if healthPercent==0 then
        deadPlayers[name]=1
    end
end

function guild_map_get_deadPlayer(name)
    return deadPlayers[name]
end

function guild_map_fix_healthpercent(healthPercent)
    if healthPercent==0 then
        if UnitIsDeadOrGhost("player") then
            return 0
        else
            return 1
        end
    else
        return healthPercent
    end
end

function GuildMapOnAddonMessageWrap(prefix, text, channel, sender)
    GuildMapOnAddonMessage(prefix, text, channel, sender)
end

function sendPositionWrap(x)
    message=GuildMap:SendGuildPosition(x)
    if message then
        C_ChatInfo.SendAddonMessage(ADDON_PREFIX, message, "GUILD")
    end
    timeSinceLastUpdate=0
    if not UnitIsFeignDeath("player") then
        lastHealth=UnitHealth("player")
    end
end

function sendPositionChat()
    message=GuildMap:SendGuildPosition(x)
    timeSinceLastUpdate=timeSinceLastUpdateExternal
    if message then
        C_ChatInfo.SendAddonMessage(ADDON_PREFIX, message, "GUILD")
        if GuildMapDB.crossBroadCast then
            SendChatMessage(message, "CHANNEL", nil, GetChannelName(GuildMapDB.crossMyGuild))
            timeSinceLastUpdate=0
            timeSinceLastUpdateExternal = 0
        end
    end
end

function checkChannels()
    channelStatus={}
    local channels = { GetChannelList() }
    if #channels == 0 then
        return
    end

    for i = 1, #channels, 3 do
        local channelNumber = channels[i]
        local channelName = channels[i + 1]
        local isPasswordProtected = channels[i + 2]
        local protectionStatus = isPasswordProtected and "Password Protected" or "No Password"
        if GuildMapDB.GMMW[channelName] then
            channelStatus[channelName]=true
            if not GuildMapDB.GMMW[channelName].setBroadcast then
                LeaveChannelByName(channelName)
            end
        end

        if GuildMapDB.crossMyGuild==channelName and not GuildMapDB.crossBroadCast then
            LeaveChannelByName(channelName)
        end
        -- print(string.format("%d: %s (%s)", channelNumber, channelName, protectionStatus))
    end

    for channeName,channel in pairs(GuildMapDB.GMMW) do
        local myGuild=false

        if not channelStatus[channeName] and  GuildMapDB.GMMW[channeName].setBroadcast then
            -- print("Attempting Connection to Connect to"..channeName)
            JoinChannelByName(channeName, channel.setEditPassword)
        end

        if channelName==GuildMapDB.crossMyGuild then
            myGuild=true
        end
    end

    if not myGuild and GuildMapDB.crossBroadCast then
        -- print("Attempting Connection to Connect to"..GuildMapDB.crossMyGuild)
        JoinChannelByName(GuildMapDB.crossMyGuild, GuildMapDB.crossMyPassword)
    end
end

function guild_map_check_stealth_render(x,y,mapID)
    return x==0 and y==0 and mapID==1458
end


function addDefaults(defaults)
    defaults.crossBroadCast=false
    defaults.crossMyGuild=nil
    defaults.crossMyPassword=nil
    defaults.otherGuilds=nil
    defaults.DBM_enabled=false
end

function isStealth()
    local stealthOption=false
    -- local _, class = UnitClass("player")
    --   if class=="DRUID" or class=="ROGUE" then
        stealthOption=true
    --   end
    return stealthOption
end

function guild_map_DBM_menu_render(container)
    local enable_dbm_hudmap = AceGUI:Create("CheckBox")
    enable_dbm_hudmap:SetLabel("Enable DBM Hudmap")
    enable_dbm_hudmap:SetWidth(300)
    enable_dbm_hudmap:SetValue(GuildMapDB.guild_map_DBM_menu_render)
    enable_dbm_hudmap:SetCallback("OnValueChanged", function(_, _, value)
        GuildMapDB.guild_map_DBM_menu_render = value
        enable_dbm_hudmap:SetValue(value)
        if value then
            guild_map_draw_dbm_pins()
        else
            guild_map_clear_all_dbm()
        end
    end)
    container:AddChild(enable_dbm_hudmap)
end

function crossGuildMyTab(container)
    local desc = AceGUI:Create("Label")
    desc:SetText("This is Tab 1")
    desc:SetFullWidth(true)
    container:AddChild(desc)
    
    local broadcastLocationOp = AceGUI:Create("CheckBox")
    broadcastLocationOp:SetLabel("Broadcast to other Guilds")
    broadcastLocationOp:SetWidth(300)
    broadcastLocationOp:SetValue(GuildMapDB.crossBroadCast)
    broadcastLocationOp:SetCallback("OnValueChanged", function(_, _, value)
        GuildMapDB.crossBroadCast = value
        broadcastLocationOp:SetValue(value)
        if not value then
            LeaveChannelByName(GuildMapDB.crossMyGuild)
        else
            JoinChannelByName(GuildMapDB.crossMyGuild, GuildMapDB.crossMyPassword)
        end
        sendPositionWrap(true)
    end)
    container:AddChild(broadcastLocationOp)
    
    -- local frame = AceGUI:Create("Frame")
    -- container.SetLayout("Flow")
    -- Add content to the frame
    local label1 = AceGUI:Create("Label")
    label1:SetText("Guild Channel")
    label1:SetWidth(350)
    container:AddChild(label1)

    local editBoxName = AceGUI:Create("EditBox")
    editBoxName:SetWidth(350)
    editBoxName:SetText(GuildMapDB.crossMyGuild or "Channel")
    prevEditBoxNameMy=GuildMapDB.crossMyGuild
    editBoxName:SetCallback("OnEnterPressed", function(_, _, value)
        if value then
            editBoxName:SetText(value:lower())
            GuildMapDB.crossMyGuild = value:lower()
            LeaveChannelByName(prevEditBoxNameMy)
            prevEditBoxNameMy=GuildMapDB.crossMyGuild
        end
        checkChannels()
    end)
    container:AddChild(editBoxName)

    local label2 = AceGUI:Create("Label")
    label2:SetText("Guild Password Case Sensitive")
    label2:SetWidth(350)
    container:AddChild(label2)

    local editBoxPassword = AceGUI:Create("EditBox")
    editBoxPassword:SetWidth(350)
    editBoxPassword:SetText(GuildMapDB.crossMyPassword or "Password")
    prevEditBoxName=GuildMapDB.crossMyPassword
    editBoxPassword:SetCallback("OnEnterPressed", function(_, _, value)
        GuildMapDB.crossMyPassword = value
        prevEditBoxName=GuildMapDB.crossMyPassword
        checkChannels()
    end)
    container:AddChild(editBoxPassword)
end

--add function to refresh channels --channels need prefix?

function crossGuildScrolLTab(container)
    local desc = AceGUI:Create("Label")
    desc:SetText("This is Tab 1")
    desc:SetFullWidth(true)
    container:AddChild(desc)


    local button = AceGUI:Create("Button")
    button:SetText("Add Guild")
    button:SetWidth(200)
    
    container:AddChild(button)

    
    local scrollFrame = AceGUI:Create("ScrollFrame")
    -- scrollFrame.SetLayout("Flow")
    scrollFrame:SetWidth(400)
    scrollFrame:SetHeight(350)
    button:SetCallback("OnClick", function(widget, event)
        --refresh tab
        container:ReleaseChildren()
        crossGuildScrolLTab(container)

        -- for key,block in pairs(GMMW) do
        --     block.setEditChannel=key
        --     local newBlock=createCrossGuildBlock(scrollFrame,container,block)
        --     scrollFrame:AddChild(newBlock)
            
        -- end

        local newBlock=createCrossGuildBlock(scrollFrame,container)
        scrollFrame:AddChild(newBlock)
    end)

    for key,block in pairs(GuildMapDB.GMMW) do
        block.setEditChannel=key
        local newBlock=createCrossGuildBlock(scrollFrame,container,block)
        scrollFrame:AddChild(newBlock)
        
    end

    container:AddChild(scrollFrame)
end

function createCrossGuildBlock(xfr,tabContainer,settings)
    local scrollFrame = AceGUI:Create("SimpleGroup")

    if not settings then
        settings= {
            setBroadcast=false,
            setEditChannel="Guild Channel",
            setEditPassword="Password"
        }
    end
    
    local broadcastLocationOp = AceGUI:Create("CheckBox")
    broadcastLocationOp:SetLabel("Enabled")
    broadcastLocationOp:SetWidth(200)
    broadcastLocationOp:SetValue(settings.setBroadcast)
    scrollFrame:AddChild(broadcastLocationOp)
    local label1 = AceGUI:Create("Label")
    label1:SetText("Guild Channel")
    label1:SetWidth(350)
    scrollFrame:AddChild(label1)

    
    local editBoxName = AceGUI:Create("EditBox")
    editBoxName:SetText(settings.setEditChannel)
    prevEditBoxName=settings.setEditChannel
    editBoxName:SetWidth(350)
    
    scrollFrame:AddChild(editBoxName)

    local label2 = AceGUI:Create("Label")
    label2:SetText("Guild Password Case Sensitive")
    label2:SetWidth(350)
    scrollFrame:AddChild(label2)

    local editBoxPassword = AceGUI:Create("EditBox")
    editBoxPassword:SetText(settings.setEditPassword)
    prevEditPassword=settings.setEditPassword
  
    editBoxPassword:SetWidth(350)
    scrollFrame:AddChild(editBoxPassword)


    broadcastLocationOp:SetCallback("OnValueChanged", function(_, _, value)
        broadcastLocationOp:SetValue(value)
        GuildMapDB.GMMW[editBoxName:GetText()]={
            setEditPassword=editBoxPassword:GetText(),
            setBroadcast=broadcastLocationOp:GetValue()
        }
        if not value then
            LeaveChannelByName(editBoxName:GetText())
            GuildMap:ClearAllWaypoints()
        else
            JoinChannelByName(editBoxName:GetText(), editBoxPassword:GetText())
        end
    end)

    editBoxPassword:SetCallback("OnEnterPressed", function(_, _, value)
        GuildMapDB.GMMW[editBoxName:GetText()]={
            setEditPassword=editBoxPassword:GetText(),
            setBroadcast=broadcastLocationOp:GetValue()
        }
        checkChannels()
    end)

    editBoxName:SetCallback("OnEnterPressed", function(_, _, value)
        if value then
            GuildMapDB.GMMW[prevEditBoxName]=nil
            editBoxName:SetText(value:lower())
            GuildMapDB.GMMW[value:lower()]={
                setEditPassword=editBoxPassword:GetText(),
                setBroadcast=broadcastLocationOp:GetValue()
            }
            LeaveChannelByName(prevEditBoxName)
            prevEditBoxName=value:lower()
            checkChannels()
        end
        
    end)
    
    local delete = AceGUI:Create("Button")
    delete:SetText("Delete")
    delete:SetWidth(200)
    delete:SetCallback("OnClick", function(widget, event)
        -- GMMW[editBoxName:GetText()]=nil
        tabContainer:ReleaseChildren()
        GuildMapDB.GMMW[editBoxName:GetText()]=nil
        crossGuildScrolLTab(tabContainer)
        LeaveChannelByName(editBoxName:GetText())
        -- for _,block in pairs(GuildMapDB.GMMW) do
        --     block.setEditChannel=_
        --     local newBlock=createCrossGuildBlock(xfr,tabContainer,block)
        --     xfr:AddChild(newBlock)
        -- end
    end)
    scrollFrame:AddChild(delete)
    local label3 = AceGUI:Create("Label")
    label3:SetText("    ")
    label3:SetWidth(350)
    scrollFrame:AddChild(label3)

    local separator = AceGUI:Create("Heading")
    -- separator:SetText("Button " .. i)
    separator:SetWidth(350)
    scrollFrame:AddChild(separator)

    scrollFrame:SetFullWidth(true)
    scrollFrame:SetFullHeight(true)
    -- scrollFrame:SetLayout("Fill")
    -- xfr:AddChild(scrollFrame)

    return scrollFrame
    
end

function GuildMapTabOptions(configFrame)
  -- function that draws the widgets for the first tab
  local function DrawGroup1(container)
    
  end
  
  -- function that draws the widgets for the second tab
  local function DrawGroup2(container)
    GuildMapUI:ShowConfigWindow(container)
  end
  
  -- Callback function for OnGroupSelected
  local function SelectGroup(container, event, group)
     container:ReleaseChildren()
     if group == "core" then
        DrawGroup2(container,isStealth())
    elseif group=="dbm" then
        guild_map_DBM_menu_render(container)
    elseif group == "tab2" then
        crossGuildMyTab(container)
     elseif group == "tab3" then
        crossGuildScrolLTab(container)
     end
  end
  
  -- Create the frame container
  local frame = AceGUI:Create("Frame")

--   Add the frame as a global variable under the name `MyGlobalFrameName`
    _G["GuildMapGFrameX"] = frame.frame
    -- Register the global variable `MyGlobalFrameName` as a "special frame"
    -- so that it is closed when the escape key is pressed.
    tinsert(UISpecialFrames, "GuildMapGFrameX")


    local frameHeight=565
    
    if isStealth() then
        frameHeight=610
    end
 
  frame:SetWidth(495)
  frame:SetHeight(frameHeight)



  frame:SetTitle("GuildMap Options")
  frame:SetStatusText("Discord: `portallz` for bugs")
  frame:SetCallback("OnClose", function(widget) AceGUI:Release(widget) end)
  -- Fill Layout - the TabGroup widget will fill the whole frame
  frame:SetLayout("Fill")
  
  -- Create the TabGroup
  local tab =  AceGUI:Create("TabGroup")
  tab:SetLayout("Flow")
  -- Setup which tabs to show
--   tab:SetTabs({{text="Core", value="core"}, {text="My Guild", value="tab2"},{text="Other Guilds", value="tab3"}})
-- if DBM then
    -- tab:SetTabs({{text="Core", value="core"}, {text="DBM", value="dbm"}})
-- else
  tab:SetTabs({{text="Core", value="core"},})
-- end
  -- Register callback
  tab:SetCallback("OnGroupSelected", SelectGroup)
  -- Set initial Tab (this will fire the OnGroupSelected callback)
  tab:SelectTab("core")
  
  -- add to the frame container
  frame:AddChild(tab)

  return frame

end
