local AceGUI = LibStub("AceGUI-3.0")
local Media = LibStub("LibSharedMedia-3.0")

do
    local fixlevels = AceGUISharedMediaWidgets.fixlevels
    local OnItemValueChanged = AceGUISharedMediaWidgets.OnItemValueChanged

    do
        local widgetType = "LSM30_Font_Item_Select"
        local widgetVersion = 1

        local function Frame_OnEnter(this)
            local self = this.obj
            if self.useHighlight then
                self.highlight:Show()
            end
            self:Fire("OnEnter")
        end

        local function Frame_OnLeave(this)
            local self = this.obj
            self.highlight:Hide()
            self:Fire("OnLeave")
        end

        local function OnAcquire(self)
            self.frame:SetToplevel(true)
            self.frame:SetFrameStrata("FULLSCREEN_DIALOG")
        end

        local function OnRelease(self)
            self.pullout = nil
            self.frame:SetParent(nil)
            self.frame:ClearAllPoints()
            self.frame:Hide()
        end

        local function SetPullout(self, pullout)
            self.pullout = pullout
            self.frame:SetParent(pullout.itemFrame)
            self.parent = pullout.itemFrame
            fixlevels(pullout.itemFrame, pullout.itemFrame:GetChildren())
        end

        local function SetText(self, text, fontPath)
            self.font = text or ""
            self.text:SetText(text or "")
            self.text:SetFont(fontPath or STANDARD_TEXT_FONT, 14, "")
        end

        local function GetText(self)
            return self.text:GetText()
        end

        local function SetPoint(self, ...)
            self.frame:SetPoint(...)
        end

        local function Show(self)
            self.frame:Show()
        end

        local function Hide(self)
            self.frame:Hide()
        end

        local function SetDisabled(self, disabled)
            self.disabled = disabled
            self.useHighlight = not disabled
            if disabled then
                self.text:SetTextColor(0.5, 0.5, 0.5)
            else
                self.text:SetTextColor(1, 1, 1)
            end
        end

        local function UpdateToggle(self)
            if self.value then
                self.check:Show()
            else
                self.check:Hide()
            end
        end

        local function Frame_OnClick(this)
            local self = this.obj
            self.value = not self.value
            UpdateToggle(self)
            self:Fire("OnValueChanged", self.value)
        end

        local function SetValue(self, value)
            self.value = value
            UpdateToggle(self)
        end

        local function Constructor()
            local count = AceGUI:GetNextWidgetNum(widgetType)
            local frame = CreateFrame("Frame", "LSM30_Font_DropDownItem" .. count)
            local self = {}
            self.frame = frame
            frame.obj = self
            self.type = widgetType
            self.useHighlight = true

            frame:SetHeight(18)
            frame:SetFrameStrata("FULLSCREEN_DIALOG")

            local button = CreateFrame("Button", nil, frame)
            button:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", 0, 0)
            button:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, 0)
            button.obj = self
            self.button = button

            local text = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
            text:SetJustifyH("LEFT")
            text:SetPoint("TOPLEFT", frame, "TOPLEFT", 18, 0)
            text:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -4, 0)
            self.text = text

            local highlight = button:CreateTexture(nil, "OVERLAY")
            highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
            highlight:SetBlendMode("ADD")
            highlight:SetHeight(14)
            highlight:SetPoint("LEFT", frame, "LEFT", 5, 0)
            highlight:SetPoint("RIGHT", frame, "RIGHT", -2, 0)
            highlight:Hide()
            self.highlight = highlight

            local check = frame:CreateTexture("OVERLAY")
            check:SetSize(16, 16)
            check:SetPoint("LEFT", frame, "LEFT", 3, -1)
            check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
            check:Hide()
            self.check = check

            button:SetScript("OnEnter", Frame_OnEnter)
            button:SetScript("OnLeave", Frame_OnLeave)
            button:SetScript("OnClick", Frame_OnClick)

            self.OnAcquire = OnAcquire
            self.OnRelease = OnRelease
            self.SetPullout = SetPullout
            self.GetText = GetText
            self.SetText = SetText
            self.SetDisabled = SetDisabled
            self.SetPoint = SetPoint
            self.Show = Show
            self.Hide = Hide
            self.SetValue = SetValue

            AceGUI:RegisterAsWidget(self)
            return self
        end

        AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion)
    end

    do
        local widgetType = "LSM30_Font"
        local widgetVersion = 1
        local sortlist = {}

        local function AddListItem(self, value, text)
            local item = AceGUI:Create("LSM30_Font_Item_Select")
            item:SetText(text, Media:Fetch("font", value, true))
            item.userdata.obj = self
            item.userdata.value = value
            item:SetCallback("OnValueChanged", OnItemValueChanged)
            self.pullout:AddItem(item)
        end

        local function SetList(self, list)
            self.list = list or Media:HashTable("font")
            self.pullout:Clear()
        end

        local function ParseListItems(self)
            for value in pairs(self.list) do
                sortlist[#sortlist + 1] = value
            end
            table.sort(sortlist)
            for index, value in ipairs(sortlist) do
                AddListItem(self, value, value)
                sortlist[index] = nil
            end
        end

        local function SetText(self, text)
            self.text:SetText(text or "")
            local fontPath = text and Media:Fetch("font", text, true)
            self.text:SetFont(fontPath or STANDARD_TEXT_FONT, 14, "")
        end

        local function Constructor()
            local self = AceGUI:Create("Dropdown")
            self.type = widgetType
            self.SetList = SetList
            self.SetValue = AceGUISharedMediaWidgets.SetValue
            self.SetText = SetText

            local clickscript = self.button:GetScript("OnClick")
            self.button:SetScript("OnClick", function(...)
                self.pullout:Clear()
                ParseListItems(self)
                clickscript(...)
            end)

            return self
        end

        AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion)
    end
end
