local addonName, ZLAUTO = ...
local ZL = ZLAUTO.mainFrame
local background = ZL.background
local ZLCreateFrame = ZL.ZLCreateFrame
local CreateEditBox = ZL.CreateEditBox
local CreateButton = ZL.CreateButton
local GameTooltipShow = ZL.GameTooltipShow
local GameTooltipShowAnchor = ZL.GameTooltipShowAnchor
local GetClassColorName = ZL.GetClassColorName
local ParseClassColorName = ZL.ParseClassColorName
local MyAddon = ZL.MyAddon
local sleep = ZL.sleep
local GetClassInfo = C_CreatureInfo and C_CreatureInfo.GetClassInfo or GetClassInfo
local InviteUnit = C_PartyInfo and C_PartyInfo.InviteUnit or InviteUnit
local GetAddOnMetadata = C_AddOns and C_AddOns.GetAddOnMetadata or GetAddOnMetadata
local IsAddOnLoaded = C_AddOns and C_AddOns.IsAddOnLoaded or IsAddOnLoaded
local GetAddOnInfo = C_AddOns and C_AddOns.GetAddOnInfo or GetAddOnInfo
local EnableAddOn = C_AddOns and C_AddOns.EnableAddOn or EnableAddOn
local LoadAddOn = C_AddOns and C_AddOns.LoadAddOn or LoadAddOn
local GetLootMethod = C_PartyInfo and C_PartyInfo.GetLootMethod or GetLootMethod
local SetLootMethod = C_PartyInfo and C_PartyInfo.SetLootMethod or SetLootMethod
local Serializer = LibStub('AceSerializer-3.0')
local LibSerialize = LibStub("LibSerialize")
local LibDeflate = LibStub("LibDeflate")

local interval = 120
local msgSystemList = {
    ERR_RAID_MEMBER_ADDED_S, ERR_RAID_MEMBER_REMOVED_S, ERR_LEFT_GROUP_S,
    LEFT_PARTY, ERR_JOINED_GROUP_S, JOINED_PARTY, ERR_PARTY_CONVERTED_TO_RAID,
    ERR_RAID_CONVERTED_TO_PARTY, ERR_GROUP_DISBANDED, ERR_LEFT_GROUP_YOU,
}
local SLOTS = {
    INVSLOT_HEAD, INVSLOT_NECK, INVSLOT_SHOULDER, INVSLOT_CHEST, INVSLOT_WAIST, INVSLOT_LEGS, INVSLOT_FEET,
    INVSLOT_WRIST, INVSLOT_HAND, INVSLOT_FINGER1, INVSLOT_FINGER2, INVSLOT_TRINKET1, INVSLOT_TRINKET2, INVSLOT_BACK,
}
ZL.talentIcon = {
    [0] = {
        ["T"] = "|A:UI-LFG-RoleIcon-Tank:13:13:-2|a",
        ["N"] = "|A:UI-LFG-RoleIcon-Healer:13:13:-2|a",
        ["DPS"] = "|A:UI-LFG-RoleIcon-DPS:13:13:-2|a",
    }, --根据职责坦克、治疗、输出
    [1] = {
        ["狂怒"] = 132347,
        ["武器"] = 132292,
        ["防护"] = 134952,
        ["双休防战"] = 134952,
        [1] = 626008,
    },
    [2] = {
        ["神圣"] = 135920,
        ["防护"] = 135893,
        ["惩戒"] = 135873,
        ["双休防骑"] = 135893,
        [2] = 626003,
    },
    [3] = {
        ["野兽控制"] = 132164,
        ["射击"] = 132222,
        ["生存"] = 132215,
        [3] = 626000,
    },
    [4] = {
        ["刺杀"] = 132292,
        ["战斗"] = 132090,
        ["奇袭"] = 132320,
        ["敏锐"] = 132320,
        [4] = 626005,
    },
    [5] = {
        ["戒律"] = 135987,
        ["神圣"] = 237542,
        ["暗影"] = 136207,
        [5] = 626004,
    },
    [6] = {
        ["鲜血坦克"] = 135770,
        ["鲜血输出"] = 135770,
        ["鲜血"] = 135770,
        ["冰霜"] = 135773,
        ["邪恶"] = 135775,
        ["双休DKT"] = 135770,
        [6] = 135771,
    },
    [7] = {
        ["元素"] = 136048,
        ["增强"] = 136051,
        ["恢复"] = 136052,
        ["双休萨满"] = 136052,
        [7] = 626006,
    },
    [8] = {
        ["奥术"] = 135932,
        ["火焰"] = 135810,
        ["冰霜"] = 135846,
        [8] = 626001,
    },
    [9] = {
        ["痛苦"] = 136145,
        ["恶魔学识"] = 136172,
        ["毁灭"] = 136186,
        [9] = 626007,
    },
    [10] = {
        ["酒仙"] = 608951,
        ["踏风"] = 608953,
        ["织雾"] = 608952,
        [10] = 626002,
    },
    [11] = {
        ["平衡"] = 136096,
        ["野性坦克"] = 132276,
        ["野性输出"] = 132115,
        ["野性"] = 132115,
        ["守护"] = 132276,
        ["恢复"] = 136041,
        ["双休德"] = 136041,
        [11] = 625999,
    },
}
local talentIcon = ZL.talentIcon
ZL.talentInfo = {
    [0] = {"T", "N", "DPS"},
    [1] = {"狂怒", "武器", "防护", "双休防战"},
    [2] = {"神圣", "防护", "惩戒", "双休防骑"},
    [3] = {"野兽控制", "射击", "生存"},
    [5] = {"戒律", "神圣", "暗影"},
    [7] = {"元素", "增强", "恢复", "双休萨满"},
    [8] = {"奥术", "火焰", "冰霜"},
    [9] = {"痛苦", "恶魔学识", "毁灭"},
    [10] = {"酒仙", "踏风", "织雾"},
}
if ZL.BUILD_DATA < 4 then
    ZL.talentInfo[4] = {"刺杀", "战斗", "奇袭"}
    ZL.talentInfo[6] = {"鲜血坦克", "冰霜", "邪恶", "鲜血输出", "双休DKT"}
    ZL.talentInfo[11] = {"平衡", "野性输出", "恢复", "野性坦克", "双休德"}
else
    ZL.talentInfo[4] = {"刺杀", "战斗", "敏锐"}
    ZL.talentInfo[6] = {"鲜血", "冰霜", "邪恶", "双休DKT"}
    ZL.talentInfo[11] = {"平衡", "恢复", "野性", "守护", "双休德"}
end
local talentInfo = ZL.talentInfo
ZL.talentOtherName = {
    [0] = {
        ["T"] = {"T", "T"},
        ["N"] = {"N", "N"},
        ["DPS"] = {"DPS", "DPS"},
        [0]= {""}
    },
    [1] = {
        ["狂怒"] = {"狂暴战", "KBZ", "狂暴", "狂怒"},
        ["武器"] = {"武器战", "WQZ", "武器", "WQ"},
        ["防护"] = {"防战", "ZST", "FZ", "FH", "防护", "坦克", "T"},
        ["双休防战"] = {"双休防战", "双休ZS", "双休战士", "双休FZ", "双休", "双休T"},
        [1] = {"战士", "ZS"},
    },
    [2] = {
        ["神圣"] = {"奶骑", "NQ", "奶", "神圣"},
        ["防护"] = {"防骑", "FQ", "防护", "坦克", "T"},
        ["惩戒"] = {"惩戒", "CJQ", "CJ", "惩戒骑"},
        ["双休防骑"] = {"双休防骑", "双休FQ", "双休骑士", "双休QS", "双休", "双休T"},
        [2] = {"骑士", "QS"},
    },
    [3] = {
        ["野兽控制"] = {"兽王猎", "兽王", "SWL", "野兽"},
        ["射击"] = {"射击猎", "射击L", "射击", "SJL"},
        ["生存"] = {"生存猎", "生存L", "SCL", "生存"},
        [3] = {"猎人", "LR"},
    },
    [4] = {
        ["刺杀"] = {"刺杀贼", "刺杀Z", "CSZ", "刺杀"},
        ["战斗"] = {"战斗贼", "战斗Z", "ZDZ", "战斗"},
        ["奇袭"] = {"奇袭贼", "奇袭Z", "QXZ", "奇袭"},
        ["敏锐"] = {"敏锐贼", "敏锐Z", "MRZ", "敏锐"},
        [4] = {"盗贼", "DZ"},
    },
    [5] = {
        ["戒律"] = {"戒律牧", "JLM", "戒律"},
        ["神圣"] = {"神牧", "神牧", "神圣"},
        ["暗影"] = {"暗牧", "AM", "暗影"},
        [5] = {"牧师", "MS"},
    },
    [6] = {
        ["鲜血坦克"] = {"DKT", "DKT", "坦克", "T"},
        ["鲜血"] = {"DKT", "DKT", "坦克", "T"},
        ["鲜血输出"] = {"鲜血输出", "血DK"},
        ["冰霜"] = {"冰DK", "BDK", "冰霜"},
        ["邪恶"] = {"邪DK", "XDK", "邪恶"},
        ["双休DKT"] = {"双休DKT", "双休DK", "双休T", "双休"},
        [6] = {"DK", "DK"},
    },
    [7] = {
        ["元素"] = {"元素萨", "元素S", "YSS", "元素", "元素SM", "电萨", "电S", "电SM"},
        ["增强"] = {"增强萨", "增强S", "ZQS", "增强", "增强SM"},
        ["恢复"] = {"奶萨", "奶S", "NS", "奶", "奶SM", "恢复"},
        ["双休萨满"] = {"双休萨满", "双休SM"},
        [7] = {"萨满", "SM"},
    },
    [8] = {
        ["奥术"] = {"奥法", "奥F", "AF", "奥术"},
        ["火焰"] = {"火法", "火F", "HF", "火焰"},
        ["冰霜"] = {"冰法", "冰F", "BF", "冰霜"},
        [8] = {"法师", "FS"},
    },
    [9] = {
        ["痛苦"] = {"痛苦术", "痛苦S", "TKS", "痛苦"},
        ["恶魔学识"] = {"恶魔术", "恶魔S", "EMS", "恶魔", "恶魔SS", "恶魔术士"},
        ["毁灭"] = {"毁灭术", "毁灭S", "HMS", "毁灭"},
        [9] = {"术士", "SS"},
    },
    [10] = {
        ["酒仙"] = {"酒仙"},
        ["踏风"] = {"踏风"},
        ["织雾"] = {"织雾"},
        [10] = {"武僧"},
    },
    [11] = {
        ["平衡"] = {"鸟德", "鸟D", "鸟", "咕咕", "平衡"},
        ["野性坦克"] = {"熊T", "熊T", "坦克", "T"},
        ["守护"] = {"熊T", "熊T", "坦克", "T"},
        ["野性输出"] = {"猫德", "猫D", "猫", "野德"},
        ["野性"] = {"猫德", "猫D", "猫", "野德"},
        ["恢复"] = {"奶德", "ND", "奶", "恢复"},
        ["双休德"] = {"双休德", "双休D", "双休鸟D", "双休鸟德", "双休鸟", "双休"},
        [11] = {"小德", "XD", "德鲁伊", "德"},
    },
}
local talentOtherName = ZL.talentOtherName
local presetsProfiles = {
    ["红玉圣殿(10人)"] = {
        {
            ["classColor"] = "fff58cba",
            ["classID"] = 2,
            ["talent"] = "防护",
        },
        {
            ["classColor"] = "fff58cba",
            ["classID"] = 2,
            ["talent"] = "神圣",
        },
        {
            ["classColor"] = "ffff7d0a",
            ["classID"] = 11,
            ["talent"] = "野性输出",
        },
        {
            ["classColor"] = "ffff7d0a",
            ["classID"] = 11,
            ["talent"] = "平衡",
        },
        {
            ["classColor"] = "fffff569",
            ["classID"] = 4,
            ["talent"] = "战斗",
        },
        {
            ["classColor"] = "ffc41f3b",
            ["classID"] = 6,
            ["talent"] = "鲜血坦克",
        },
        {
            ["classColor"] = "ffffffff",
            ["classID"] = 5,
            ["talent"] = "戒律",
        },
        {
            ["classColor"] = "ff0070de",
            ["classID"] = 7,
            ["talent"] = "恢复",
        },
        {
            ["classColor"] = "fff58cba",
            ["classID"] = 2,
            ["talent"] = "惩戒",
        },
        {
            ["classColor"] = "ffc79c6e",
            ["classID"] = 1,
            ["talent"] = "狂怒",
        },
    },
    ["阿尔卡冯的宝库(25人)"] = {
        {
            ["classColor"] = "ffc79c6e",
            ["classID"] = 1,
            ["talent"] = 1,
        },
        {
            ["classColor"] = "ffc79c6e",
            ["classID"] = 1,
            ["talent"] = 1,
        },
        {
            ["classColor"] = "fff58cba",
            ["classID"] = 2,
            ["talent"] = 2,
        },
        {
            ["classColor"] = "fff58cba",
            ["classID"] = 2,
            ["talent"] = 2,
        },
        {
            ["classColor"] = "ffabd473",
            ["classID"] = 3,
            ["talent"] = 3,
        },
        {
            ["classColor"] = "ffabd473",
            ["classID"] = 3,
            ["talent"] = 3,
        },
        {
            ["classColor"] = "fffff569",
            ["classID"] = 4,
            ["talent"] = 4,
        },
        {
            ["classColor"] = "fffff569",
            ["classID"] = 4,
            ["talent"] = 4,
        },
        {
            ["classColor"] = "ffffffff",
            ["classID"] = 5,
            ["talent"] = 5,
        },
        {
            ["classColor"] = "ffffffff",
            ["classID"] = 5,
            ["talent"] = 5,
        },
        {
            ["classColor"] = "ffc41f3b",
            ["classID"] = 6,
            ["talent"] = 6,
        },
        {
            ["classColor"] = "ffc41f3b",
            ["classID"] = 6,
            ["talent"] = 6,
        },
        {
            ["classColor"] = "ff0070de",
            ["classID"] = 7,
            ["talent"] = 7,
        },
        {
            ["classColor"] = "ff0070de",
            ["classID"] = 7,
            ["talent"] = 7,
        },
        {
            ["classColor"] = "ff40c7eb",
            ["classID"] = 8,
            ["talent"] = 8,
        },
        {
            ["classColor"] = "ff40c7eb",
            ["classID"] = 8,
            ["talent"] = 8,
        },
        {
            ["classColor"] = "ff8787ed",
            ["classID"] = 9,
            ["talent"] = 9,
        },
        {
            ["classColor"] = "ff8787ed",
            ["classID"] = 9,
            ["talent"] = 9,
        },
        {
            ["classColor"] = "ffff7d0a",
            ["classID"] = 11,
            ["talent"] = 11,
        },
        {
            ["classColor"] = "ffff7d0a",
            ["classID"] = 11,
            ["talent"] = 11,
        },
    },
    ["红玉圣殿(25人)"] = {
        {
            ["classColor"] = "ffc41f3b",
            ["classID"] = 6,
            ["talent"] = "鲜血坦克",
        },
        {
            ["classColor"] = "fff58cba",
            ["classID"] = 2,
            ["talent"] = "神圣",
        },
        {
            ["classColor"] = "ffffffff",
            ["classID"] = 5,
            ["talent"] = "神圣",
        },
        {
            ["classColor"] = "ffff7d0a",
            ["classID"] = 11,
            ["talent"] = "恢复",
        },
        {
            ["classColor"] = "ff0070de",
            ["classID"] = 7,
            ["talent"] = "恢复",
        },
        {
            ["classColor"] = "fffff569",
            ["classID"] = 4,
            ["talent"] = "刺杀",
        },
        {
            ["classColor"] = "fff58cba",
            ["classID"] = 2,
            ["talent"] = "惩戒",
        },
        {
            ["classColor"] = "fff58cba",
            ["classID"] = 2,
            ["talent"] = "惩戒",
        },
        {
            ["classColor"] = "ffc79c6e",
            ["classID"] = 1,
            ["talent"] = "狂怒",
        },
        {
            ["classColor"] = "ffc79c6e",
            ["classID"] = 1,
            ["talent"] = "狂怒",
        },
        {
            ["classColor"] = "ffc41f3b",
            ["classID"] = 6,
            ["talent"] = "鲜血坦克",
        },
        {
            ["classColor"] = "fff58cba",
            ["classID"] = 2,
            ["talent"] = "防护",
        },
        {
            ["classColor"] = "fff58cba",
            ["classID"] = 2,
            ["talent"] = "神圣",
        },
        {
            ["classColor"] = "ffffffff",
            ["classID"] = 5,
            ["talent"] = "戒律",
        },
        {
            ["classColor"] = "ff0070de",
            ["classID"] = 7,
            ["talent"] = "恢复",
        },
        {
            ["classColor"] = "ffc41f3b",
            ["classID"] = 6,
            ["talent"] = "邪恶",
        },
        {
            ["classColor"] = "ffff7d0a",
            ["classID"] = 11,
            ["talent"] = "野性输出",
        },
        {
            ["classColor"] = "fffff569",
            ["classID"] = 4,
            ["talent"] = "战斗",
        },
        {
            ["classColor"] = "ff40c7eb",
            ["classID"] = 8,
            ["talent"] = "火焰",
        },
        {
            ["classColor"] = "ff40c7eb",
            ["classID"] = 8,
            ["talent"] = "火焰",
        },
        {
            ["classColor"] = "ffabd473",
            ["classID"] = 3,
            ["talent"] = "生存",
        },
        {
            ["classColor"] = "ffabd473",
            ["classID"] = 3,
            ["talent"] = "生存",
        },
        {
            ["classColor"] = "ff8787ed",
            ["classID"] = 9,
            ["talent"] = "恶魔学识",
        },
        {
            ["classColor"] = "ffff7d0a",
            ["classID"] = 11,
            ["talent"] = "平衡",
        },
        {
            ["classColor"] = "ffffffff",
            ["classID"] = 5,
            ["talent"] = "暗影",
        },
    },
    ["冰冠堡垒(10人)"] = {
        {
            ["classColor"] = "fff58cba",
            ["classID"] = 2,
            ["talent"] = "防护",
        },
        {
            ["classColor"] = "ffc41f3b",
            ["classID"] = 6,
            ["talent"] = "鲜血坦克",
        },
        {
            ["classColor"] = "fff58cba",
            ["classID"] = 2,
            ["talent"] = "神圣",
        },
        {
            ["classColor"] = "fff58cba",
            ["classID"] = 2,
            ["talent"] = "惩戒",
        },
        {
            ["classColor"] = "ffc79c6e",
            ["classID"] = 1,
            ["talent"] = "狂怒",
        },
        {
            ["classColor"] = "ffffffff",
            ["classID"] = 5,
            ["talent"] = "戒律",
        },
        {
            ["classColor"] = "ffabd473",
            ["classID"] = 3,
            ["talent"] = "生存",
        },
        {
            ["classColor"] = "ffff7d0a",
            ["classID"] = 11,
            ["talent"] = "平衡",
        },
        {
            ["classColor"] = "ff0070de",
            ["classID"] = 7,
            ["talent"] = "双休萨满",
        },
        {
            ["classColor"] = "ff8787ed",
            ["classID"] = 9,
            ["talent"] = "恶魔学识",
        },
    },
    ["阿尔卡冯的宝库(10人)"] = {
        {
            ["classColor"] = "fff58cba",
            ["classID"] = 2,
            ["talent"] = 2,
        },
        {
            ["classColor"] = "ffc79c6e",
            ["classID"] = 1,
            ["talent"] = 1,
        },
        {
            ["classColor"] = "ffabd473",
            ["classID"] = 3,
            ["talent"] = 3,
        },
        {
            ["classColor"] = "fffff569",
            ["classID"] = 4,
            ["talent"] = 4,
        },
        {
            ["classColor"] = "ffffffff",
            ["classID"] = 5,
            ["talent"] = 5,
        },
        {
            ["classColor"] = "ffc41f3b",
            ["classID"] = 6,
            ["talent"] = 6,
        },
        {
            ["classColor"] = "ff0070de",
            ["classID"] = 7,
            ["talent"] = 7,
        },
        {
            ["classColor"] = "ff40c7eb",
            ["classID"] = 8,
            ["talent"] = 8,
        },
        {
            ["classColor"] = "ff8787ed",
            ["classID"] = 9,
            ["talent"] = 9,
        },
        {
            ["classColor"] = "ffff7d0a",
            ["classID"] = 11,
            ["talent"] = 11,
        },
    },
    ["冰冠堡垒(25人)"] = {
        {
            ["classColor"] = "ffc41f3b",
            ["classID"] = 6,
            ["talent"] = "鲜血坦克",
        },
        {
            ["classColor"] = "fff58cba",
            ["classID"] = 2,
            ["talent"] = "防护",
        },
        {
            ["classColor"] = "fff58cba",
            ["classID"] = 2,
            ["talent"] = "双休防骑",
        },
        {
            ["classColor"] = "fff58cba",
            ["classID"] = 2,
            ["talent"] = "惩戒",
        },
        {
            ["classColor"] = "ffc41f3b",
            ["classID"] = 6,
            ["talent"] = "邪恶",
        },
        {
            ["classColor"] = "ffc79c6e",
            ["classID"] = 1,
            ["talent"] = "狂怒",
        },
        {
            ["classColor"] = "ffc41f3b",
            ["classID"] = 6,
            ["talent"] = "邪恶",
        },
        {
            ["classColor"] = "fffff569",
            ["classID"] = 4,
            ["talent"] = "战斗",
        },
        {
            ["classColor"] = "ffff7d0a",
            ["classID"] = 11,
            ["talent"] = "野性输出",
        },
        {
            ["classColor"] = "ffabd473",
            ["classID"] = 3,
            ["talent"] = "生存",
        },
        {
            ["classColor"] = "ffff7d0a",
            ["classID"] = 11,
            ["talent"] = "野性输出",
        },
        {
            ["classColor"] = "ffabd473",
            ["classID"] = 3,
            ["talent"] = "生存",
        },
        {
            ["classColor"] = "ff8787ed",
            ["classID"] = 9,
            ["talent"] = "痛苦",
        },
        {
            ["classColor"] = "ff8787ed",
            ["classID"] = 9,
            ["talent"] = "痛苦",
        },
        {
            ["classColor"] = "ff8787ed",
            ["classID"] = 9,
            ["talent"] = "恶魔学识",
        },
        {
            ["classColor"] = "ffffffff",
            ["classID"] = 5,
            ["talent"] = "暗影",
        },
        {
            ["classColor"] = "ffff7d0a",
            ["classID"] = 11,
            ["talent"] = "平衡",
        },
        {
            ["classColor"] = "ff40c7eb",
            ["classID"] = 8,
            ["talent"] = "火焰",
        },
        {
            ["classColor"] = "ff40c7eb",
            ["classID"] = 8,
            ["talent"] = "火焰",
        },
        {
            ["classColor"] = "ff0070de",
            ["classID"] = 7,
            ["talent"] = "元素",
        },
        {
            ["classColor"] = "fff58cba",
            ["classID"] = 2,
            ["talent"] = "神圣",
        },
        {
            ["classColor"] = "fff58cba",
            ["classID"] = 2,
            ["talent"] = "神圣",
        },
        {
            ["classColor"] = "ffffffff",
            ["classID"] = 5,
            ["talent"] = "戒律",
        },
        {
            ["classColor"] = "ffffffff",
            ["classID"] = 5,
            ["talent"] = "戒律",
        },
        {
            ["classColor"] = "ff0070de",
            ["classID"] = 7,
            ["talent"] = "恢复",
        },
    },
}

