local function createButton(icon_on, icon_off, help, getf, setf, ...)
    local button = CreateFrame("BUTTON", nil, CharacterModelFrame)
    
    -- setup
    local hilite = button:CreateTexture(nil, "HIGHLIGHT")
    hilite:SetAllPoints()
    hilite:SetTexture("Interface\\Common\\UI-ModelControlPanel")
    hilite:SetTexCoord(0.57812500, 0.82812500, 0.00781250, 0.13281250)
    
    button:SetWidth(32)
    button:SetHeight(32)
    button:SetPoint(...)
    button:Hide()

    -- update
    local function update()
        if getf() then
            button:SetNormalTexture(icon_on)
        else
            button:SetNormalTexture(icon_off)
        end
    end
    
    button:RegisterEvent("PLAYER_FLAGS_CHANGED")
    button:RegisterEvent("PLAYER_ENTERING_WORLD")
    button:SetScript("OnEvent", update)

    -- click
    button:SetScript("OnClick", function()
        setf(not getf())
        update()
    end)

    -- hover
    button:SetScript("OnEnter", function()
        button:SetAlpha(1)
        GameTooltip:SetOwner(button, "ANCHOR_TOPRIGHT")
        GameTooltip:SetText(help, nil, nil, nil, nil, 1)
    end)
    button:SetScript("OnLeave", function()
        button:SetAlpha(0.5)
        GameTooltip_Hide()
    end)
    button:SetAlpha(0.5)

    CharacterModelFrame:HookScript("OnEnter", function()
        button:Show()
    end)
    CharacterModelFrame:HookScript("OnLeave", function(self)
        if not self:IsMouseOver() then
            button:Hide()
        else
            -- XXX fix control buttons
            self.controlFrame:Show()
        end
    end)
    
    update()
end

createButton(
    "Interface\\AddOns\\CloakHelmToggle\\HelmShow",
    "Interface\\AddOns\\CloakHelmToggle\\HelmHide",
    SHOW_HELM,
    function() return ShowingHelm() end,
    function(value) ShowHelm(value) end,
    "BOTTOMLEFT", 5, 5
)

createButton(
    "Interface\\AddOns\\CloakHelmToggle\\CloakShow",
    "Interface\\AddOns\\CloakHelmToggle\\CloakHide",
    SHOW_CLOAK,
    function() return ShowingCloak() end,
    function(value) ShowCloak(value) end,
    "BOTTOMRIGHT", -5, 5
)