local function getColorString(color, str)
    return "|c" .. color .. str .. "|r"
end
local function getPlayerTalent(name)
    if not name then return end
    local manualTalentInfo = ZL_PLAYERLIST.manualTalentInfo
    if manualTalentInfo and manualTalentInfo[name] and manualTalentInfo[name].talent then
        return manualTalentInfo[name].talent, 1 --手动设置只能
    end
    local playerInfo = ZL.opt.playerInfo
    if playerInfo and playerInfo[name] and playerInfo[name].newTalentName then
        return playerInfo[name].newTalentName, 2 --观察获取到的职能
    end
    local msgTalentInfo = ZL_PLAYERLIST.msgTalentInfo
    if msgTalentInfo and msgTalentInfo[name] and msgTalentInfo[name].talent then
        return msgTalentInfo[name].talent, 3 --密语消息获取到的职能
    end
    return nil, nil
end

local function isInMsgSystemList(msg)
    if not msg then return false end
    for _, v in ipairs(msgSystemList) do
        if strmatch(msg, v:gsub("%%s", "(.+)")) then
            return true
        end
    end
    return false
end
local function CreatFrontString(w, h, fontSize, wordWrap, JustifyH, parent)
    parent = parent or ZL.RaidGroupsFrame
    local fontString = parent:CreateFontString(nil, "OVERLAY")
    if w then
        fontString:SetWidth(w)
    end
    if h then
        fontString:SetHeight(h)
    end
    fontString:SetFont(GameFontNormal:GetFont(), fontSize or 14, "OUTLINE")
    fontString:SetWordWrap(wordWrap or false)
    fontString:SetJustifyH(JustifyH or "CENTER")
    fontString:SetTextColor(1, 0.82, 0, 1)
    return fontString
end
--降职按钮
local function DemoteButtonCanShow(name)
    if not name then
        return false;
    end

    local isLeader = UnitIsGroupLeader("player");
    local isAssistant = UnitIsGroupAssistant("player");
    if not (isLeader or isAssistant) then
        return false;
    end
    if not (GetPartyAssignment("MAINTANK", name) or GetPartyAssignment("MAINASSIST", name)) then
        if (not isLeader) and isAssistant and UnitIsGroupAssistant(name) then
            return false;
        end

        if isLeader or isAssistant then
            if UnitIsGroupLeader(name) then
            return false;
            end

            if not UnitIsGroupAssistant(name) then
            return false;
            end

            if IsEveryoneAssistant() then
                return false;
            end
        end
    end

    return true;
end
--取消邀请按钮
local function RemoveButtonCanShow(name)
	local isLeader = UnitIsGroupLeader("player")
	local isAssistant = UnitIsGroupAssistant("player")
	if not (isLeader or isAssistant) then
		return false
	end
	if isAssistant then
		if UnitIsGroupAssistant(name) or UnitIsGroupLeader(name) then
			return false
		end
	else
		if UnitIsUnit(name, "player") then
		    return false
		end
	end
	return true
end
--提升为物品分配者按钮
local function LootPromoteButtonCanShow(name)
	if not IsInGroup() then
		return false
	end
	if not UnitIsGroupLeader("player") then
		return false
	end
	local lootMethod, partyIndex, raidIndex = GetLootMethod()
	if lootMethod ~=  'master' and lootMethod ~= 2 then
		return false
	end
	if IsInRaid(1) then
		if raidIndex and (name == UnitName("raid"..raidIndex)) then
			return false
		end
	elseif IsInGroup(1) then
		if partyIndex and (name == UnitName("party"..partyIndex)) then
			return false
		end
	end
	return true
end
local function dropDownMenu(self)
    local menuList = {}
    for i = 1, 13 do
        local className, classFile = GetClassInfo(i)
        if className then
            if type(className) == "table" then
                classFile = className.classFile
                className = className.className
            end
            local classColor = select(4, GetClassColor(classFile))
            local menuTable = {}
            if talentInfo[i] then
                for _, value in ipairs(talentInfo[i]) do
                    tinsert(menuTable, {
                        text = "|T" .. talentIcon[i][value] .. ":12:12:-2|t" .. talentOtherName[i][value][1],
                        checkable = 1,
                        checked = function ()
                            local data = ZL_PLAYERLIST.RaidGroupsData
                            if data and data[self.index] and data[self.index].classID == i then
                                local talent = data[self.index].talent
                                if type(talent) == "string" and talent == value then
                                    return true
                                end
                            end
                            return false
                        end,
                        func = function ()
                            ZL_PLAYERLIST.RaidGroupsData = ZL_PLAYERLIST.RaidGroupsData or {}
                            local RaidGroupsData = ZL_PLAYERLIST.RaidGroupsData
                            RaidGroupsData[self.index] = RaidGroupsData[self.index] or {}
                            RaidGroupsData[self.index].talent = value
                            RaidGroupsData[self.index].classID = i
                            RaidGroupsData[self.index].classColor = classColor
                            ZL.GUI:CloseMenu()
                            ZL.RaidGroupsFrame:Update()
                        end
                    })
                end
            end
            tinsert(menuTable, {
                text = "|T" .. talentIcon[i][i] .. ":12:12:-2|t" .. talentOtherName[i][i][1],
                checkable = 1,
                checked = function ()
                    local data = ZL_PLAYERLIST.RaidGroupsData
                    if data and data[self.index] and data[self.index].classID == i then
                        local talent = data[self.index].talent
                        if type(talent) == "number" and talent == i then
                            return true
                        end
                    end
                    return false
                end,
                func = function ()
                    ZL_PLAYERLIST.RaidGroupsData = ZL_PLAYERLIST.RaidGroupsData or {}
                    local RaidGroupsData = ZL_PLAYERLIST.RaidGroupsData
                    RaidGroupsData[self.index] = RaidGroupsData[self.index] or {}
                    RaidGroupsData[self.index].talent = i
                    RaidGroupsData[self.index].classID = i
                    RaidGroupsData[self.index].classColor = classColor
                    ZL.GUI:CloseMenu()
                    ZL.RaidGroupsFrame:Update()
                end
            })
            tinsert(menuList, {
                text = "|T" .. talentIcon[i][i] .. ":12:12:-2|t|c" .. classColor .. className .. "|r",
                hasArrow = 1,
                menuTable = menuTable,
                func = function ()
                    ZL_PLAYERLIST.RaidGroupsData = ZL_PLAYERLIST.RaidGroupsData or {}
                    local RaidGroupsData = ZL_PLAYERLIST.RaidGroupsData
                    RaidGroupsData[self.index] = RaidGroupsData[self.index] or {}
                    RaidGroupsData[self.index].talent = i
                    RaidGroupsData[self.index].classID = i
                    RaidGroupsData[self.index].classColor = classColor
                    ZL.GUI:CloseMenu()
                    ZL.RaidGroupsFrame:Update()
                end
            })
        end
    end
    tinsert(menuList, {
        text =  "|T :12:12:-2|t按职责",
        notClickable = 1,
        hasArrow = 1,
        menuTable = function ()
            local tempList = {}
            for _, v in ipairs(ZL.talentInfo[0]) do
                tinsert(tempList, {
                    text = ZL.talentIcon[0][v] .. v,
                    checkable = 1,
                    checked = function ()
                        local data = ZL_PLAYERLIST.RaidGroupsData
                        if data and data[self.index] and data[self.index].classID == 0 and data[self.index].talent == v then
                            return true
                        end
                        return false
                    end,
                    func = function ()
                        ZL_PLAYERLIST.RaidGroupsData = ZL_PLAYERLIST.RaidGroupsData or {}
                        local RaidGroupsData = ZL_PLAYERLIST.RaidGroupsData
                        RaidGroupsData[self.index] = RaidGroupsData[self.index] or {}
                        RaidGroupsData[self.index].talent = v
                        RaidGroupsData[self.index].classID = 0
                        RaidGroupsData[self.index].classColor = "ffffffff"
                        ZL.GUI:CloseMenu()
                        ZL.RaidGroupsFrame:Update()
                    end
                })
            end
            return tempList
        end,
    })
    if #(self:GetText() or "") > 0 then
        tinsert(menuList, {isSeparator=1})
        tinsert(menuList, {
            text = "|cFFFFDE00清除|r",
            func = function ()
                ZL_PLAYERLIST.RaidGroupsData[self.index] = nil
                ZL.GUI:CloseMenu()
                ZL.RaidGroupsFrame:Update()
            end
        })
    end
    return menuList
end
local function noInDropDownMenu(self, name, classID)
    local menuList = {}
    name = name or self.info.name
    classID = classID or self.info.classID
    if not name or not classID then
        tinsert(menuList, {text="缺少玩家名或职业ID", isTitle=1})
        return menuList
    end
    local playerInfo = ZL.opt.playerInfo
    local activeTalent
    local talent, talentSorce = getPlayerTalent(name)
    if playerInfo and playerInfo[name] and playerInfo[name].newTalentName then
        activeTalent = playerInfo[name].newTalentName
    end
    tinsert(menuList, {text="使用当前天赋职能", isTitle=1})
    tinsert(menuList, {
        text = activeTalent and ("|T" .. talentIcon[classID][activeTalent] .. ":12:12:-2|t" .. talentOtherName[classID][activeTalent][1]) or "未获取到",
        checkable = 1,
        checked = activeTalent == talent and talentSorce == 2,
        func = function ()
            if ZL_PLAYERLIST.manualTalentInfo then
                ZL_PLAYERLIST.manualTalentInfo[name] = nil
                ZL.GUI:CloseMenu()
                ZL.RaidGroupsFrame:Update()
            end
        end
    })
    if talentInfo[classID] then
        tinsert(menuList, {text="手动设置职能", isTitle=1})
        for _, value in ipairs(talentInfo[classID]) do
            if value:find("双休") or (not (playerInfo and playerInfo[name] and playerInfo[name].talentName)) or
            playerInfo[name].talentName[value] then
                tinsert(menuList, {
                    text = "|T" .. talentIcon[classID][value] .. ":12:12:-2|t" .. talentOtherName[classID][value][1],
                    checkable = 1,
                    checked = talent == value and talentSorce == 1,
                    func = function ()
                        ZL_PLAYERLIST.manualTalentInfo = ZL_PLAYERLIST.manualTalentInfo or {}
                        ZL_PLAYERLIST.manualTalentInfo[name] = ZL_PLAYERLIST.manualTalentInfo[name] or {}
                        ZL_PLAYERLIST.manualTalentInfo[name].talent = value
                        ZL.GUI:CloseMenu()
                        ZL.RaidGroupsFrame:Update()
                    end
                })
            end
        end
        local className, classFile = GetClassInfo(classID)
        if className then
            if type(className) == "table" then
                classFile = className.classFile
                className = className.className
            end
            tinsert(menuList, {
                text = "|A:classicon-" .. string.lower(classFile) .. ":12:12:-2|a" .. talentOtherName[classID][classID][1],
                checkable = 1,
                checked = talent == classID and talentSorce == 1,
                func = function ()
                    ZL_PLAYERLIST.manualTalentInfo = ZL_PLAYERLIST.manualTalentInfo or {}
                    ZL_PLAYERLIST.manualTalentInfo[name] = ZL_PLAYERLIST.manualTalentInfo[name] or {}
                    ZL_PLAYERLIST.manualTalentInfo[name].talent = classID
                    ZL.GUI:CloseMenu()
                    ZL.RaidGroupsFrame:Update()
                end
            })
        end
    end
    local index = #menuList + 1
    local isSeparator
    if RemoveButtonCanShow(name) then
        isSeparator = 1
        tinsert(menuList, {
            text = "取消邀请",
            func = function ()
                UninviteUnit(name)
            end
        })
    end
    if UnitIsGroupLeader("player") and not UnitIsGroupLeader(name) then
        isSeparator = 1
        tinsert(menuList, {
            text = SET_RAID_LEADER,
            func = function ()
                PromoteToLeader(name)
            end
        })
    end
    if UnitIsGroupLeader("player") and not UnitIsGroupAssistant(name) and not UnitIsGroupLeader(name) then
        isSeparator = 1
        tinsert(menuList, {
            text = SET_RAID_ASSISTANT,
            func = function ()
                PromoteToAssistant(name)
            end
        })
    end
    if DemoteButtonCanShow(name) then
        isSeparator = 1
        tinsert(menuList, {
            text = DEMOTE,
            func = function ()
                if UnitIsGroupLeader("player") and UnitIsGroupAssistant(name) then
                    DemoteAssistant(name, true);
                end
                if GetPartyAssignment("MAINTANK", name, true) then
                    ClearPartyAssignment("MAINTANK", name, true);
                elseif GetPartyAssignment("MAINASSIST", name, true) then
                    ClearPartyAssignment("MAINASSIST", name, true);
                end
            end
        })
    end
    if LootPromoteButtonCanShow(name) then
        isSeparator = 1
        tinsert(menuList, {
            text = LOOT_PROMOTE,
            func = function ()
                SetLootMethod((C_PartyInfo and 2 or "master"), name)
            end
        })
    end
    if isSeparator then
        tinsert(menuList, index, {isSeparator=1})
    end
    return menuList
end
local function getWCLScore(unit)
    if not IsAddOnLoaded("ArchonTooltip") then return end
    local score
    GameTooltip:SetOwner(UIParent, "ANCHOR_NONE")
    GameTooltip:ClearLines()
    GameTooltip:SetUnit(unit)
    local line1, line2, txt1, txt2
    for i = 1, GameTooltip:NumLines() do
        line1 = _G["GameTooltipTextLeft" .. i]
        if line1 then
            txt1 = line1:GetText()
            if txt1 and txt1:match("Warcraft Logs") then
                line2 = _G["GameTooltipTextLeft" .. (i+1)]
                if line2 then
                    txt2 = line2:GetText()
                    score = txt2 and txt2:match("^.+%s+(|c........%d+%.-%d-|r)%s+.+击杀$")
                end
                break
            end
        end
    end
    line1, line2, txt1 = nil, nil, nil
    return score, txt2
end
local function GetItemLevel(unit)
    local _itemLevel = false
    local fullName = ZL.GetFullName(unit)
    if TDDB_INSPECT2 and TDDB_INSPECT2.global and TDDB_INSPECT2.global.userCache and TDDB_INSPECT2.global.userCache[fullName] and
    TDDB_INSPECT2.global.userCache[fullName].equips then
        local equips = TDDB_INSPECT2.global.userCache[fullName].equips
        local tdInspect = LibStub("AceAddon-3.0"):GetAddon("tdInspect")
        local ItemLevelCalculator = tdInspect:GetClass("ItemLevelCalculator")
        function ItemLevelCalculator:GetSlotInfo(slot)
            local item = equips[slot]
            if not item then
                return 0
            end
            local itemLevel, _, _, _, _, itemEquipLoc, _, _, _, subClassId = select(4, GetItemInfo(item))
            if itemLevel then
                return itemLevel, itemEquipLoc, subClassId
            end
        end
        _itemLevel = ItemLevelCalculator:GetItemLevel()
        function ItemLevelCalculator:GetSlotInfo(slot)
            local item = self.fn(slot)
            if not item then
                return 0
            end
            local itemLevel, _, _, _, _, itemEquipLoc, _, _, _, subClassId = select(4, GetItemInfo(item))
            if itemLevel then
                return itemLevel, itemEquipLoc, subClassId
            end
        end
    end
    return _itemLevel
end
local function inspectfunc(msg, name, guid)
    msg = string.upper(msg)
    local RaidGroupsFrame = ZL.RaidGroupsFrame
    local className, classFile = GetPlayerInfoByGUID(guid)
    local classID = tIndexOf(ZL.ClassFileList, classFile)
    local classColor = select(4, GetClassColor(classFile))
    local colorName = GetClassColorName(name, classFile)
    local msgTalent, msgItemLevel
    ZL_PLAYERLIST.whisperList = ZL_PLAYERLIST.whisperList or {}
    local whisperList = ZL_PLAYERLIST.whisperList
    local msgTime = time()
    whisperList[name] = whisperList[name] or {
        firstTime = msgTime,
        whisperMsgList = {},
        classColor = classColor,
        classID = classID,
    }
    whisperList[name].lastTime = msgTime
    tinsert(whisperList[name].whisperMsgList, {msgTime, msg})
    for talent, data in pairs(talentOtherName[classID]) do
        for _, v in ipairs(data) do
            if msg:find(v) then
                msgTalent = talent
                break
            end
        end
        if msgTalent then break end
    end
    whisperList[name].msgTalent = msgTalent
    if not msgTalent then
        -- print(colorName, "职业", className, "密语未检测到天赋内容")
    else
        -- print(colorName, "：职业：", className, "，检测到密语天赋为：", msgTalent)
        msg = msg:gsub("%s", "")
        msgItemLevel = msg:match("(%d+)")
        msgItemLevel = msgItemLevel and tonumber(msgItemLevel)
        whisperList[name].msgItemLevel = msgItemLevel
    end

    ZL.opt.playerInfo = ZL.opt.playerInfo or {}
    ZL.opt.playerInfo[name] = ZL.opt.playerInfo[name] or {}
    local playerInfo = ZL.opt.playerInfo
    local fullName = ZL.GetFullName(name)
    local istdInspectDB
    --如果tdInspect插件存在更新的缓存数据，则直接读取
    if TDDB_INSPECT2 and TDDB_INSPECT2.global and TDDB_INSPECT2.global.userCache and TDDB_INSPECT2.global.userCache[fullName] and
    TDDB_INSPECT2.global.userCache[fullName].talents and (time() - TDDB_INSPECT2.global.userCache[fullName].timestamp <= interval) and
    (not (playerInfo and playerInfo[name] and playerInfo[name].updateTimestamp) or (playerInfo[name].updateTimestamp < TDDB_INSPECT2.global.userCache[fullName].timestamp)) then
        istdInspectDB = true
    else
        if (not (playerInfo and playerInfo[name] and playerInfo[name].updateTimestamp)) or (time() - playerInfo[name].updateTimestamp > interval) then
            if TDDB_INSPECT2 then
                --先用tdInspect插件通信，安装人数更多
                local isSync
                if TDDB_INSPECT2.global and TDDB_INSPECT2.global.userCache and TDDB_INSPECT2.global.userCache[fullName] and
                TDDB_INSPECT2.global.userCache[fullName].talents then
                    if time() - TDDB_INSPECT2.global.userCache[fullName].timestamp > interval then
                        isSync = true
                    end
                else
                    isSync = true
                end
                if isSync then
                    MyAddon:SendCommMessage("tdInspect", Serializer:Serialize('Q', true, true, 2, false, false), 'WHISPER', name)
                    sleep(1)
                    if TDDB_INSPECT2.global and TDDB_INSPECT2.global.userCache and TDDB_INSPECT2.global.userCache[fullName]
                    and TDDB_INSPECT2.global.userCache[fullName].talents and (time() - TDDB_INSPECT2.global.userCache[fullName].timestamp <= interval) then
                        istdInspectDB = true
                    end
                    if not istdInspectDB then
                        MyAddon:SendCommMessage("EMUCOM", '_q_tal', 'WHISPER', name)
                        sleep(1)
                        if TDDB_INSPECT2.global and TDDB_INSPECT2.global.userCache and TDDB_INSPECT2.global.userCache[fullName]
                        and TDDB_INSPECT2.global.userCache[fullName].talents and (time() - TDDB_INSPECT2.global.userCache[fullName].timestamp <= interval) then
                            istdInspectDB = true
                        end
                    end
                end
            end
            if not istdInspectDB then
                MyAddon:TransmitAddonInfo2("AUTOAUC TALENT", {type="talent"}, 'WHISPER', name)
                sleep(2)
            end
        end
    end
    if istdInspectDB then
        ZL.updateFromtdInspect(name)
    end
    local activeTalent, secondTalent, isTalent
    if playerInfo[name].talentName then
        activeTalent = playerInfo[name].newTalentName
        for talent in pairs(playerInfo[name].talentName) do
            if talent ~= activeTalent then
                secondTalent = talent
                break
            end
        end
    end
    whisperList[name].activeTalent = activeTalent
    whisperList[name].secondTalent = secondTalent
    RaidGroupsFrame.whisperFrame:Update()
    local RaidGroupsData = ZL_PLAYERLIST.RaidGroupsData
    if msgTalent and RaidGroupsData then -- and ZL.opt.autoInvite
        local talentList = {}
        if playerInfo[name].talentName then
            talentList = {activeTalent}
        else
            -- print(colorName, "职业", className, "未获取到天赋, 开始检测密语内容")
            local talent
            for _talent, data in pairs(talentOtherName[classID]) do
                for _, v in ipairs(data) do
                    if msg:find(v) then
                        talent = _talent
                        tinsert(talentList, talent)
                        break
                    end
                end
                if talent then
                    break
                end
            end
            if not talent then
                -- print(colorName, "职业", className, "密语未检测到天赋内容，无法判断")
            end
        end
        RaidGroupsFrame:Update()
        local edit
        ----职能检查开始----
        for j = 1, 40 do
            edit = RaidGroupsFrame.edits[j]
            local data = RaidGroupsData[j]
            if data and data.classID == classID and #(edit.name or "") == 0 and (msgTalent == data.talent or data.classID == data.talent) then
                isTalent = format("%s：职业：%s，天赋：%s，满足要求", colorName, className, msgTalent)
                break
            end
        end
        if isTalent then
            -- print(isTalent)
            -- InviteUnit(name)
        else
            -- print(format("%s：职业：%s，不满足要求", colorName, className))
        end
        ----职能检查结束----
        edit = nil
    end
    local itemLevel
    local tryCount = 0
    local function tempfuc()
        if itemLevel == nil and tryCount <= 30 then
            RaidGroupsFrame.getItemLevelIng = true
            tryCount = tryCount + 1
            itemLevel = GetItemLevel(name)
            itemLevel = itemLevel and floor(itemLevel)
            C_Timer.After(1, tempfuc)
        elseif type(itemLevel) == "number" then
            whisperList[name].itemLevel = itemLevel
            RaidGroupsFrame.whisperFrame:Update()
            RaidGroupsFrame.getItemLevelIng = nil
            if isTalent and ZL.opt.autoInvite then
                --判断装等是否相符
                if ZL.opt.checkItemLevel then
                    if itemLevel >= (ZL.opt.MinItemLevel or 0) then
                        InviteUnit(name)
                    end
                else
                    InviteUnit(name)
                end
            end
        else
            RaidGroupsFrame.getItemLevelIng = nil
            if isTalent and ZL.opt.autoInvite then
                --判断消息获取到的装等是否相符
                if ZL.opt.checkItemLevel then
                    if msgItemLevel >= (ZL.opt.MinItemLevel or 0) then
                        InviteUnit(name)
                    end
                else
                    InviteUnit(name)
                end
            end

        end
    end
    if not RaidGroupsFrame.getItemLevelIng then
        tempfuc()
    end
end
function ZL.isDoubleTalent(name, classID)
    --检测是否有双休天赋
    if not ZL.opt.playerInfo or not ZL.opt.playerInfo[name] or not ZL.opt.playerInfo[name].talentName then return end
    local playerInfo = ZL.opt.playerInfo[name]
    local roles = {}
    for talent in pairs(playerInfo.talentName) do
        roles[ZL.talentRole[talent][1]] = true
    end
    local roleDouble
    if roles["DPS"] and (roles["T"] or roles["N"]) then
        roleDouble = true
    end
    local isDouble
    for _, talent in ipairs(talentInfo[classID]) do
        if talent:find("双休") then
            isDouble = talent
        end
    end
    local talent
    if roleDouble and isDouble then
        talent = isDouble
    end
    return talent
end
function ZL.getMsgContent()
    local playerName = UnitName("player")
    local _, classFile, classID = UnitClass("player")
    ZL.GetTalent(false, classFile, playerName, true)
    local avgItemLevel = floor(select(2, GetAverageItemLevel()))
    local playerInfo = ZL.opt.playerInfo[playerName]
    playerInfo.avgItemLevel = avgItemLevel
    playerInfo.classID = classID
    local activeTalent = playerInfo.newTalentName
    local doubleTalent = ZL.isDoubleTalent(playerName, classID)
    return ZL.talentOtherName[classID][activeTalent][1], doubleTalent, avgItemLevel, UnitLevel("player")
end
local getMsgContent = ZL.getMsgContent
function ZL.sendWhisper(name, unitLevel)
    -- ChatEdit_ActivateChat(ChatEdit_ChooseBoxForSend())
    -- ChatEdit_ChooseBoxForSend():SetText("")
    -- ChatEdit_InsertLink("/w " .. name .. getMsgContent())
    SendChatMessage(getMsgContent(), "WHISPER", nil, name)
end
local function hookfunc(aName)
    local MeetingHorn = LibStub("AceAddon-3.0"):GetAddon(aName)
    local Browser = MeetingHorn.MainPanel.Browser
    -- local LFG = MeetingHorn:GetModule('LFG', 'AceEvent-3.0', 'AceTimer-3.0', 'AceComm-3.0', 'LibCommSocket-3.0')
    -- local Activity = MeetingHorn:GetClass('Activity')
    hooksecurefunc(MeetingHorn.MainPanel.Browser.ActivityList, "update", function ()
        local buttons = MeetingHorn.MainPanel.Browser.ActivityList._buttons
        for _, v in pairs(buttons) do
            local bt = v.Signup
            if bt then
                if not bt.hasClick then
                    bt.hasClick = true
                    bt:RegisterForClicks("LeftButtonUp", "RightButtonUp")
                    bt:SetScript("OnClick", function(self, button)
                        local activeTalent, doubleTalent, avgItemLevel, unitLevel = getMsgContent()
                        if button == "LeftButton" then
                            if IsShiftKeyDown() then
                                SendChatMessage(format("%s %d级", activeTalent, unitLevel), "WHISPER", nil, v.item.leaderLower)
                            else
                                ChatFrame_SendTell(v.item.leaderLower)
                            end
                        elseif button == "RightButton" then
                            if IsShiftKeyDown() then
                                if doubleTalent then
                                    SendChatMessage(format("%s 装等%d", doubleTalent, unitLevel), "WHISPER", nil, v.item.leaderLower)
                                end
                            else
                                SendChatMessage(format("%s 装等%d", activeTalent, avgItemLevel), "WHISPER", nil, v.item.leaderLower)
                            end
                        end
                    end)
                    bt:SetScript("OnEnter", function (self)
                        local activeTalent, doubleTalent, avgItemLevel, unitLevel = getMsgContent()
                        GameTooltipShow(self, "LEFT", "RIGHT")
                        GameTooltip:AddLine("快速密语")
                        GameTooltip:AddLine("左键：|cffffffff悄悄话|r")
                        GameTooltip:AddLine("右键：|cffffffff" .. activeTalent .. " 装等" .. avgItemLevel .. "|r")
                        GameTooltip:AddLine("Shift+左键：|cffffffff" .. activeTalent .. " " .. UnitLevel("player") .. "级|r")
                        if doubleTalent then
                            GameTooltip:AddLine("Shift+右键：|cffffffff" .. doubleTalent .. " 装等" .. avgItemLevel .. "|r")
                        end
                        GameTooltip:AddLine(" ")
                        GameTooltip:AddLine("由[AutoAuction]提供")
                        GameTooltip:Show()
                    end)
                    bt:SetScript("OnLeave", function (self)
                        GameTooltip:Hide()
                    end)
                end
            end
        end
    end)
    local oldActivityMenu = Browser.CreateActivityMenu
    local activeTalent, doubleTalent, avgItemLevel, unitLevel = getMsgContent()
    function Browser:CreateActivityMenu(activity)
        local tbl = oldActivityMenu(Browser, activity)
        tinsert(tbl, 3, {isSeparator=1})
        tinsert(tbl, 4, {text="快速密语", isTitle=1})
        tinsert(tbl, 5, {
            text = "|cffffffff" .. activeTalent .. " 装等" .. avgItemLevel .. "|r",
            tooltipTitle = "|CFFFFDE00由[AutoAuction]提供|r",
            func = function()
                SendChatMessage(format("%s 装等%d", activeTalent, avgItemLevel), "WHISPER", nil, activity:GetLeader())
            end,
        })
        tinsert(tbl, 6, {
            text = "|cffffffff" .. activeTalent .. " " .. unitLevel .. "级|r",
            tooltipTitle = "|CFFFFDE00由[AutoAuction]提供|r",
            func = function()
                SendChatMessage(format("%s %d级", activeTalent, unitLevel), "WHISPER", nil, activity:GetLeader())
            end,
        })
        if doubleTalent then
            tinsert(tbl, 7, {
                text = "|cffffffff" .. doubleTalent .. " 装等" .. avgItemLevel .. "|r",
                tooltipTitle = "|CFFFFDE00由[AutoAuction]提供|r",
                func = function()
                    SendChatMessage(format("%s 装等%d", doubleTalent, avgItemLevel), "WHISPER", nil, activity:GetLeader())
                end,
            })
        end
        return tbl
    end
end
local function aiMsgContentUpdate()
    local RaidGroupsData = ZL_PLAYERLIST.RaidGroupsData
    if RaidGroupsData and next(RaidGroupsData) then
        local RaidGroupsFrame = ZL.RaidGroupsFrame
        local msg = "来"
        if ZL.opt.checkItemLevel and ZL.opt.MinItemLevel and ZL.opt.MinItemLevel > 0 then
            msg = msg .. "装等" .. ZL.opt.MinItemLevel .. "+"
        end
        local needTalent = {}
        local edit, nameLen, data, talentTxt
        local isTExist, isNExist, isDPSExist
        for i = 1, 40 do
            edit = RaidGroupsFrame.edits[i]
            nameLen = #(edit.name or "")
            data = RaidGroupsData[i]
            if data and nameLen == 0 then
                talentTxt = ZL.talentOtherName[data.classID][data.talent][2] or ZL.talentOtherName[data.classID][data.talent][1]
                if talentTxt == "T" then
                    isTExist = true
                elseif talentTxt == "N" then
                    isNExist = true
                elseif talentTxt == "DPS" then
                    isDPSExist = true
                end
                needTalent[talentTxt] = ZL.talentRole[data.talent] and ZL.talentRole[data.talent][1] or talentTxt
            end
        end
        if next(needTalent) then
            --如果存在职责如：T、N、DPS，则清除天赋和职业
            if isTExist or isNExist or isDPSExist then
                for k, v in pairs(ZL.talentRole) do
                    if isTExist and v[1] == "T" then
                        for _, v2 in pairs(ZL.talentOtherName) do
                            for k3, v3 in pairs(v2) do
                                if k3 == k then
                                    for _, v4 in ipairs(v3) do
                                        if v4 ~= v[1] then
                                            needTalent[v4] = nil
                                        end
                                    end
                                end
                            end
                        end
                    end
                    if isNExist and v[1] == "N" then
                        for _, v2 in pairs(ZL.talentOtherName) do
                            for k3, v3 in pairs(v2) do
                                if k3 == k then
                                    for _, v4 in ipairs(v3) do
                                        if v4 ~= v[1] then
                                            needTalent[v4] = nil
                                        end
                                    end
                                end
                            end
                        end
                    end
                    if isDPSExist and v[1] == "DPS" then
                        for _, v2 in pairs(ZL.talentOtherName) do
                            for k3, v3 in pairs(v2) do
                                if k3 == k then
                                    for _, v4 in ipairs(v3) do
                                        if v4 ~= v[1] then
                                            needTalent[v4] = nil
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
            end
            --如果存在职业，则天赋需求清除掉
            for k, v in pairs(ZL.talentOtherName) do
                local tempName = v[k][2] or v[k][1]
                if needTalent[tempName] then
                    for k2, v2 in pairs(v) do
                        if k2 ~= k then
                            local tempName2 = v2[2] or v2[1]
                            needTalent[tempName2] = nil
                        end
                    end
                end
            end
            local tempList = {}
            for k, v in pairs(needTalent) do
                tinsert(tempList, {k, v})
            end
            table.sort(tempList, function (a, b)
                -- print(a, b)
                if not a or not b then return false end
                if a[1] == "T" and b[1] == "T" then
                    return true
                elseif a[1] == "T" and b[1] ~= "T" then
                    return true
                elseif a[1] ~= "T" and b[1] == "T" then
                    return false
                elseif a[1] == "N" and b[1] == "N" then
                    return true
                elseif a[1] == "N" and b[1] ~= "N" then
                    return true
                elseif a[1] ~= "N" and b[1] == "N" then
                    return false
                elseif a[1] == "DPS" and b[1] == "DPS" then
                    return true
                elseif a[1] == "DPS" and b[1] ~= "DPS" then
                    return true
                elseif a[1] ~= "DPS" and b[1] == "DPS" then
                    return false
                elseif a[2] == "T" and b[2] == "T" then
                    return a[1] < b[1]
                elseif a[2] == "T" and b[2] ~= "T" then
                    return true
                elseif a[2] == "N" and b[2] == "T" then
                    return false
                elseif a[2] == "N" and b[2] == "N" then
                    return a[1] < b[1]
                elseif a[2] == "N" and b[2] == "DPS" then
                    return true
                elseif a[2] == "DPS" and b[2] ~= "DPS" then
                    return false
                elseif a[2] == "DPS" and b[2] == "DPS" then
                    return a[1] < b[1]
                else
                    return a[1] < b[1]
                end
            end)
            for i, v in ipairs(tempList) do
                msg = i==1 and msg .. v[1] or msg .. " " .. v[1]
            end
            if #msg > 250 then
                ZL.Print("AI内容超过250字节，请调整阵容职能设置", true)
            else
                RaidGroupsFrame.aiMsgContentFrame.aiMsgContentEditBox:SetText(msg)
            end
            tempList = nil
        end
        edit = nil
        needTalent = nil
    end
end
local function msgContentFontStringUpdate()
    local RaidGroupsFrame = ZL.RaidGroupsFrame
    local aiMsg = #(RaidGroupsFrame.aiMsgContentFrame.aiMsgContentEditBox:GetText() or "")
    local myMsg = #((RaidGroupsFrame.msgContentFrame.msgContentEditBox:GetText() or ""):gsub("，", ", "))
    local totalMsg = aiMsg + myMsg
    local msg
    if ZL.opt.aiRolesCheckBtn then
        if totalMsg > 250 then
            msg = "|cffff0000总字节数已超过250个，请删减自定义内容，做多不超过" .. (250-aiMsg) .. "个。|r|CFFFFDE001个中文字符=3个字节|r"
        else
            msg = format("|cff999999总字节数不超过250个，已输入%d个，还剩余%d个。|r|CFFFFDE001个中文字符=3个字节|r", totalMsg, 250-totalMsg)
        end
    else
        msg = format("|cff999999总字节数不超过250个，已输入%d个，还剩余%d个。|r|CFFFFDE001个中文字符=3个字节|r", myMsg, 250-myMsg)
    end
    RaidGroupsFrame.msgContentFrame.msgContentEditBox.msgContentFontString:SetText(msg)
end
local function titleBtn(parent, text, point, relativeTo, relativePoint, offsetX, offsetY, width, height)
    local btn = CreateButton(nil, parent, text, point, relativeTo, relativePoint, offsetX, offsetY, width, height)
    btn:GetFontString():SetFont(GameFontNormal:GetFont(), 14, "OUTLINE")
    btn:SetNormalTexture([[Interface\ACHIEVEMENTFRAME\UI-Achievement-Parchment-Horizontal]])
    btn:ClearHighlightTexture()
    btn:GetFontString():SetTextColor(0.95, 0.95, 0.95)
    -- btn.BorderRight:Hide()
    return btn
end
local function whisperDropdownMenu(self)
    local menuList = {
        {text=self.name, isTitle=1},
        {
            text = "密语",
            func = function ()
                ChatFrame_SendTell(self.name)
            end
        },
        {
            text = "快速密语",
            tooltipTitle = "|CFFFFDE00密语内容：|r",
            tooltipText = "|cffffffff请报：天赋+装等|r",
            func = function ()
                SendChatMessage("请报：天赋+装等", "WHISPER", nil, self.name)
            end
        },
        {
            text = "复制WCL",
            func = function ()
                --local url = "https://cn.classic.warcraftlogs.com/character/cn/" .. GetRealmName() .. "/" .. self.name .."?utm_source=addon" --怀旧服WLK
                local url = "https://cn.fresh.warcraftlogs.com/character/cn/" .. GetRealmName() .. "/" .. self.name .."?utm_source=addon" --经典怀旧服
                ChatEdit_ActivateChat(ChatEdit_ChooseBoxForSend())
                ChatEdit_ChooseBoxForSend():SetText("")
                ChatEdit_InsertLink(url)
                ChatEdit_ChooseBoxForSend():HighlightText()
            end
        },
        {
            text = "删除",
            func = function ()
                ZL_PLAYERLIST.whisperList[self.name] = nil
                ZL.RaidGroupsFrame.whisperFrame:Update()
            end
        }
    }
    local tdInspect, tooltipText, disabled
    local text = "观察"
    local tdName = "tdInspect"
    if GetAddOnInfo(tdName) then
        if IsAddOnLoaded(tdName) then
            tdInspect = LibStub("AceAddon-3.0"):GetAddon(tdName)
        else
            text = "开启"
            tooltipText = "请先开启|cffffffff" .. tdName .."|r插件"
        end
    else
        disabled = true
        tooltipText = "请先安装|cffffffff" .. tdName .."|r插件"
    end
    tinsert(menuList, 2, {
        text = text,
        disabled = disabled,
        tooltipWhileDisabled = 1,
        tooltipText = tooltipText,
        func = function ()
            if tdInspect then
                local Inspect= tdInspect:GetModule('Inspect', 'AceComm-3.0')
                Inspect:Query(nil, self.name)
            elseif text == "开启" then
                EnableAddOn(tdName)
                LoadAddOn(tdName)
                ZL.Print("|cffffffff" .. tdName .. "|r插件已开启。")
            end
        end
    })
    return menuList
end
local function applyToRaid()
    local toRaidBtn = ZL.RaidGroupsFrame.toRaidBtn
    if not toRaidBtn:IsEnabled() then return end
    local function tempfunc()
        local RaidGroupsData = ZL_PLAYERLIST.RaidGroupsData
        if not RaidGroupsData or not next(RaidGroupsData) then return end
        if not IsInRaid(1) then return end
        if not (UnitIsGroupLeader("player") or UnitIsGroupAssistant("player")) then
            ZL.Print("团长或助理权限才可以应用到团队。", true)
            return
        end
        for i = 1, MAX_RAID_MEMBERS do
            if UnitAffectingCombat("raid" .. i) then
                ZL.Print("有队员正在战斗中，无法应用到团队。", true)
                return
            end
        end
        toRaidBtn:Disable()
        local RaidGroupsFrame = ZL.RaidGroupsFrame
        RaidGroupsFrame:Update()
        local roster = {}
        for i = 1, 8 do roster[i] = {} end
        local edit, name, newName, raidIndex1, raidIndex2, slotBtn
        local subgroup1, bridgeIndex, bridgeSoltBtn
        local RLName = GetRaidRosterInfo(1) --RL永远是1号
        for i = 1, 8 do
            --先检测RL，RL永远在小队的第一位
            for j = 1, 5 do
                edit = RaidGroupsFrame.edits[(i-1)*5+j]
                name = edit.name
                if name == RLName then
                    tinsert(roster[i], name)
                    break
                end
            end
            --检测其他成员
            for j = 1, 5 do
                edit = RaidGroupsFrame.edits[(i-1)*5+j]
                name = edit.name
                if name and name ~= RLName then
                    --中间不能留空位置
                    tinsert(roster[i], name)
                end
            end
        end
        --先调换到指定的队伍
        for i = 1, 8 do
            for j, playerName in ipairs(roster[i]) do
                raidIndex1 = UnitInRaid(playerName)
                if raidIndex1 then
                    subgroup1 = select(3, GetRaidRosterInfo(raidIndex1))
                    if i ~= subgroup1 then
                        if roster[i][1] ~= RLName and playerName ~= RLName and _G["RaidGroup" .. i.. "Slot1"].button and _G[_G["RaidGroup" .. i.. "Slot1"].button].name == RLName then
                            j = j + 1
                        end
                        slotBtn = _G["RaidGroup" .. i.. "Slot" .. j].button
                        if slotBtn then
                            raidIndex2 = tonumber(strmatch(slotBtn, "^RaidGroupButton(%d+)$"))
                            if raidIndex2 then
                                if raidIndex1 ~= raidIndex2 then
                                    if i ~= subgroup1 then
                                        --不在一队，直接对调
                                        newName = nil
                                        SwapRaidSubgroup(raidIndex2, raidIndex1)
                                        while newName ~= playerName do
                                            sleep(0.2)
                                            newName = _G[slotBtn].name
                                        end
                                    end
                                end
                            end
                        else
                            SetRaidSubgroup(raidIndex1, i)
                            newName = nil
                            while newName ~= playerName do
                                sleep(0.2)
                                for k = 1, 5 do
                                    slotBtn = _G["RaidGroup" .. i.. "Slot" .. k].button
                                    if slotBtn then
                                        newName = _G[slotBtn].name
                                        if newName == playerName then
                                            break
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
            end
        end
        --再调换到指定位置
        for i = 1, 8 do
            for j, playerName in ipairs(roster[i]) do
                raidIndex1 = UnitInRaid(playerName)
                if raidIndex1 then
                    subgroup1 = select(3, GetRaidRosterInfo(raidIndex1))
                    if subgroup1 == i then
                        raidIndex2 = nil
                        if roster[i][1] ~= RLName and playerName ~= RLName and _G["RaidGroup" .. i.. "Slot1"].button and _G[_G["RaidGroup" .. i.. "Slot1"].button].name == RLName then
                            j = j + 1
                        end
                        slotBtn = _G["RaidGroup" .. i.. "Slot" .. j].button
                        if slotBtn then
                            raidIndex2 = tonumber(strmatch(slotBtn, "^RaidGroupButton(%d+)$"))
                            if raidIndex2 and raidIndex2 ~= raidIndex1 then
                                bridgeIndex = nil
                                local isBreak
                                for m = 1, 8 do
                                    for n = 1, 5 do
                                        if m ~= i then
                                            bridgeSoltBtn = _G["RaidGroup" .. m.. "Slot" .. n].button
                                            if bridgeSoltBtn then
                                                bridgeIndex = tonumber(strmatch(bridgeSoltBtn, "^RaidGroupButton(%d+)$"))
                                                if bridgeIndex and bridgeIndex ~= 1 then
                                                    isBreak = true
                                                    break
                                                else
                                                    bridgeIndex = nil
                                                end
                                            end
                                        end
                                    end
                                    if isBreak then break end
                                end
                                if bridgeIndex then
                                    SwapRaidSubgroup(raidIndex1, bridgeIndex)
                                    SwapRaidSubgroup(raidIndex2, bridgeIndex)
                                    SwapRaidSubgroup(raidIndex1, bridgeIndex)
                                    newName = nil
                                    while newName ~= playerName do
                                        sleep(0.2)
                                        newName = _G[slotBtn].name
                                    end
                                else
                                    --如果只有1个小队，没有可搭桥的情况待定
                                end
                            end
                        else

                        end
                    end
                end
            end
        end
        edit, name, newName, raidIndex1, raidIndex2, slotBtn = nil, nil, nil, nil, nil, nil
        subgroup1, bridgeIndex, bridgeSoltBtn = nil, nil, nil
        toRaidBtn:Enable()
    end
    local co = coroutine.create(tempfunc)
    local success, reason = coroutine.resume(co)
    -- print("线程结束", success, reason)
end
local function filterFunc(self, _, text, ...)
    if text == "THROTTLED" then --"该频道内可发送的信息数量受限"
        return true
    end
end
function ZL:CreateRaidGroupsFrame()
    if ZL.opt.filterThrottledMsg then
        ChatFrame_AddMessageEventFilter("CHAT_MSG_CHANNEL_NOTICE", filterFunc)
    else
        ChatFrame_RemoveMessageEventFilter("CHAT_MSG_CHANNEL_NOTICE", filterFunc)
    end
    ZL.RaidGroupsFrame = ZLCreateFrame("ZLRAIDGROUPSFRAME", ZL, nil, nil, nil, true, true, "AI开团助手")
    local RaidGroupsFrame = ZL.RaidGroupsFrame
    RaidGroupsFrame:Hide()
    -- 注册 ESC 键关闭窗口
    -- tinsert(UISpecialFrames, RaidGroupsFrame:GetName())
    RaidGroupsFrame.Background:SetColorTexture(0.1, 0.1, 0.1, 1)
    RaidGroupsFrame:SetClampedToScreen(false)
    RaidGroupsFrame:SetScript("OnMouseUp", function (self)
        self:StopMovingOrSizing()
        if not ZL.glb.ZLRaidGroupsFrame then ZL.glb.ZLRaidGroupsFrame = {} end
        ZL.glb.ZLRaidGroupsFrame.point, _, ZL.glb.ZLRaidGroupsFrame.relative, ZL.glb.ZLRaidGroupsFrame.x, ZL.glb.ZLRaidGroupsFrame.y = self:GetPoint()
    end)
    RaidGroupsFrame:SetScript("OnMouseDown", function (self)
        self:StartMoving()
    end)
    RaidGroupsFrame:SetScript("OnShow", function (self)
        self:Update()
        RaidGroupsFrame.profileFrame.profileFrameScrollFrame:Update()
    end)
    RaidGroupsFrame.resizeButton:Hide()
    RaidGroupsFrame:ClearAllPoints()
    if ZL.glb.ZLRaidGroupsFrame and ZL.glb.ZLRaidGroupsFrame.point then
        RaidGroupsFrame:SetPoint(ZL.glb.ZLRaidGroupsFrame.point, UIParent, ZL.glb.ZLRaidGroupsFrame.relative, ZL.glb.ZLRaidGroupsFrame.x, ZL.glb.ZLRaidGroupsFrame.y)
    else
        RaidGroupsFrame:SetPoint("CENTER")
    end
    RaidGroupsFrame:SetSize(1089, 675)

    RaidGroupsFrame.edits = {}
	for i = 1, 40 do
		local edit = CreateEditBox(RaidGroupsFrame, 210, 22, 14, "LEFT")
		edit:SetPoint("TOPLEFT",10+((i-1) % 10 < 5 and 0 or 225), -50-((i-1) % 5)*24-floor((i-1)/10)*142)
		edit.index = i
        local nameString = edit:CreateFontString(nil, "OVERLAY")
        nameString:SetSize(150, 22)
        nameString:SetPoint("TOPRIGHT", -1, -1)
        nameString:SetFont(GameFontNormal:GetFont(), 14, "OUTLINE")
        nameString:SetWordWrap(false)
        nameString:SetJustifyH("RIGHT")
        edit.nameString = nameString
        edit:Disable()
        edit:SetMovable(true)
		edit:RegisterForDrag("LeftButton")
		edit:SetScript("OnDragStart", function (self)
            if self:IsMovable() then
                ZL.GUI:CloseMenu()
                self:StartMoving()
            end
        end)
		edit:SetScript("OnDragStop", function (self)
            self:StopMovingOrSizing()
            self:ClearAllPoints()
            self:SetPoint("TOPLEFT",10+((i-1) % 10 < 5 and 0 or 225), -50-((i-1) % 5)*24-floor((i-1)/10)*142)
            for index = 1, #RaidGroupsFrame.edits do
                local edit2 = RaidGroupsFrame.edits[index]
                if edit2:IsMouseOver() and edit2 ~= self then
                    local textSelf = ZL_PLAYERLIST.RaidGroupsData[self.index]
                    local textMO = ZL_PLAYERLIST.RaidGroupsData[edit2.index]
                    ZL_PLAYERLIST.RaidGroupsData[self.index] = textMO
                    ZL_PLAYERLIST.RaidGroupsData[edit2.index] = textSelf
                    break
                end
            end
            RaidGroupsFrame:Update()
        end)
        edit:SetScript("OnMouseDown", function (self, button)
            if button == "LeftButton" then
                ZL.GUI:ToggleMenu(self, dropDownMenu(self), "cursor")
            elseif button == "RightButton" then
                local name = self.name or ""
                if #name > 0 then
                    name = ParseClassColorName(name)
                    local classID = ZL_PLAYERLIST.RaidGroupsData[self.index].classID
                    ZL.GUI:ToggleMenu(self, noInDropDownMenu(self, name, classID), "cursor")
                end
            end
        end)
        edit:SetScript("OnEnter", function (self)
            if #(self.name or "") > 0 then
                GameTooltipShow(self, "TOPRIGHT", "TOPLEFT")
                GameTooltip:AddLine(self.name)
                GameTooltip:AddLine(" ")
                local playerInfo = ZL.opt.playerInfo
                if playerInfo and playerInfo[self.name] and playerInfo[self.name].talentName then
                    for talentName, icon in pairs(playerInfo[self.name].talentName) do
                        if talentName == playerInfo[self.name].newTalentName then
                            GameTooltip:AddLine("|T" .. icon .. ":11:11:-2:-4|t" .. talentName .. " |cff4080FF←|r")
                        else
                            GameTooltip:AddLine("|T" .. icon .. ":11:11:-2:-4|t" .. talentName, 1, 1, 1)
                        end
                    end
                else
                    GameTooltip:AddLine("未获取到天赋", 1, 1, 1)
                end
                GameTooltip:Show()
            end
        end)
        edit:SetScript("OnLeave", function (self)
            GameTooltip:Hide()
        end)
        RaidGroupsFrame.edits[i] = edit
	end
    for i = 1, 4 do
        for j = 1, 2 do
            local fontString = CreatFrontString(210, 24)
            fontString:SetPoint("TOPLEFT",(j == 1 and 10 or 235),-50-(i-1)*142+20)
            fontString:SetText("小队 "..((i-1)*2+j))
        end
    end
    local fontString1 = CreatFrontString(300, nil, 13, true, "LEFT")
    fontString1:SetPoint("TOPLEFT", RaidGroupsFrame, "TOPLEFT", 10, -600)
    fontString1:SetText("*为手动设置的玩家职能\n\n左键拖拽：|cffffffff拖动文本框调整队伍|r\n左键点击：|cffffffff设置阵容职能|r\n右键点击：|cffffffff设置玩家职能|r")
    RaidGroupsFrame.toRaidBtn = CreateButton(nil, RaidGroupsFrame, "应用到团队", "TOPLEFT", RaidGroupsFrame, "TOPLEFT", 235, -599, 103, 21, 14, true, 0)
    local toRaidBtn = RaidGroupsFrame.toRaidBtn
    toRaidBtn:SetScript("OnClick", function (self)
        applyToRaid()
    end)
    RaidGroupsFrame.readRaidBtn = CreateButton(nil, RaidGroupsFrame, "读取团队阵容", "LEFT", toRaidBtn, "RIGHT", 4, 0, 103, 21, 14, true, 0)
    local readRaidBtn = RaidGroupsFrame.readRaidBtn
    readRaidBtn:SetScript("OnClick", function (self)
        ZL_PLAYERLIST.RaidGroupsData = {}
        local RaidGroupsData = ZL_PLAYERLIST.RaidGroupsData
        local playerInfo = ZL.opt.playerInfo
        local roster = {}
		for i = 1, 8 do roster[i] = {} end
        do
            local name, subgroup, fileName, classColor, classID, talent, _
            for i = 1, GetNumGroupMembers() do
                name, _, subgroup, _, _, fileName = GetRaidRosterInfo(i)
                classColor = select(4, GetClassColor(fileName))
                classID = tIndexOf(ZL.ClassFileList, fileName)
                talent = (playerInfo and playerInfo[name] and playerInfo[name].newTalentName) and playerInfo[name].newTalentName or classID
                tinsert(roster[subgroup], {
                    classColor = classColor,
                    classID = classID,
                    talent = talent,
                })
            end
            name, subgroup, fileName, classColor, classID, talent = nil, nil, nil, nil, nil, nil
        end
		for i = 1, 8 do
			for j = 1, 5 do
				if roster[i][j] then
                    RaidGroupsData[(i-1)*5+j] = roster[i][j]
                end
			end
		end
        RaidGroupsFrame:Update()
    end)
    local exportBtn = CreateButton(nil, RaidGroupsFrame, "导出当前阵容", "TOPLEFT", toRaidBtn, "BOTTOMLEFT", 0, -4, 103, 21, 14, true, 0)
    exportBtn:SetScript("OnClick", function (self)
        local RaidGroupsData = ZL_PLAYERLIST.RaidGroupsData
        if RaidGroupsData and next(RaidGroupsData) then
            local serialized = LibSerialize:Serialize(RaidGroupsData)
            local compressed = LibDeflate:CompressDeflate(serialized)
            local encoded = "!AutoAuction:2!" .. LibDeflate:EncodeForPrint(compressed)
            if not ZL.WaStringFrame then ZL:CreateWAStringFrame() end
            local editBox = ZL.WaStringFrame.scrollFrame.editBox
            ZL.WaStringFrame.Title:SetText("导出当前阵容")
            editBox:SetScript("OnTextChanged", function (self) self:HighlightText() end)
            editBox:SetScript("OnMouseUp", function(self) self:HighlightText() end)
            editBox:SetScript("OnEscapePressed", function() ZL.WaStringFrame:Hide() end)
            editBox:SetText(encoded)
            editBox:HighlightText()
            editBox:SetFocus()
            ZL.WaStringFrame:Show()
            encoded = nil
            compressed = nil
            serialized = nil
        else
            ZL.Print("当前没安排阵容！")
        end
    end)
    local importdBtn = CreateButton(nil, RaidGroupsFrame, "导入", "LEFT", exportBtn, "RIGHT", 4, 0, 103, 21, 14, true, 0)
    importdBtn:SetScript("OnClick", function (self)
        if not ZL.WaStringFrame then ZL:CreateWAStringFrame() end
        local editBox = ZL.WaStringFrame.scrollFrame.editBox
        ZL.WaStringFrame.Title:SetText("在下方粘贴字符串文本")
        editBox:SetScript("OnMouseUp", nil)
        editBox:SetScript("OnEscapePressed", function() ZL.WaStringFrame:Hide() end)
        editBox:SetScript("OnTextChanged", function (self)
            local text = self:GetText()
            if text:match("^!AutoAuction:2!.+") then
                text = text:gsub("!AutoAuction:%d+!", "", 1)
                local decodedData = LibDeflate:DecodeForPrint(text)
                local decompressedData = LibDeflate:DecompressDeflate(decodedData)
                local success, myReceivedData = LibSerialize:Deserialize(decompressedData)
                if success then
                    if ((not self.time) or (GetTime() - self.time) > 1) then
                        self.time = GetTime()
                        ZL_PLAYERLIST.RaidGroupsData = myReceivedData
                        RaidGroupsFrame:Update()
                        ZL.Print("导入成功！")
                    end
                else
                    ZL.Print("解析失败！", true, nil, 1, 0, 0)
                end
            end
        end)
        editBox:SetText("")
        editBox:HighlightText()
        editBox:SetFocus()

        ZL.WaStringFrame:Show()
    end)
    local refreshBtn = CreateButton(nil, RaidGroupsFrame, "刷新", "TOPLEFT", exportBtn, "BOTTOMLEFT", 0, -4, 103, 21, 14, true, 0)
    refreshBtn:SetScript("OnClick", function (self)
        RaidGroupsFrame:Update()
        RaidGroupsFrame.profileFrame.profileFrameScrollFrame:Update()
    end)
    local clearAllBtn = CreateButton(nil, RaidGroupsFrame, "清空当前阵容", "LEFT", refreshBtn, "RIGHT", 4, 0, 103, 21, 14, true, 0)
    clearAllBtn:SetScript("OnClick", function ()
        ZL_PLAYERLIST.RaidGroupsData = nil
        RaidGroupsFrame:Update()
    end)

    local fontString2 = CreatFrontString(212, 20, 14, false, "CENTER")
    fontString2:SetPoint("TOPLEFT", RaidGroupsFrame, "TOPLEFT", 465, -30)
    fontString2:SetText("职能未知")

    RaidGroupsFrame.unknowTalentFrame = CreateFrame("Button", nil, RaidGroupsFrame, BackdropTemplateMixin and "BackdropTemplate")
    local unknowTalentFrame = RaidGroupsFrame.unknowTalentFrame
    unknowTalentFrame:SetPoint("TOPLEFT", RaidGroupsFrame, "TOPLEFT", 465, -50)
    unknowTalentFrame:SetSize(212, 201) --260
    unknowTalentFrame:SetAlpha(1)
    unknowTalentFrame:SetBackdrop({
        bgFile = "Interface\\CharacterFrame\\UI-Party-Background",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 32, edgeSize = 6,
        insets = { left = 1, right = 1, top = 1, bottom = 1 }
    })
    unknowTalentFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b)
    unknowTalentFrame:SetBackdropColor(0.1, 0.1, 0.1, 0.2)
    --创建滚动条
    unknowTalentFrame.unknowTalentScrollFrame = CreateFrame("ScrollFrame", nil, unknowTalentFrame, "UIPanelScrollFrameTemplate")
    local unknowTalentScrollFrame = unknowTalentFrame.unknowTalentScrollFrame
    unknowTalentScrollFrame:SetFrameLevel(unknowTalentFrame:GetFrameLevel() + 1) -- 设置为比父框架高1级
    unknowTalentScrollFrame:SetPoint("TOPLEFT", unknowTalentFrame, "TOPLEFT", 5, -5)
    unknowTalentScrollFrame:SetPoint("BOTTOMRIGHT", unknowTalentFrame, "BOTTOMRIGHT", -2, 5)
    unknowTalentScrollFrame:SetClipsChildren(true) --必须设置为true，scrollFrame所有的子元素才会被剪切
    unknowTalentScrollFrame:SetScript("OnMouseWheel", ZL.ScrollFrame_OnMouseWheel) --重设滑动条鼠标滚轮事件
    --重设ScrollBar位置，放置到scrollFrame内，防止被剪切掉
    unknowTalentScrollFrame.ScrollBar:ClearAllPoints()
    unknowTalentScrollFrame.ScrollBar:SetPoint("TOPLEFT", unknowTalentScrollFrame, "TOPRIGHT", -20, -16)
    unknowTalentScrollFrame.ScrollBar:SetPoint("BOTTOMRIGHT", unknowTalentScrollFrame, "BOTTOMRIGHT", 0, 16)
    unknowTalentScrollFrame.content = CreateFrame("Frame", nil, unknowTalentScrollFrame)
    local unknowTalentContent = unknowTalentScrollFrame.content
    unknowTalentContent:SetPoint("TOPLEFT", unknowTalentScrollFrame, "TOPLEFT", 0, 0)
    unknowTalentContent:SetSize(180, 100)
    unknowTalentScrollFrame:SetScrollChild(unknowTalentContent)
    unknowTalentScrollFrame.entries = setmetatable({}, {
        __index = function (t, v)
            local f = CreateEditBox(unknowTalentContent, 180, 20, 13, "LEFT")
            f:Hide()
            f:Disable()
            f:SetPoint("TOPLEFT", unknowTalentContent, "TOPLEFT", 0, -(v-1)*22)
            f:SetMovable(true)
            f:SetScript("OnMouseDown", function (self, button)
                if button == "RightButton" then
                    ZL.GUI:ToggleMenu(self, noInDropDownMenu(self), "cursor")
                end
            end)
		    f:RegisterForDrag("LeftButton")
            f:SetScript("OnDragStart", function (self)
                if self:IsMovable() then
                    self:SetParent(RaidGroupsFrame)
                    self:StartMoving()
                end
            end)
            f:SetScript("OnDragStop", function (self)
                self:StopMovingOrSizing()
                self:SetParent(unknowTalentContent)
                self:ClearAllPoints()
                self:SetPoint("TOPLEFT", unknowTalentContent, "TOPLEFT", 0, -(v-1)*22)
                if time() - (self.time or 0) < 1 then return end
                self.time = time()
                for index = 1, #RaidGroupsFrame.edits do
                    local edit2 = RaidGroupsFrame.edits[index]
                    if edit2:IsMouseOver() and edit2 ~= self then
                        if #(edit2.name or "") > 0 then
                            ZL.Print("已安排任务，请选择空闲的格子！")
                            break
                        end
                        local data = ZL_PLAYERLIST.RaidGroupsData[edit2.index]
                        if data and data.classID ~= self.info.classID then
                            ZL.Print("职业不相符，请重新选择！")
                            break
                        end
                        if data then
                            ZL_PLAYERLIST.manualTalentInfo = ZL_PLAYERLIST.manualTalentInfo or {}
                            ZL_PLAYERLIST.manualTalentInfo[self.info.name] = ZL_PLAYERLIST.manualTalentInfo[self.info.name] or {}
                            ZL_PLAYERLIST.manualTalentInfo[self.info.name].talent = data.talent
                        else
                            ZL_PLAYERLIST.RaidGroupsData[edit2.index] = {
                                classID = self.info.classID,
                                classColor = self.info.classColor,
                                talent = self.info.classID,
                            }
                            ZL_PLAYERLIST.manualTalentInfo = ZL_PLAYERLIST.manualTalentInfo or {}
                            ZL_PLAYERLIST.manualTalentInfo[self.info.name] = ZL_PLAYERLIST.manualTalentInfo[self.info.name] or {}
                            ZL_PLAYERLIST.manualTalentInfo[self.info.name].talent = self.info.classID
                        end
                        RaidGroupsFrame:Update()
                        break
                    end
                end
            end)
            t[v] = f
            return f
        end
    })
    function unknowTalentScrollFrame:Update(list)
        for _, f in ipairs(unknowTalentScrollFrame.entries) do f.info = nil f:Hide() end
        local i = 1
        for name, data in pairs(list) do
            local colorName = "|c" .. data.classColor .. name .. "|r"
            local classID = data.classID
            local f = unknowTalentScrollFrame.entries[i]
            local text = "|T" .. talentIcon[classID][classID] .. ":12:12:-2|t" .. colorName
            f:SetText(text)
            f.info = data
            f:Show()
            i = i + 1
        end
    end

    local fontString3 = CreatFrontString(212, 20, 14, false, "CENTER")
    fontString3:SetPoint("LEFT", fontString2, "RIGHT", 15, 0)
    fontString3:SetText("职能不匹配")
    RaidGroupsFrame.noHavePositionFrame = CreateFrame("Button", nil, RaidGroupsFrame, BackdropTemplateMixin and "BackdropTemplate")
    local noHavePositionFrame = RaidGroupsFrame.noHavePositionFrame
    noHavePositionFrame:SetPoint("TOPLEFT", RaidGroupsFrame, "TOPLEFT", 692, -50)
    noHavePositionFrame:SetSize(unknowTalentFrame:GetWidth(), unknowTalentFrame:GetHeight())
    noHavePositionFrame:SetAlpha(1)
    noHavePositionFrame:SetBackdrop({
        bgFile = "Interface\\CharacterFrame\\UI-Party-Background",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 32, edgeSize = 6,
        insets = { left = 1, right = 1, top = 1, bottom = 1 }
    })
    noHavePositionFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b)
    noHavePositionFrame:SetBackdropColor(0.1, 0.1, 0.1, 0.2)
    --创建滚动条
    noHavePositionFrame.noHavePositionScrollFrame = CreateFrame("ScrollFrame", nil, noHavePositionFrame, "UIPanelScrollFrameTemplate")
    local noHavePositionScrollFrame = noHavePositionFrame.noHavePositionScrollFrame
    noHavePositionScrollFrame:SetFrameLevel(noHavePositionFrame:GetFrameLevel() + 1) -- 设置为比父框架高1级
    noHavePositionScrollFrame:SetPoint("TOPLEFT", noHavePositionFrame, "TOPLEFT", 5, -5)
    noHavePositionScrollFrame:SetPoint("BOTTOMRIGHT", noHavePositionFrame, "BOTTOMRIGHT", -2, 5)
    noHavePositionScrollFrame:SetClipsChildren(true) --必须设置为true，scrollFrame所有的子元素才会被剪切
    noHavePositionScrollFrame:SetScript("OnMouseWheel", ZL.ScrollFrame_OnMouseWheel) --重设滑动条鼠标滚轮事件
    --重设ScrollBar位置，放置到scrollFrame内，防止被剪切掉
    noHavePositionScrollFrame.ScrollBar:ClearAllPoints()
    noHavePositionScrollFrame.ScrollBar:SetPoint("TOPLEFT", noHavePositionScrollFrame, "TOPRIGHT", -20, -17)
    noHavePositionScrollFrame.ScrollBar:SetPoint("BOTTOMRIGHT", noHavePositionScrollFrame, "BOTTOMRIGHT", 0, 17)
    noHavePositionScrollFrame.content = CreateFrame("Frame", nil, noHavePositionScrollFrame)
    local content = noHavePositionScrollFrame.content
    content:SetPoint("TOPLEFT", noHavePositionScrollFrame, "TOPLEFT", 0, 0)
    content:SetSize(180, 100)
    noHavePositionScrollFrame:SetScrollChild(content)
    -- noHavePositionScrollFrame.ScrollBar:SetFrameLevel(content:GetFrameLevel()+100)
    noHavePositionScrollFrame.entries = setmetatable({}, {
        __index = function (t, v)
            local f = CreateEditBox(content, 180, 20, 13, "LEFT")
            f:Disable()
            f:Hide()
            f:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -(v-1)*22)
            f:SetMovable(true)
            f:SetScript("OnMouseDown", function (self, button)
                if button == "RightButton" then
                    ZL.GUI:ToggleMenu(self, noInDropDownMenu(self), "cursor")
                end
            end)
		    f:RegisterForDrag("LeftButton")
            f:SetScript("OnDragStart", function (self)
                if self:IsMovable() then
                    self:SetParent(RaidGroupsFrame)
                    self:StartMoving()
                end
            end)
            f:SetScript("OnDragStop", function (self)
                self:StopMovingOrSizing()
                self:SetParent(content)
                self:ClearAllPoints()
                self:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -(v-1)*22)
                if time() - (self.time or 0) < 1 then return end
                self.time = time()
                for index = 1, #RaidGroupsFrame.edits do
                    local edit2 = RaidGroupsFrame.edits[index]
                    if edit2:IsMouseOver() and edit2 ~= self then
                        if #(edit2.name or "") > 0 then
                            ZL.Print("已安排任务，请选择空闲的格子！")
                            break
                        end
                        ZL_PLAYERLIST.RaidGroupsData[edit2.index] = {
                            classID = self.info.classID,
                            classColor = self.info.classColor,
                            talent = self.info.talent,
                        }
                        RaidGroupsFrame:Update()
                        break
                    end
                end
            end)
            f:SetScript("OnEnter", function (self)
                local name = self.info.name
                if #(name or "") > 0 then
                    GameTooltipShow(self, "TOPRIGHT", "TOPLEFT")
                    GameTooltip:AddLine(name)
                    GameTooltip:AddLine(" ")
                    local playerInfo = ZL.opt.playerInfo
                    if playerInfo and playerInfo[name] and playerInfo[name].talentName then
                        for talentName, icon in pairs(playerInfo[name].talentName) do
                            if talentName == playerInfo[name].newTalentName then
                                GameTooltip:AddLine("|T" .. icon .. ":11:11:-2:-4|t" .. talentName .. " |cff4080FF←|r")
                            else
                                GameTooltip:AddLine("|T" .. icon .. ":11:11:-2:-4|t" .. talentName, 1, 1, 1)
                            end
                        end
                    else
                        GameTooltip:AddLine("未获取到天赋", 1, 1, 1)
                    end
                    GameTooltip:Show()
                end
            end)
            f:SetScript("OnLeave", function (self)
                GameTooltip:Hide()
            end)
            t[v] = f
            return f
        end
    })
    function noHavePositionScrollFrame:Update(list)
        for _, f in ipairs(noHavePositionScrollFrame.entries) do f.info = nil f:Hide() end
        local i = 1
        for name, data in pairs(list) do
            local colorName = "|c" .. data.classColor .. name .. "|r"
            local talent = data.talent
            local classID = data.classID
            local talentSorce = data.talentSorce
            local f = noHavePositionScrollFrame.entries[i]
            local text = (talentSorce==1 and "*" or "") .. colorName .. "  |T" .. talentIcon[classID][talent] .. ":12:12:-2|t|c" .. data.classColor .. talentOtherName[classID][talent][1] .. "|r"
            f:SetText(text)
            f.info = data
            f:Show()
            i = i + 1
        end
    end

    local fontString4 = CreatFrontString(439, nil, 13, true, "LEFT")
    fontString4:SetPoint("TOPLEFT", unknowTalentFrame, "BOTTOMLEFT", 0, -5)
    fontString4:SetText("*以上2种需手动拖动到左边对应位置或设置对应职能\n左键拖拽：|cffffffff拖动文本框到左边|r    右键点击：|cffffffff设置玩家职能|r")
    
    local fontString5 = CreatFrontString(182, 20, 14, false, "CENTER")
    fontString5:SetPoint("TOPLEFT", RaidGroupsFrame, "TOPLEFT", 919, -30)
    fontString5:SetText("自定义阵容")

    RaidGroupsFrame.profileFrame = CreateFrame("Button", nil, RaidGroupsFrame, BackdropTemplateMixin and "BackdropTemplate")
    local profileFrame = RaidGroupsFrame.profileFrame
    profileFrame:SetPoint("TOPLEFT", fontString5, "BOTTOMLEFT", 0, 0)
    profileFrame:SetPoint("BOTTOMRIGHT", noHavePositionFrame, "BOTTOMRIGHT", 177, 0)
    profileFrame:SetAlpha(1)
    profileFrame:SetBackdrop({
        bgFile = "Interface\\CharacterFrame\\UI-Party-Background",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 32, edgeSize = 6,
        insets = { left = 1, right = 1, top = 1, bottom = 1 }
    })
    profileFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b)
    profileFrame:SetBackdropColor(0.1, 0.1, 0.1, 0.2)
    --创建滚动条
    profileFrame.profileFrameScrollFrame = CreateFrame("ScrollFrame", nil, profileFrame, "UIPanelScrollFrameTemplate")
    local profileFrameScrollFrame = profileFrame.profileFrameScrollFrame
    profileFrameScrollFrame:SetFrameLevel(profileFrame:GetFrameLevel() + 1) -- 设置为比父框架高1级
    profileFrameScrollFrame:SetPoint("TOPLEFT", profileFrame, "TOPLEFT", 5, -5)
    profileFrameScrollFrame:SetPoint("BOTTOMRIGHT", profileFrame, "BOTTOMRIGHT", -2, 5)
    profileFrameScrollFrame:SetClipsChildren(true) --必须设置为true，scrollFrame所有的子元素才会被剪切
    profileFrameScrollFrame:SetScript("OnMouseWheel", ZL.ScrollFrame_OnMouseWheel) --重设滑动条鼠标滚轮事件
    --重设ScrollBar位置，放置到scrollFrame内，防止被剪切掉
    profileFrameScrollFrame.ScrollBar:ClearAllPoints()
    profileFrameScrollFrame.ScrollBar:SetPoint("TOPLEFT", profileFrameScrollFrame, "TOPRIGHT", -20, -17)
    profileFrameScrollFrame.ScrollBar:SetPoint("BOTTOMRIGHT", profileFrameScrollFrame, "BOTTOMRIGHT", 0, 17)
    profileFrameScrollFrame.content = CreateFrame("Frame", nil, profileFrameScrollFrame)
    local profileFrameContent = profileFrameScrollFrame.content
    profileFrameContent:SetPoint("TOPLEFT", profileFrameScrollFrame, "TOPLEFT", 0, 0)
    profileFrameContent:SetSize(130, 100)
    profileFrameScrollFrame:SetScrollChild(profileFrameContent)
    -- profileFrameScrollFrame.ScrollBar:SetFrameLevel(profileFrameContent:GetFrameLevel()+100)
    profileFrameContent.delBtn = CreateFrame("Button", nil, profileFrameContent)
    local delBtn = profileFrameContent.delBtn
    delBtn:Hide()
    delBtn:SetPoint("TOPLEFT")
    delBtn:SetSize(16, 16)
    delBtn:SetNormalTexture(136813)
    delBtn:SetHighlightTexture(136813)
    delBtn:SetScript("OnClick", function (self)
        ZL.opt.RaidGroupsData[self.profileName] = nil
        profileFrameScrollFrame:Update()
        ZL.Print("已删除：[|cffffffff" .. self.profileName .. "|r]")
    end)
    delBtn:SetScript("OnLeave", function (self)
        delBtn:Hide()
    end)
    profileFrameScrollFrame.entries = setmetatable({}, {
        __index = function (t, v)
            local f = CreateFrame("Button", nil, profileFrameContent)
            f:Hide()
            f:SetSize(130, 18)
            if v == 1 then
                f:SetPoint("TOPLEFT", profileFrameContent, "TOPLEFT", 0, 0)
            else
                f:SetPoint("TOPLEFT", t[v-1], "BOTTOMLEFT", 0, 0)
            end
            f:SetNormalFontObject("GameFontNormal")
            f:SetHighlightFontObject("GameFontHighlight")
            f:SetText(" ")
            local font = f:GetFontString()
            if font then
                font:SetAllPoints()
                font:SetFont(GameFontNormal:GetFont(), 13, "OUTLINE")
                font:SetTextColor(0.95, 0.95, 0.95)
                font:SetJustifyH("LEFT")
            end
            f:SetHighlightTexture([[Interface\QuestFrame\UI-QuestLogTitleHighlight]])
            f:SetScript("OnEnter", function (self)
                local profileName = self:GetText()
                delBtn.profileName = profileName
                delBtn:ClearAllPoints()
                delBtn:SetParent(f)
                delBtn:SetPoint("RIGHT", f, "RIGHT", -5, 0)
                delBtn:Show()
                if profileName then
                    GameTooltipShow(self, "LEFT", "RIGHT", 25, 0)
                    GameTooltip:AddLine(profileName)
                    GameTooltip:AddLine("|cff808080" .. date("%Y-%m-%d %H:%M:%S", ZL.opt.RaidGroupsData[profileName].stamptime) .. "|r")
                    GameTooltip:AddLine("双击：|cffffffff应用到当前阵容|r")
                    GameTooltip:Show()
                end
            end)
            f:SetScript("OnLeave", function (self)
                GameTooltip:Hide()
                if not f:IsMouseOver() then
                    delBtn:Hide()
                end
            end)
            f:SetScript("OnDoubleClick", function ()
                ZL_PLAYERLIST.RaidGroupsData = CopyTable(ZL.opt.RaidGroupsData[f:GetText()].data)
                RaidGroupsFrame:Update()
            end)
            t[v] = f
            return f
        end
    })
    function profileFrameScrollFrame:Update()
        for _, f in ipairs(profileFrameScrollFrame.entries) do f:Hide() end
        if not ZL.opt.RaidGroupsData then return end
        local f
        local tempList = {}
        for name, data in pairs(ZL.opt.RaidGroupsData) do
            tinsert(tempList, {name, data.stamptime})
        end
        table.sort(tempList, function (a, b)
            if a[2] > b[2] then
                return true
            end
            return false
        end)
        for i, data in ipairs(tempList) do
            tempList[i] = data[1]
        end
        for i, name in ipairs(tempList) do
            f = profileFrameScrollFrame.entries[i]
            f:SetText(name)
            f:Show()
        end
    end

    local presetsBtn = CreateButton(nil, RaidGroupsFrame, "预设阵容 |T130940:14|t", "TOPLEFT", profileFrame, "BOTTOMLEFT", 0, -3, 162, 20, 14, true, 0)
    presetsBtn:SetScript("OnClick", function (self)
        local function tempfunc()
            local menuList = {}
            for _, project in ipairs(ZL.WOW_PROJECT) do
                local menuTable = {}
                for _, instance in ipairs(ZL.WOW_RAID_INSTANCE[project]) do
                    if presetsProfiles[instance] then
                        tinsert(menuTable, {
                            text = instance,
                            func = function ()
                                ZL_PLAYERLIST.RaidGroupsData = CopyTable(presetsProfiles[instance])
                                ZL.GUI:CloseMenu()
                                RaidGroupsFrame:Update()
                            end
                        })
                    end
                end
                if #menuTable > 0 then
                    tinsert(menuList, {
                        text = project,
                        hasArrow = 1,
                        menuTable = menuTable,
                    })
                end
            end
            return menuList
        end
        ZL.GUI:ToggleMenu(self, tempfunc(), "cursor")
    end)
    local saveProfileBtn = CreateButton(nil, RaidGroupsFrame, "保存当前阵容为 |T130940:14|t", "TOPLEFT", presetsBtn, "BOTTOMLEFT", 0, -3, 162, 20, 14, true, 0)
    saveProfileBtn:SetScript("OnClick", function (self)
        if not ZL_PLAYERLIST.RaidGroupsData or not next(ZL_PLAYERLIST.RaidGroupsData) then
            ZL.Print("当前阵容未进行任何设置，无法保存！")
            return
        end
        local function tmepfunc()
            local menuList = {
                {
                    text="新阵容",
                    func = function ()
                        if not StaticPopupDialogs["ZL_SAVERAIDGROUPSDATA"] then
                            StaticPopupDialogs["ZL_SAVERAIDGROUPSDATA"] = {
                                text = "请输入阵容配置名称",
                                button1 = "保存",
                                button2 = "取消",
                                hasEditBox = true,
                                EditBoxOnEnterPressed = function(self) self:GetParent():GetButton1():Click() end,
                                EditBoxOnTextChanged = function(self)
                                    if #(self:GetText() or "") > 0 then
                                        self:GetParent():GetButton1():Enable()
                                    else
                                        self:GetParent():GetButton1():Disable()
                                    end
                                end,
                                OnShow = function(self)
                                    self:GetButton1():Disable()
                                    self:GetEditBox():SetNumeric(false)
                                    self:GetEditBox():SetAutoFocus(true)
                                end,
                                OnAccept = function(self, data)
                                    ZL.opt.RaidGroupsData = ZL.opt.RaidGroupsData or {}
                                    local RaidGroupsData = ZL.opt.RaidGroupsData
                                    local profileName = self:GetEditBox():GetText()
                                    if RaidGroupsData[profileName] then
                                        if not StaticPopupDialogs["ZL_SAVERAIDGROUPSDATAALARM"] then
                                            StaticPopupDialogs["ZL_SAVERAIDGROUPSDATAALARM"] = {
                                                text = "|CFFFFDE00" .. profileName .. "|r已存在，是否覆盖？",
                                                button1 = "覆盖",
                                                button2 = "取消",
                                                OnShow = function(self)
                                                    self:GetEditBox():SetNumeric(false)
                                                    self:GetEditBox():SetAutoFocus(false)
                                                end,
                                                OnAccept = function()
                                                    RaidGroupsData[profileName] = {
                                                        stamptime = time(),
                                                        data = CopyTable(ZL_PLAYERLIST.RaidGroupsData),
                                                    }
                                                    profileFrameScrollFrame:Update()
                                                    ZL.Print("[|cffffffff" .. profileName .. "|r]保存成功。")
                                                end,
                                                timeout = 0,
                                                whileDead = true,
                                                hideOnEscape = true,
                                            }
                                            StaticPopup_Show("ZL_SAVERAIDGROUPSDATAALARM")
                                        end
                                    else
                                        RaidGroupsData[profileName] = {
                                            stamptime = time(),
                                            data = CopyTable(ZL_PLAYERLIST.RaidGroupsData)
                                        }
                                        profileFrameScrollFrame:Update()
                                        ZL.Print("[|cffffffff" .. profileName .. "|r]保存成功。")
                                    end
                                end,
                                timeout = 0,
                                whileDead = true,
                                hideOnEscape = true,
                            }
                        end
                        StaticPopup_Show("ZL_SAVERAIDGROUPSDATA")
                    end
                }
            }
            local RaidGroupsData = ZL.opt.RaidGroupsData
            if RaidGroupsData and next(RaidGroupsData) then
                tinsert(menuList, {isSeparator=1})
                local tempList = {}
                for name, data in pairs(RaidGroupsData) do
                    tinsert(tempList, {name, data.stamptime})
                end
                table.sort(tempList, function (a, b)
                    if a[2] > b[2] then
                        return true
                    end
                    return false
                end)
                for i, data in ipairs(tempList) do
                    tempList[i] = data[1]
                end
                for _, name in ipairs(tempList) do
                    tinsert(menuList, {
                        text = name,
                        func = function ()
                            RaidGroupsData[name] = {
                                stamptime = time(),
                                data = CopyTable(ZL_PLAYERLIST.RaidGroupsData),
                            }
                            profileFrameScrollFrame:Update()
                            ZL.Print("[|cffffffff" .. name .. "|r]保存成功。")
                        end
                    })
                end
            end
            return menuList
        end
        ZL.GUI:ToggleMenu(self, tmepfunc(), "cursor")
    end)
    local fontString6 = CreatFrontString(nil, 22, 15, nil, "LEFT")
    fontString6:SetPoint("TOPLEFT", fontString4, "BOTTOMLEFT", 0, -25)
    fontString6:SetText("自定义喊话内容")

    RaidGroupsFrame.msgContentFrame = CreateFrame("Button", nil, RaidGroupsFrame, BackdropTemplateMixin and "BackdropTemplate")
    local msgContentFrame = RaidGroupsFrame.msgContentFrame
    msgContentFrame:SetPoint("TOPLEFT", fontString6, "BOTTOMLEFT", 0, -5)
    msgContentFrame:SetSize(306, 72)
    msgContentFrame:SetAlpha(1)
    msgContentFrame:SetBackdrop({
        bgFile = "Interface\\CharacterFrame\\UI-Party-Background",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 32, edgeSize = 6,
        insets = { left = 1, right = 1, top = 1, bottom = 1 }
    })
    msgContentFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b)
    msgContentFrame:SetBackdropColor(0.1, 0.1, 0.1, 0.9)
    --创建滚动条
    msgContentFrame.msgContentScrollFrame = CreateFrame("ScrollFrame", nil, msgContentFrame, "UIPanelScrollFrameTemplate")
    local msgContentScrollFrame = msgContentFrame.msgContentScrollFrame
    msgContentScrollFrame:SetFrameLevel(msgContentFrame:GetFrameLevel() + 1) -- 设置为比父框架高1级
    msgContentScrollFrame:SetPoint("TOPLEFT", msgContentFrame, "TOPLEFT", 5, -3)
    msgContentScrollFrame:SetPoint("BOTTOMRIGHT", msgContentFrame, "BOTTOMRIGHT", 0, 3)
    msgContentScrollFrame:SetClipsChildren(true) --必须设置为true，scrollFrame所有的子元素才会被剪切
    msgContentScrollFrame:SetScript("OnMouseWheel", ZL.ScrollFrame_OnMouseWheel) --重设滑动条鼠标滚轮事件
    --重设ScrollBar位置，放置到scrollFrame内，防止被剪切掉
    msgContentScrollFrame.ScrollBar:ClearAllPoints()
    msgContentScrollFrame.ScrollBar:SetPoint("TOPLEFT", msgContentScrollFrame, "TOPRIGHT", -20, -16)
    msgContentScrollFrame.ScrollBar:SetPoint("BOTTOMRIGHT", msgContentScrollFrame, "BOTTOMRIGHT", 0, 15)
    -- 创建编辑框
    msgContentFrame.msgContentEditBox = CreateFrame("EditBox", nil, msgContentScrollFrame)
    local msgContentEditBox = msgContentFrame.msgContentEditBox
    msgContentEditBox:SetPoint("TOPLEFT")
    msgContentEditBox:SetSize(msgContentScrollFrame:GetWidth() - 21, 50) -- 减去滚动条宽度
    msgContentEditBox:EnableMouse(true)
    msgContentEditBox:SetTextColor(0.95, 0.95, 0.95)
    msgContentEditBox:SetMultiLine(true)
    msgContentEditBox:SetAutoFocus(false)
    msgContentEditBox:SetFontObject("ChatFontNormal")
    -- msgContentEditBox:SetMaxBytes(251)
    msgContentEditBox:SetTextInsets(0, 0, 2, 0)
    msgContentEditBox:SetText(ZL.opt.lastOldMsgContent or "")
    msgContentEditBox.msgContentFontString = CreatFrontString(nil, 20, 12, nil, "LEFT")
    local msgContentFontString = msgContentEditBox.msgContentFontString
    msgContentFontString:SetPoint("TOPLEFT", msgContentFrame, "BOTTOMLEFT")
    msgContentFontString:SetTextColor(0.6, 0.6, 0.6, 1)
    msgContentEditBox:SetScript("OnEscapePressed",function (self)
        self:ClearFocus()
    end)
    msgContentEditBox:SetScript("OnEnterPressed", function (self)
        self:ClearFocus()
    end)
    msgContentEditBox:SetScript("OnEditFocusLost",function (self)
        self:HighlightText(0, 0)
    end)
    msgContentEditBox:SetScript("OnEditFocusGained",function (self)
        self:HighlightText()
    end)
    msgContentEditBox:SetScript("OnTextChanged", function (self)
        local myMsg = self:GetText() or ""
        myMsg = myMsg:gsub("，", ", ")
        if #myMsg > 250 then
            self:SetText(ZL.opt.lastOldMsgContent)
        end
        ZL.opt.lastOldMsgContent = self:GetText() or ""
        msgContentFontStringUpdate()
    end)
    msgContentScrollFrame:SetScrollChild(msgContentEditBox)
    msgContentScrollFrame:SetScript("OnMouseDown", function (self, button)
        if button == "LeftButton" then
            msgContentEditBox:SetFocus()
        end
    end)

    RaidGroupsFrame.aiMsgContentFrame = CreateFrame("Button", nil, RaidGroupsFrame, BackdropTemplateMixin and "BackdropTemplate")
    local aiMsgContentFrame = RaidGroupsFrame.aiMsgContentFrame
    aiMsgContentFrame:SetPoint("LEFT", msgContentFrame, "RIGHT", 4, 0)
    aiMsgContentFrame:SetSize(306, 72)
    aiMsgContentFrame:SetAlpha(1)
    aiMsgContentFrame:SetBackdrop({
        bgFile = "Interface\\CharacterFrame\\UI-Party-Background",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 32, edgeSize = 6,
        insets = { left = 1, right = 1, top = 1, bottom = 1 }
    })
    aiMsgContentFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b)
    aiMsgContentFrame:SetBackdropColor(0.1, 0.1, 0.1, 0.9)
    --创建滚动条
    aiMsgContentFrame.aiMsgContentScrollFrame = CreateFrame("ScrollFrame", nil, aiMsgContentFrame, "UIPanelScrollFrameTemplate")
    local aiMsgContentScrollFrame = aiMsgContentFrame.aiMsgContentScrollFrame
    aiMsgContentScrollFrame:SetFrameLevel(aiMsgContentFrame:GetFrameLevel() + 1) -- 设置为比父框架高1级
    aiMsgContentScrollFrame:SetPoint("TOPLEFT", aiMsgContentFrame, "TOPLEFT", 5, -3)
    aiMsgContentScrollFrame:SetPoint("BOTTOMRIGHT", aiMsgContentFrame, "BOTTOMRIGHT", 0, 3)
    aiMsgContentScrollFrame:SetClipsChildren(true) --必须设置为true，scrollFrame所有的子元素才会被剪切
    aiMsgContentScrollFrame:SetScript("OnMouseWheel", ZL.ScrollFrame_OnMouseWheel) --重设滑动条鼠标滚轮事件
    --重设ScrollBar位置，放置到scrollFrame内，防止被剪切掉
    aiMsgContentScrollFrame.ScrollBar:ClearAllPoints()
    aiMsgContentScrollFrame.ScrollBar:SetPoint("TOPLEFT", aiMsgContentScrollFrame, "TOPRIGHT", -20, -16)
    aiMsgContentScrollFrame.ScrollBar:SetPoint("BOTTOMRIGHT", aiMsgContentScrollFrame, "BOTTOMRIGHT", 0, 15)
    -- 创建编辑框
    aiMsgContentFrame.aiMsgContentEditBox = CreateFrame("EditBox", nil, aiMsgContentScrollFrame)
    local aiMsgContentEditBox = aiMsgContentFrame.aiMsgContentEditBox
    aiMsgContentEditBox:Disable()
    aiMsgContentEditBox:SetPoint("TOPLEFT")
    aiMsgContentEditBox:SetSize(aiMsgContentScrollFrame:GetWidth() - 21, 50) -- 减去滚动条宽度
    aiMsgContentEditBox:EnableMouse(true)
    aiMsgContentEditBox:SetTextColor(0.6, 0.6, 0.6)
    aiMsgContentEditBox:SetMultiLine(true)
    aiMsgContentEditBox:SetAutoFocus(false)
    aiMsgContentEditBox:SetFontObject("ChatFontNormal")
    aiMsgContentEditBox:SetMaxBytes(251)
    aiMsgContentEditBox:SetTextInsets(0, 0, 2, 0)
    aiMsgContentEditBox:SetScript("OnTextChanged", function (self)
        msgContentFontStringUpdate()
    end)
    aiMsgContentEditBox:SetScript("OnMouseDown", function (self, button)
        if IsShiftKeyDown() and button == "LeftButton" then
            msgContentEditBox:SetText((msgContentEditBox:GetText() or "") .. (self:GetText() or ""))
        end
    end)
    aiMsgContentEditBox:SetScript("OnEnter", function (self)
        GameTooltipShow(self, "TOPLEFT", "TOPRIGHT", 22)
        GameTooltip:AddLine("提示")
        GameTooltip:AddLine("内容根据阵容自动生成，无法手动修改", 1, 1, 1)
        GameTooltip:AddLine("Shift+左键：|cffffffff复制到自定义内容区|r")
        GameTooltip:Show()
    end)
    aiMsgContentEditBox:SetScript("OnLeave", function (self)
        GameTooltip:Hide()
    end)
    aiMsgContentScrollFrame:SetScrollChild(aiMsgContentEditBox)
    aiMsgContentScrollFrame:SetScript("OnEnter", function (self)
        GameTooltipShow(aiMsgContentEditBox, "TOPLEFT", "TOPRIGHT", 22)
        GameTooltip:AddLine("提示")
        GameTooltip:AddLine("内容根据阵容自动生成，无法手动修改", 1, 1, 1)
        GameTooltip:AddLine("Shift+左键：|cffffffff复制到自定义内容区|r")
        GameTooltip:Show()
    end)
    aiMsgContentScrollFrame:SetScript("OnLeave", function (self)
        GameTooltip:Hide()
    end)
    aiMsgContentScrollFrame:SetScript("OnMouseDown", function (self, button)
        if IsShiftKeyDown() and button == "LeftButton" then
            msgContentEditBox:SetText((msgContentEditBox:GetText() or "") .. (aiMsgContentEditBox:GetText() or ""))
        end
    end)

    RaidGroupsFrame.shortMsgBtn = CreateButton(nil, RaidGroupsFrame, "快捷 |T130940:14|t", "LEFT", fontString6, "RIGHT", 10, 0, 70, 22, 14, true, 0)
    local shortMsgBtn = RaidGroupsFrame.shortMsgBtn
    shortMsgBtn:SetScript("OnClick", function (self)
        local menuList = {
            {
                text = "另存为",
                func = function ()
                    local msg = msgContentEditBox:GetText() or ""
                    if #msg == 0 then
                        ZL.Print("没有内容，请先输入！")
                        return
                    end
                    if not StaticPopupDialogs["ZL_SAVERAIDGROUPSMESSAGE"] then
                        StaticPopupDialogs["ZL_SAVERAIDGROUPSMESSAGE"] = {
                            text = "请输入快捷名称：如25人HICC",
                            button1 = "保存",
                            button2 = "取消",
                            hasEditBox = true,
                            EditBoxOnEnterPressed = function(self) self:GetParent():GetButton1():Click() end,
                            EditBoxOnTextChanged = function(self)
                                if #(self:GetText() or "") > 0 then
                                    self:GetParent():GetButton1():Enable()
                                else
                                    self:GetParent():GetButton1():Disable()
                                end
                            end,
                            OnShow = function(self)
                                self:GetButton1():Disable()
                                self:GetEditBox():SetNumeric(false)
                                self:GetEditBox():SetAutoFocus(true)
                            end,
                            OnAccept = function(self, data)
                                ZL.opt.RaidGroupsMessageList = ZL.opt.RaidGroupsMessageList or {}
                                local RaidGroupsMessageList = ZL.opt.RaidGroupsMessageList
                                local profileName = self:GetEditBox():GetText()
                                if RaidGroupsMessageList[profileName] then
                                    if not StaticPopupDialogs["ZL_SAVERAIDGROUPSMESSAGEALARM"] then
                                        StaticPopupDialogs["ZL_SAVERAIDGROUPSMESSAGEALARM"] = {
                                            text = "|CFFFFDE00" .. profileName .. "|r已存在，是否覆盖？",
                                            button1 = "覆盖",
                                            button2 = "取消",
                                            OnShow = function(self)
                                                self:GetEditBox():SetNumeric(false)
                                                self:GetEditBox():SetAutoFocus(false)
                                            end,
                                            OnAccept = function()
                                                RaidGroupsMessageList[profileName] = {
                                                    stamptime = time(),
                                                    data = msg,
                                                }
                                                ZL.Print("[|cffffffff" .. profileName .. "|r]保存成功。")
                                            end,
                                            timeout = 0,
                                            whileDead = true,
                                            hideOnEscape = true,
                                        }
                                        StaticPopup_Show("ZL_SAVERAIDGROUPSMESSAGEALARM")
                                    end
                                else
                                    RaidGroupsMessageList[profileName] = {
                                        stamptime = time(),
                                        data = msg,
                                    }
                                    ZL.Print("[|cffffffff" .. profileName .. "|r]保存成功。")
                                end
                            end,
                            timeout = 0,
                            whileDead = true,
                            hideOnEscape = true,
                        }
                    end
                    StaticPopup_Show("ZL_SAVERAIDGROUPSMESSAGE")
                end
            }
        }
        local RaidGroupsMessageList = ZL.opt.RaidGroupsMessageList
        if RaidGroupsMessageList and next(RaidGroupsMessageList) then
            tinsert(menuList, {isSeparator=1})
            local tempList = {}
            for shorName, data in pairs(RaidGroupsMessageList) do
                tinsert(tempList, {shorName, data.stamptime})
            end
            table.sort(tempList, function (a, b)
                if a[2] > b[2] then
                    return true
                elseif a[2] < b[2] then
                    return false
                else
                    return a[1] < b[2]
                end
            end)
            for _, v in ipairs(tempList) do
                tinsert(menuList, {
                    text = v[1],
                    tooltipTitle = "|CFFFFDE00" .. v[1] .. "|r",
                    tooltipText = "|cff808080" .. date("%Y-%m-%d %H:%M:%S", v[2]) .. "|r\n|cffffffff" .. RaidGroupsMessageList[v[1]].data .. "|r",
                    hasArrow = 1,
                    menuTable = {
                        {
                            text = "删除",
                            func = function ()
                                RaidGroupsMessageList[v[1]] = nil
                                ZL.GUI:CloseMenu()
                            end
                        }
                    },
                    func = function ()
                        msgContentEditBox:SetText(RaidGroupsMessageList[v[1]].data)
                    end,
                })
            end
            tempList = nil
        end
        ZL.GUI:ToggleMenu(self, menuList, "cursor")
    end)

    RaidGroupsFrame.sendMsgBtn = CreateButton("RAIDGROUPSFRAMESENDMSGBTN", RaidGroupsFrame, "发送", "LEFT", shortMsgBtn, "RIGHT", 5, 0, 50, 22, 14, true, 0)
    local sendMsgBtn = RaidGroupsFrame.sendMsgBtn
    sendMsgBtn:RegisterForClicks("LeftButtonUp", "RightButtonUp")
    sendMsgBtn:SetScript("OnClick", function (self, button)
        if button == "LeftButton" then
            self:Disable()
            local count = 10
            self:SetText("发送" .. count)
            C_Timer.NewTicker(1, function ()
                count = count - 1
                self:SetText("发送" .. count)
                if count == 0 then
                    self:Enable()
                    self:SetText("发送")
                end
            end, 10)
            msgContentEditBox:ClearFocus()
            local msg = msgContentEditBox:GetText() or ""
            if ZL.opt.aiRolesCheckBtn then
                msg = msg .. (aiMsgContentEditBox:GetText() or "")
            end
            msg = msg:gsub("，", ", ")
            if #msg == 0 then return end
            -- SendChatMessage(msg, "PARTY")
            SendChatMessage(msg, "CHANNEL", nil, 6)
            local channelID
            if ZL.opt.msgChannelTeam then
                channelID = GetChannelName("寻求组队")
                if channelID then
                    SendChatMessage(msg, "CHANNEL", nil, channelID)
                end
            end
            if ZL.opt.msgChannelWorld then
                channelID = GetChannelName("大脚世界频道")
                if channelID then
                    SendChatMessage(msg, "CHANNEL", nil, channelID)
                end
            end
            if ZL.opt.msgChannelYell then
                SendChatMessage(msg, "YELL")
            end
            if ZL.opt.msgChannelSay then
                SendChatMessage(msg, "SAY")
            end
        elseif button == "RightButton" then

        end
    end)
    sendMsgBtn:SetScript("OnEnter", function (self)
        GameTooltipShow(self, "BOTTOM", "TOP")
        GameTooltip:AddLine("提示")
        GameTooltip:AddLine("消息内容总字符数不能超过250字节", 1, 1, 1)
        GameTooltip:AddLine("1个中文字符=3字节，尽量使用英文字符")
        GameTooltip:Show()
    end)
    sendMsgBtn:SetScript("OnLeave", function ()
        GameTooltip:Hide()
    end)

    RaidGroupsFrame.sendMsgSettingBtn = CreateButton(nil, RaidGroupsFrame, "设置 |T130940:14|t", "LEFT", sendMsgBtn, "RIGHT", 5, 0, 70, 22, 14, true, 0)
    local sendMsgSettingBtn = RaidGroupsFrame.sendMsgSettingBtn
    sendMsgSettingBtn:RegisterForClicks("LeftButtonUp", "RightButtonUp")
    sendMsgSettingBtn:SetScript("OnClick", function (self)
        local minutes = {}
        for i = 1, 10 do
            tinsert(minutes, {
                text = i,
                checkable = 1,
                checked = i == ZL.opt.whisperLastMinute,
                func = function ()
                    ZL.opt.whisperLastMinute = i
                    ZL.GUI:CloseMenu()
                    ZL.RaidGroupsFrame.whisperFrame:Update()
                end
            })
        end
        local whisperMessageNumbers = {}
        for i = 10, 30 do
            tinsert(whisperMessageNumbers, {
                text = i,
                checkable = 1,
                checked = i == ZL.opt.whisperMessageNumbers,
                func = function ()
                    ZL.opt.whisperMessageNumbers = i
                    ZL.GUI:CloseMenu()
                end
            })
        end
        local menuList = {
            {
                text = "发送频道",
                hasArrow = 1,
                menuTable = {
                    {
                        text = "寻求组队",
                        checkable = 1,
                        isNotRadio = 1,
                        keepShownOnClick = 1,
                        checked = ZL.opt.msgChannelTeam,
                        func = function (_, data)
                            ZL.opt.msgChannelTeam = data.checked
                        end
                    },
                    {
                        text = "大脚世界频道",
                        checkable = 1,
                        isNotRadio = 1,
                        keepShownOnClick = 1,
                        checked = ZL.opt.msgChannelWorld,
                        func = function (_, data)
                            ZL.opt.msgChannelWorld = data.checked
                        end
                    },
                    {
                        text = "说",
                        checkable = 1,
                        isNotRadio = 1,
                        keepShownOnClick = 1,
                        checked = ZL.opt.msgChannelSay,
                        func = function (_, data)
                            ZL.opt.msgChannelSay = data.checked
                        end
                    },
                    {
                        text = "喊",
                        checkable = 1,
                        isNotRadio = 1,
                        keepShownOnClick = 1,
                        checked = ZL.opt.msgChannelYell,
                        func = function (_, data)
                            ZL.opt.msgChannelYell = data.checked
                        end
                    },
                },
            },
            -- {
            --     text = "屏蔽|CFFFFDE00消息受限|r",
            --     checkable = 1,
            --     isNotRadio = 1,
            --     keepShownOnClick = 1,
            --     checked = ZL.opt.filterThrottledMsg,
            --     func = function (_, data)
            --         ZL.opt.filterThrottledMsg = data.checked
            --         if ZL.opt.filterThrottledMsg then
            --             ChatFrame_AddMessageEventFilter("CHAT_MSG_CHANNEL_NOTICE", filterFunc)
            --         else
            --             ChatFrame_RemoveMessageEventFilter("CHAT_MSG_CHANNEL_NOTICE", filterFunc)
            --         end
            --     end
            -- },
            {
                text = "同步到集结号",
                checkable = 1,
                isNotRadio = 1,
                keepShownOnClick = 1,
                checked = ZL.opt.syncToMeetingHorn,
                func = function (_, data)
                    ZL.opt.syncToMeetingHorn = data.checked
                end
            },
            {isSeparator=1},
            {
                text = "密语玩家数",
                tooltipText = "展示最近" .. ZL.opt.whisperLastMinute .. "分钟内有密语记录的玩家",
                hasArrow = 1,
                menuTable = minutes,
            },
            {
                text = "密语条数",
                tooltipText = "展示最近" .. ZL.opt.whisperMessageNumbers .. "条密语记录",
                hasArrow = 1,
                menuTable = whisperMessageNumbers,
            },
            {
                text = "自动邀请",
                checkable = 1,
                isNotRadio = 1,
                keepShownOnClick = 1,
                checked = ZL.opt.autoInvite,
                func = function (_, data)
                    ZL.opt.autoInvite = data.checked
                end
            },
            {
                text = "自动调整队伍",
                checkable = 1,
                isNotRadio = 1,
                keepShownOnClick = 1,
                checked = ZL.opt.autoChangeGroup,
                func = function (_, data)
                    ZL.opt.autoChangeGroup = data.checked
                end
            },
        }
        ZL.GUI:ToggleMenu(self, menuList, "cursor")
        minutes, whisperMessageNumbers, menuList = nil, nil, nil
    end)

    RaidGroupsFrame.aiRolesCheckBtn = CreateFrame("CheckButton", nil, RaidGroupsFrame, "ChatConfigCheckButtonTemplate")
    local aiRolesCheckBtn = RaidGroupsFrame.aiRolesCheckBtn
    aiRolesCheckBtn:SetPoint("LEFT", sendMsgSettingBtn, "RIGHT", 5, 0)
    aiRolesCheckBtn:SetSize(20, 20)
    aiRolesCheckBtn.Text:SetText("AI职能")
    aiRolesCheckBtn.Text:ClearAllPoints()
    aiRolesCheckBtn.Text:SetPoint("LEFT", aiRolesCheckBtn , "RIGHT", -3, 0)
    aiRolesCheckBtn:SetHitRectInsets(0, -aiRolesCheckBtn.Text:GetWidth(), 0, 0)
    aiRolesCheckBtn:SetChecked(ZL.opt.aiRolesCheckBtn)
    aiRolesCheckBtn:SetScript("OnEnter", function (self)
        GameTooltipShow(self, "BOTTOM", "TOP")
        GameTooltip:AddLine("在自定义内容后面自动\n添加AI职能话术")
        GameTooltip:Show()
    end)
    aiRolesCheckBtn:SetScript("OnLeave", function (self)
        GameTooltip:Hide()
    end)
    aiRolesCheckBtn:SetScript("OnClick", function (self)
        ZL.opt.aiRolesCheckBtn = self:GetChecked()
        msgContentFontStringUpdate()
    end)

    RaidGroupsFrame.itemLevelCheckBtn = CreateFrame("CheckButton", nil, RaidGroupsFrame, "ChatConfigCheckButtonTemplate")
    local itemLevelCheckBtn = RaidGroupsFrame.itemLevelCheckBtn
    itemLevelCheckBtn:SetPoint("LEFT", aiRolesCheckBtn, "RIGHT", 5+aiRolesCheckBtn.Text:GetWidth(), 0)
    itemLevelCheckBtn:SetSize(20, 20)
    itemLevelCheckBtn.Text:SetText("装等")
    itemLevelCheckBtn.Text:ClearAllPoints()
    itemLevelCheckBtn.Text:SetPoint("LEFT", itemLevelCheckBtn , "RIGHT", -3, 0)
    itemLevelCheckBtn:SetHitRectInsets(0, -itemLevelCheckBtn.Text:GetWidth(), 0, 0)
    itemLevelCheckBtn:SetChecked(ZL.opt.checkItemLevel)
    itemLevelCheckBtn:SetScript("OnClick", function (self)
        ZL.opt.checkItemLevel = self:GetChecked()
        aiMsgContentUpdate()
    end)
    itemLevelCheckBtn:SetScript("OnEnter", function (self)
        GameTooltipShow(self, "BOTTOM", "TOP")
        GameTooltip:AddLine("提示")
        GameTooltip:AddLine(" ")
        GameTooltip:AddLine("装等检测有10-60秒左右时间延迟", 1, 1, 1)
        GameTooltip:Show()
    end)
    itemLevelCheckBtn:SetScript("OnLeave", function (self)
        GameTooltip:Hide()
    end)
    itemLevelCheckBtn.itemLevelEditBox = CreateEditBox(itemLevelCheckBtn, 50, 22, 14, "RIGHT", true)
    local itemLevelEditBox = itemLevelCheckBtn.itemLevelEditBox
    itemLevelEditBox:SetPoint("LEFT", itemLevelCheckBtn, "RIGHT", itemLevelCheckBtn.Text:GetWidth(), 0)
    itemLevelEditBox:SetText(ZL.opt.MinItemLevel or 0)
    itemLevelEditBox:SetScript("OnTextChanged", function (self)
        ZL.opt.MinItemLevel = itemLevelEditBox:GetNumber()
    end)
    itemLevelEditBox:SetScript("OnMouseWheel", function (self, delta)
        if self:HasFocus() then
            local number = self:GetNumber()
            if delta > 0 then
                number = number + 1
            else
                number = number - 1
            end
            if number < 1 then
                number = 1
            end
            self:SetNumber(number)
        end
    end)
    local whisperHeight = 24
    local nameWidth, activeWidth, secondWidth, itmeLevelWidth, msgTalentWidth, inviteWidth = 140, 90, 90, 60, 90, 60
    local contentWidth = nameWidth + activeWidth + secondWidth + itmeLevelWidth + msgTalentWidth + inviteWidth
    RaidGroupsFrame.whisperFrame = CreateFrame("Button", nil, RaidGroupsFrame, BackdropTemplateMixin and "BackdropTemplate")
    local whisperFrame = RaidGroupsFrame.whisperFrame
    whisperFrame:SetPoint("TOPLEFT", msgContentFontString, "BOTTOMLEFT", 0, -10)
    whisperFrame:SetSize(contentWidth + 30, 235)
    whisperFrame:SetAlpha(1)
    whisperFrame:SetBackdrop({
        bgFile = "Interface\\CharacterFrame\\UI-Party-Background",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 32, edgeSize = 6,
        insets = { left = 1, right = 1, top = 1, bottom = 1 }
    })
    whisperFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b)
    whisperFrame:SetBackdropColor(0.1, 0.1, 0.1, 0.2)
    local nameBtn = titleBtn(whisperFrame, "玩家名", "TOPLEFT", whisperFrame, "TOPLEFT", 5, -5, nameWidth, whisperHeight)
    local activeBtn = titleBtn(whisperFrame, "当前天赋", "LEFT", nameBtn, "RIGHT", 0, 0, activeWidth, whisperHeight)
    local secondBtn = titleBtn(whisperFrame, "第二天赋", "LEFT", activeBtn, "RIGHT", 0, 0, secondWidth, whisperHeight)
    local itmeLevelBtn = titleBtn(whisperFrame, "装等", "LEFT", secondBtn, "RIGHT", 0, 0, itmeLevelWidth, whisperHeight)
    local msgTalentBtn = titleBtn(whisperFrame, "申请职位", "LEFT", itmeLevelBtn, "RIGHT", 0, 0, msgTalentWidth, whisperHeight)
    local inviteBtn = titleBtn(whisperFrame, "操作", "LEFT", msgTalentBtn, "RIGHT", 0, 0, inviteWidth, whisperHeight)
    --创建滚动条
    whisperFrame.whisperScrollFrame = CreateFrame("ScrollFrame", nil, whisperFrame, "UIPanelScrollFrameTemplate")
    local whisperScrollFrame = whisperFrame.whisperScrollFrame
    whisperScrollFrame:SetFrameLevel(whisperFrame:GetFrameLevel() + 1) -- 设置为比父框架高1级
    whisperScrollFrame:SetPoint("TOPLEFT", nameBtn, "BOTTOMLEFT", 0, 0)
    whisperScrollFrame:SetPoint("BOTTOMRIGHT", whisperFrame, "BOTTOMRIGHT", -2, 3)
    whisperScrollFrame:SetClipsChildren(true) --必须设置为true，scrollFrame所有的子元素才会被剪切
    whisperScrollFrame:SetScript("OnMouseWheel", ZL.ScrollFrame_OnMouseWheel) --重设滑动条鼠标滚轮事件
    --重设ScrollBar位置，放置到scrollFrame内，防止被剪切掉
    whisperScrollFrame.ScrollBar:ClearAllPoints()
    whisperScrollFrame.ScrollBar:SetPoint("TOPLEFT", whisperScrollFrame, "TOPRIGHT", -20, -16)
    whisperScrollFrame.ScrollBar:SetPoint("BOTTOMRIGHT", whisperScrollFrame, "BOTTOMRIGHT", 0, 16)
    whisperScrollFrame.content = CreateFrame("Frame", nil, whisperScrollFrame)
    local whisperContent = whisperScrollFrame.content
    whisperContent:SetPoint("TOPLEFT", whisperScrollFrame, "TOPLEFT", 0, 0)
    whisperContent:SetSize(180, 100)
    whisperScrollFrame:SetScrollChild(whisperContent)
    -- whisperScrollFrame.ScrollBar:SetFrameLevel(whisperContent:GetFrameLevel()+100)
    local function CreateWhisperFontString(parent, width, relativeto, relativePoint)
        local s = CreatFrontString(nil, nil, 14, nil, "LEFT", parent)
        s:SetTextColor(0.95, 0.95, 0.95)
        s:SetPoint("LEFT", relativeto, relativePoint)
        s:SetSize(width, whisperHeight)
        return s
    end
    whisperFrame.entries = setmetatable({}, {
        __index = function (t, v)
            local f = CreateFrame("Button", nil, whisperContent)
            f:Hide()
            f:SetHighlightTexture([[Interface\QuestFrame\UI-QuestLogTitleHighlight]])
            f:GetHighlightTexture():SetAlpha(0.3)
            f:SetPoint("TOPLEFT", whisperContent, "TOPLEFT", 0, -(v-1)*whisperHeight)
            f:SetSize(contentWidth-inviteWidth, whisperHeight)
            f:RegisterForClicks("LeftButtonUp", "RightButtonUp")
            f:SetScript("OnClick", function (self, button)
                if button == "RightButton" then
                    ZL.GUI:ToggleMenu(self, whisperDropdownMenu(self), "cursor")
                end
            end)
            f:SetScript("OnEnter", function (self)
                local name = f.name
                GameTooltipShow(whisperFrame, "TOPLEFT", "TOPRIGHT")
                GameTooltip:AddLine(name)
                for i, data in ipairs(ZL_PLAYERLIST.whisperList[name].whisperMsgList) do
                    if i <= ZL.opt.whisperMessageNumbers then
                        GameTooltip:AddLine("|cffFF8F00" .. date("%H:%M:%S", data[1]) .. "|r：|cffFF90FF" .. data[2] .. "|r", nil, nil, nil, true)
                    end
                end
                GameTooltip:Show()
            end)
            f:SetScript("OnLeave", function (self)
                GameTooltip:Hide()
            end)
            f.nameString = CreateWhisperFontString(f, nameWidth, f, "LEFT")
            f.activeString = CreateWhisperFontString(f, activeWidth, f.nameString, "RIGHT")
            f.secondString = CreateWhisperFontString(f, secondWidth, f.activeString, "RIGHT")
            f.itmeLevelString = CreateWhisperFontString(f, itmeLevelWidth, f.secondString, "RIGHT")
            f.itmeLevelString:SetJustifyH("CENTER")
            f.msgTalentString = CreateWhisperFontString(f, msgTalentWidth, f.itmeLevelString, "RIGHT")
            f.inviteBtn = CreateButton(nil, f, "邀请", "LEFT", f.msgTalentString, "RIGHT", 0, 0, inviteWidth, whisperHeight-4, 13, true, 0)
            f.inviteBtn:SetScript("OnClick", function ()
                InviteUnit(f.name)
            end)

            t[v] = f
            return f
        end
    })
    function whisperFrame:Update()
        for _, f in ipairs(whisperFrame.entries) do f:Hide() end
        local whisperList = ZL_PLAYERLIST.whisperList
        if whisperList and next(whisperList) then
            local nameList = {}
            local lastTime
            for name, data in pairs(whisperList) do
                lastTime = whisperList[name].lastTime
                if not (UnitInRaid(name) or UnitInParty(name)) and (time() - lastTime <= ZL.opt.whisperLastMinute*60) then --在团队或队伍中的不显示  --ZL.opt.whisperLastMinute*60
                    tinsert(nameList, {name, data.classID, data.activeTalent, data.itmeLevel})
                end
            end
            lastTime = nil
            table.sort(nameList, function (a, b)
                if a[2] < b[2] then
                    return true
                elseif a[2] > b[2] then
                    return false
                else
                    if a[3] and b[3] then
                        if a[3] < b[3] then
                            return true
                        elseif a[3] > b[3] then
                            return false
                        else
                            if a[4] and b[4] then
                                if a[4] > b[4] then
                                    return true
                                elseif a[4] < b[4] then
                                    return false
                                end
                            end
                        end
                    else
                        if a[4] and b[4] then
                            if a[4] > b[4] then
                                return true
                            elseif a[4] < b[4] then
                                return false
                            end
                        end
                    end
                end
                return a[1] < b[1]
            end)
            local f, name, classID, classColor, activeTalent, secondTalent, itemLevel, msgTalent, msgTalent2
            for i, data in ipairs(nameList) do
                name = data[1]
                f = whisperFrame.entries[i]
                classID = whisperList[name].classID
                classColor = whisperList[name].classColor
                activeTalent = whisperList[name].activeTalent
                secondTalent = whisperList[name].secondTalent
                itemLevel= whisperList[name].itemLevel or (whisperList[name].msgItemLevel and "*" .. whisperList[name].msgItemLevel)
                msgTalent = whisperList[name].msgTalent
                msgTalent2 = msgTalent and ZL.talentOtherName[classID][msgTalent][1]
                f.name = name
                f.nameString:SetText("|T" .. talentIcon[classID][classID] .. ":13:13|t " .. getColorString(classColor, name))
                f.activeString:SetText(activeTalent and "|T" .. talentIcon[classID][activeTalent] .. ":13:13|t " .. getColorString(classColor, activeTalent) or "")
                f.secondString:SetText(secondTalent and "|T" .. talentIcon[classID][secondTalent] .. ":13:13|t " .. getColorString(classColor, secondTalent) or "")
                f.itmeLevelString:SetText(itemLevel and getColorString(classColor, itemLevel) or "")
                f.msgTalentString:SetText(msgTalent and "|T" .. talentIcon[classID][msgTalent] .. ":13:13|t " .. getColorString(classColor, msgTalent2) or "")
                f:Show()
            end
            f, name, classID, classColor, activeTalent, secondTalent, itemLevel, msgTalent, msgTalent2 = nil, nil, nil, nil, nil, nil, nil, nil, nil
        end
    end

    function RaidGroupsFrame:Update()
        local edit
        ZL_PLAYERLIST.RaidGroupsData = ZL_PLAYERLIST.RaidGroupsData or {}
        local RaidGroupsData = ZL_PLAYERLIST.RaidGroupsData
        for i = 1, 40 do
            edit = RaidGroupsFrame.edits[i]
            edit.nameString:SetText("")
            edit.name = nil
            if RaidGroupsData and RaidGroupsData[i] then
                local talent = RaidGroupsData[i].talent
                local classColor = RaidGroupsData[i].classColor
                local classID = RaidGroupsData[i].classID
                if classID == 0 then
                    edit:SetText(talentIcon[classID][talent] .. "|c" .. classColor .. talentOtherName[classID][talent][1] .. "|r")
                else
                    edit:SetText("|T" .. talentIcon[classID][talent] .. ":12:12:-2|t|c" .. classColor .. talentOtherName[classID][talent][1] .. "|r")
                end
            else
                edit:SetText("")
            end
        end
        local unknowTalent = {}
        local noHavePosition = {}
        for i = 1, MAX_RAID_MEMBERS do
            local name, _, _, _, _, fileName = GetRaidRosterInfo(i)
            if name then
                local colorName = GetClassColorName(name, fileName)
                local classID = select(3, UnitClass(name))
                local playerTalent, talentSorce = getPlayerTalent(name)
                if playerTalent then
                    local isExist
                    --1、根据天赋匹配
                    for j = 1, 40 do
                        edit = RaidGroupsFrame.edits[j]
                        local data = RaidGroupsData[j]
                        if #(edit.name or "") == 0 and data and data.classID == classID and playerTalent == data.talent then
                            edit.name = name
                            edit.nameString:SetText(talentSorce == 1 and ("*" .. colorName) or colorName)
                            isExist = true
                            break
                        end
                    end
                    --2、根据职业和职责匹配
                    if not isExist and type(playerTalent) == "string" then
                        local playerRole = ZL.talentRole[playerTalent][1]
                        for j = 1, 40 do
                            edit = RaidGroupsFrame.edits[j]
                            local data = RaidGroupsData[j]
                            if #(edit.name or "") == 0 and data and ((data.classID == classID and data.classID == data.talent and tIndexOf(talentInfo[classID], playerTalent))
                            or (data.classID == 0 and data.talent == playerRole)) then
                                edit.name = name
                                local text = "|T" .. talentIcon[classID][playerTalent] .. ":12:12:-2|t" .. colorName
                                edit.nameString:SetText(talentSorce == 1 and ("*" .. text) or text)
                                isExist = true
                                break
                            end
                        end
                    end
                    if not isExist then
                        noHavePosition[name] = {
                            classID = classID,
                            classColor = select(4, GetClassColor(fileName)),
                            talent = playerTalent,
                            talentSorce = talentSorce,
                            name = name,
                        }
                    end
                else
                    --未获取到天赋情况下根据职业判断
                    local isExist
                    for j = 1, 40 do
                        edit = RaidGroupsFrame.edits[j]
                        local data = RaidGroupsData[j]
                        if data and data.classID == classID and data.classID == data.talent and #(edit.name or "") == 0 then
                            edit.name = name
                            edit.nameString:SetText("?" .. colorName)
                            isExist = true
                            break
                        end
                    end
                    if not isExist then
                        unknowTalent[name] = {
                            classID = classID,
                            classColor = select(4, GetClassColor(fileName)),
                            name = name,
                        }
                    end
                end
            end
        end
        unknowTalentScrollFrame:Update(unknowTalent)
        noHavePositionScrollFrame:Update(noHavePosition)
        aiMsgContentUpdate()
        whisperFrame:Update()
        if ZL.opt.autoChangeGroup then
            applyToRaid()
        end
    end
    local eventList = {
        "CHAT_MSG_SYSTEM", "CHAT_MSG_WHISPER", "GROUP_FORMED", "GROUP_LEFT",
        --"LOADING_SCREEN_ENABLED"
    }
    for _, event in ipairs(eventList) do
        RaidGroupsFrame:RegisterEvent(event)
    end
    RaidGroupsFrame:SetScript("OnEvent", function (self, event, ...)
        local arg = ZL.emptytable(...)
        if RaidGroupsFrame:IsShown() and ((event == "CHAT_MSG_SYSTEM" and isInMsgSystemList(arg[1])) or
        event == "GROUP_FORMED" or event == "GROUP_LEFT") then
            C_Timer.After(1, function ()
                RaidGroupsFrame:Update()
            end)
        elseif event == "CHAT_MSG_WHISPER" then
            if not (UnitInRaid("player") or UnitInParty("player")) or ((UnitInRaid("player", 1) or UnitInParty("player", 1))
            and (UnitIsGroupLeader("player", 1) or UnitIsGroupAssistant("player"))) then
                local name=  ZL.pruneCrossRealm(arg[2])
                if not (UnitInRaid(name) or UnitInParty(name)) then
                    local co = coroutine.create(inspectfunc)
                    coroutine.resume(co, arg[1], name, arg[12])
                end
            end
        -- elseif event == "LOADING_SCREEN_ENABLED" then
            -- LeaveChannelByName("测试")
        end
        arg:Release()
    end)

    RaidGroupsFrame:Update()
    profileFrameScrollFrame:Update()
    whisperFrame:Update()

    do
        local aName = "MeetingHorn"
        local name = GetAddOnInfo(aName)
        if name then
            if IsAddOnLoaded(aName) then
                hookfunc(aName)
            else
                RaidGroupsFrame:RegisterEvent("ADDON_LOADED")
                RaidGroupsFrame:SetScript("OnEvent", function(self, event, _name)
                    if event == "ADDON_LOADED" and _name == aName then
                        RaidGroupsFrame:UnregisterEvent("ADDON_LOADED")
                        hookfunc(aName)
                    end
                end)
            end
        end
    end
end

-- local function HookSetupMenu(_, root)
--     local name = root.contextData and (root.contextData.chatTarget or root.contextData.name)
--     if name then
--         root:CreateDivider()
--         root:CreateTitle('aaaa')
--         root:CreateButton(INSPECT .. "11", function()
--             print(11111)
--         end)
--     end
-- end

-- Menu.ModifyMenu('MENU_UNIT_FRIEND', HookSetupMenu)
-- Menu.ModifyMenu('MENU_UNIT_RAID', HookSetupMenu)
-- Menu.ModifyMenu('MENU_UNIT_COMMUNITIES_GUILD_MEMBER', HookSetupMenu)