local _AddonName, _EchoRaidTools = ...;


local module = _EchoRaidTools:GetModule("todo-list")
module.config = module.config or {}
local config = module.config
local editor, mainConfigFrame, anchorConfigFrame;
local temporaryDisplayInfo
local editedFields

local function getTextures()
    local texturesTable = {}
    for i, textureName in ipairs(module.lsm:GetStatusbars()) do
        table.insert(texturesTable,
            { label = textureName, value = textureName, statusbar = module.lsm:GetStatusbarPath(textureName) })
    end
    return texturesTable
end

local function getFonts()
    local fontsTable = {}
    for i, fontName in ipairs(module.lsm:GetFonts()) do
        table.insert(fontsTable, { label = fontName, value = fontName, font = module.lsm:GetFontPath(fontName) })
    end
    return fontsTable
end


local function registerFieldEdit(fieldTable)
    local key = ""

    for i, field in ipairs(fieldTable) do
        key = key .. field
    end

    editedFields[key] = fieldTable
end

local function setTemporaryAnchorSettings()
    module.display:updateDisplaySettings(temporaryDisplayInfo)
end


local function setAnchorField(fieldTable, value)
    if module:SetField(temporaryDisplayInfo, fieldTable, value) then
        registerFieldEdit(fieldTable)
        setTemporaryAnchorSettings()
    end
end




local function onDragFunc(displayFrame)
    local point, relativeTo, relativePoint, offsetX, offsetY = displayFrame:GetPoint()
    --only the offset we care about here (I'm pretty sure)

    setAnchorField({ "anchors", "offsetX" }, offsetX)
    setAnchorField({ "anchors", "offsetY" }, offsetY)

    anchorConfigFrame.sliderX:UpdateValues()
    anchorConfigFrame.sliderY:UpdateValues()
end


local function shouldCustomAnchorFieldBeVisible()
    local validDropdownOptions = { "WorldMapFrame", "UIParent" }
    local anchorString = module:GetField(temporaryDisplayInfo, { "anchors", "frame" })
    if anchorString and tContains(validDropdownOptions, anchorString) then
        anchorConfigFrame.parentFrameDropdown:UpdateSelection(anchorString)
        anchorConfigFrame.customFrameInput:Hide()
    else
        anchorConfigFrame.parentFrameDropdown:UpdateSelection("")
        anchorConfigFrame.customFrameInput:Show()
        anchorConfigFrame.customFrameInput.Editbox:SetText(anchorString or "")
    end
end

local function openAnchorConfig()
    mainConfigFrame:Hide()
    anchorConfigFrame:Show()
    temporaryDisplayInfo = module:GetDisplayInfo()
    module.display:updateDisplaySettings(temporaryDisplayInfo)
    module.display:EnableDrag(onDragFunc)
    editedFields = {}
    anchorConfigFrame.anchorDropdown:UpdateSelection(module:GetField(temporaryDisplayInfo, { "anchors", "sourcePoint" }))
    anchorConfigFrame.relativeAnchorDropdown:UpdateSelection(module:GetField(temporaryDisplayInfo,
        { "anchors", "destPoint" }))
    shouldCustomAnchorFieldBeVisible()

    anchorConfigFrame.sliderX:UpdateValues()
    anchorConfigFrame.sliderY:UpdateValues()
    anchorConfigFrame.frameStrataDropdown:UpdateSelection(module:GetField(temporaryDisplayInfo, { "anchors", "strata" }))
end

local function closeAnchorConfig(shouldSave)
    if not editedFields then return end
    if shouldSave then
        for _, fieldTable in pairs(editedFields) do
            local value = module:GetField(temporaryDisplayInfo, fieldTable)
            table.insert(fieldTable, 1, "display")
            module:UpdateSetting(fieldTable, value)
        end
    end
    module.display:updateDisplaySettings()
    temporaryDisplayInfo = nil
    editedFields = nil
    module.display:DisableDrag()
    anchorConfigFrame:Hide()
    mainConfigFrame:Show()
end



local configFields = {
    {
        inputType = "dropdown",
        name = "Bar Texture",
        field = { "display", "barSettings", "texture" },
        dropdownOptions = getTextures,
        dropdownTexture = true
    },
    {
        inputType = "dropdown",
        name = "Font",
        field = { "display", "barSettings", "font" },
        dropdownOptions = getFonts,
        dropdownFont = true,
    },
    {
        inputType = "colorpicker",
        field = { "display", "barSettings", "colour" },
        name = "Bar Colour",
    },
    {
        inputType = "colorpicker",
        field = { "display", "barSettings", "bgColour" },
        name = "Bar Background Colour",
    },
    {
        inputType = "slider",
        name = "Bar Height",
        field = { "display", "barSettings", "height" },
        boundaries = { 1, 200, 1 }
    },
    {
        inputType = "slider",
        name = "Text Font Size",
        field = { "display", "barSettings", "textFontSize" },
        boundaries = { 1, 30, 1 }
    },
    {
        inputType = "colorpicker",
        field = { "display", "barSettings", "textColour" },
        name = "Text Colour",
    },
    {
        inputType = "slider",
        name = "Progress Text Font Size",
        field = { "display", "barSettings", "progressTextFontSize" },
        boundaries = { 1, 30, 1 }
    },
    {
        inputType = "slider",
        name = "Bar Padding",
        field = { "display", "barSettings", "padding" },
        boundaries = { 0, 30, 1 }
    },
    {
        inputType = "slider",
        name = "Bar Width",
        field = { "display", "size", "width" },
        boundaries = { 1, 1000, 1 }
    },
    {
        inputType = "slider",
        name = "Scale",
        field = { "display", "size", "scale" },
        boundaries = { 0.1, 10, 0.1 }
    },
    {
        inputType = "colorpicker",
        field = { "display", "barSettings", "progressTextColour" },
        name = "Progress Text Colour",
    },
    {
        inputType = "colorpicker",
        field = { "display", "bgColour" },
        name = "Window Background Colour",
    },
    {
        inputType = "button",
        name = "Anchor Settings",
        script = openAnchorConfig
    },
    {
        inputType = "dropdown",
        name = "Hide while in combat",
        field = { "loadCondition", "combatType" },
        dropdownOptions = {
            { label = "Never",     value = "never" },
            { label = "Encounter", value = "encounter" },
            { label = "Combat",    value = "combat" },
        },
    },
    {
        inputType = "dropdown",
        name = "Hide while in group",
        field = { "loadCondition", "groupType" },
        dropdownOptions = {
            { label = "Never", value = "never" },
            { label = "Raid",  value = "raid" },
            { label = "Party", value = "party" },
        },
    },
    {
        inputType = "checkbox",
        name = "Hide when completed",
        field = { "display", "hideOnComplete" },
    },
}

function config:GetDisplayConfig(contentPanel)
    if editor then
        return editor
    end
    local window = contentPanel
    mainConfigFrame = CreateFrame("frame", nil, window)
    anchorConfigFrame = CreateFrame("frame", nil, window)
    mainConfigFrame:SetAllPoints()
    anchorConfigFrame:SetAllPoints()
    mainConfigFrame:Show()
    anchorConfigFrame:Hide()
    -- do cool things

    -- bar texture
    -- bar height
    -- bar font
    -- text fontsize
    -- text fontcolor
    -- progressText fontsize
    -- progressText fontcolor
    -- width
    -- anchor frame
    -- position (make drag:able)(should probably be a separate page)
    -- load condition
    -- disable new default mods by default
    --time offset for regions without built in offset


    local columns = 4
    local xSize = 220
    local ySize = 80
    local xOffset = 20
    local yOffset = 30

    window.configUpdateFunctions = {}

    for index, configOptions in ipairs(configFields) do
        local frame, update
        if configOptions.inputType == "dropdown" then
            frame = CreateFrame("Frame", nil, mainConfigFrame, "EchoRaidToolsConfig_Dropdown")
            frame.TopText:SetText(configOptions.name)
            frame.TopText:Show()
            frame:SetWidth(200)

            local static = type(configOptions.dropdownOptions) == "table" and true or false
            local function updateDropDown()
                local items = {
                }

                local dropdownOptions = static and configOptions.dropdownOptions or
                    configOptions.dropdownOptions()
                for _, info in ipairs(dropdownOptions) do
                    table.insert(items,
                        {
                            icon = nil,
                            label = info.label,
                            value = info.value,
                            onclick = function()
                                module:UpdateSetting(configOptions.field, info.value)
                            end,
                            statusbar = info.statusbar,
                            font = info.font,
                        })
                end
                frame:SetupSelections(items)
            end

            if static then
                updateDropDown()
            end


            update = function()
                if static == false then
                    updateDropDown()
                end
                local stateSetting = module:GetSetting(configOptions.field)
                frame:UpdateSelection(stateSetting)
            end
        elseif configOptions.inputType == "button" then
            frame = CreateFrame("FRAME", nil, mainConfigFrame)
            frame:SetSize(200, 30)
            frame:Show()
            frame.child = CreateFrame("FRAME", nil, frame, "EchoRaidToolsConfig_Button")
            frame.child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, -4)
            frame.child.Button:SetText(configOptions.name)
            frame.child.Button:SetScript("OnClick", configOptions.script)
            frame.child:SetSize(200, 30)
            frame.child:Show()
        elseif configOptions.inputType == "colorpicker" then --TODO when messing around with the colorpicker, bars are not sorted properly
            frame = CreateFrame("Button", nil, mainConfigFrame, "EchoRaidToolsConfig_NewColorPicker")
            --colorpicker.tooltip = "The color of the notification."

            frame:SetupInteraction(function(...)
                module:UpdateSetting(configOptions.field, { ... })
            end, 1, 1, 1, 1, nil, nil, true)
            update = function()
                local stateSetting = module:GetSetting(configOptions.field)

                frame:SetRGBA(
                    stateSetting[1],
                    stateSetting[2],
                    stateSetting[3],
                    stateSetting[4])
            end
            frame.TopText:SetText(configOptions.name)
            frame.TopText:Show()
        elseif configOptions.inputType == "slider" then
            frame = CreateFrame("FRAME", nil, mainConfigFrame, "EchoRaidTools_BetterSlider")
            frame:Show()
            frame:SetSize(200, 32)
            frame.TopText:SetText(configOptions.name)
            frame.TopText:Show()
            local boundaries = configOptions.boundaries
            frame:Setup(
                boundaries[1], boundaries[2], boundaries[3],
                function() return module:GetSetting(configOptions.field) end,
                function(value)
                    module:UpdateSetting(configOptions.field, value)
                end, boundaries[1], boundaries[2])
            update = function() frame:UpdateValues() end
        elseif configOptions.inputType == "checkbox" then
            frame = CreateFrame("CheckButton", nil, mainConfigFrame, "EchoRaidToolsConfig_CheckButton")
            frame:SetSize(25, 25)
            frame.CheckButton:SetScript("OnClick", function(self)
                module:UpdateSetting(configOptions.field, self:GetChecked())
            end)

            update = function() frame.CheckButton:SetChecked(module:GetSetting(configOptions.field)) end
            frame.TopText:SetText(configOptions.name)
            frame.TopText:Show()
        else
            print("no frame type", configOptions.inputType)
            frame = CreateFrame("frame", nil, mainConfigFrame)
        end


        table.insert(window.configUpdateFunctions, update)

        local i = index - 1
        local row = math.floor(i / columns)
        local column = i - (row * columns)
        local xPosition = (xSize * column) + xOffset
        local yPosition = (ySize * row) + yOffset


        frame:SetPoint("TOPLEFT", window, "TOPLEFT", xPosition, -yPosition)
    end



    local function updateFields()
        if not window.configUpdateFunctions then return end
        for i, func in ipairs(window.configUpdateFunctions) do
            func()
        end
    end
    window:SetScript("OnShow", updateFields)
    updateFields()





    ---anchorWindow TODO split file

    local acceptButton = CreateFrame("FRAME", nil, anchorConfigFrame, "EchoRaidToolsConfig_Button")
    acceptButton.Button:SetText("Accept")
    acceptButton.Button:SetScript("OnClick", function()
        closeAnchorConfig(true)
    end)
    acceptButton:SetSize(150, 30)
    acceptButton:SetPoint("BOTTOMRIGHT", anchorConfigFrame, "BOTTOMRIGHT", -20, 5)
    acceptButton:Show()
    local cancelButton = CreateFrame("FRAME", nil, anchorConfigFrame, "EchoRaidToolsConfig_Button")
    cancelButton.Button:SetText("Cancel")
    cancelButton.Button:SetScript("OnClick", function()
        closeAnchorConfig(false)
    end)
    cancelButton:SetSize(150, 30)
    cancelButton:SetPoint("RIGHT", acceptButton, "LEFT", -10, 0)
    cancelButton:Show()

    local function generateSetPointDropdownList(sourcePoint)
        local point = sourcePoint and "sourcePoint" or "destPoint"
        local points = {
            ["TOPLEFT"] = "Top Left",
            ["TOP"] = "Top",
            ["TOPRIGHT"] = "Top Right",
            ["LEFT"] = "Left",
            ["CENTER"] = "Center",
            ["RIGHT"] = "Right",
            ["BOTTOMLEFT"] = "Bottom Left",
            ["BOTTOM"] = "Bottom",
            ["BOTTOMRIGHT"] = "Bottom Right",
        }
        local ret = {}
        for value, label in pairs(points) do
            table.insert(ret, {
                icon = nil,
                label = label,
                value = value,
                onclick = function()
                    setAnchorField({ "anchors", point }, value)
                end
            })
        end
        return ret
    end


    local anchorDropdown = CreateFrame("Frame", nil, anchorConfigFrame,
        "EchoRaidToolsConfig_Dropdown")
    anchorDropdown:SetPoint("TOPLEFT", anchorConfigFrame, "TOPLEFT", 30, -30)
    anchorDropdown.TopText:SetText("Point")
    anchorDropdown.TopText:Show()
    anchorDropdown:SetWidth(200)
    anchorDropdown:SetupSelections(generateSetPointDropdownList(true))

    local relativeAnchorDropdown = CreateFrame("Frame", nil, anchorConfigFrame,
        "EchoRaidToolsConfig_Dropdown")
    relativeAnchorDropdown:SetPoint("TOP", anchorDropdown, "BOTTOM", 0, -10)
    relativeAnchorDropdown.TopText:SetText("Relative Point")
    relativeAnchorDropdown.TopText:Show()
    relativeAnchorDropdown:SetWidth(200)
    relativeAnchorDropdown:SetupSelections(generateSetPointDropdownList(false))

    local parentFrameDropdown = CreateFrame("Frame", nil, anchorConfigFrame,
        "EchoRaidToolsConfig_Dropdown")

    parentFrameDropdown.TopText:SetText("Parent Frame")
    parentFrameDropdown.TopText:Show()
    parentFrameDropdown:SetWidth(200)
    parentFrameDropdown:SetPoint("TOP", relativeAnchorDropdown, "BOTTOM", 0, -10)

    local presetFrames = {
        {
            icon = nil,
            label = "World Map",
            value = "WorldMapFrame",
            onclick = function()
                setAnchorField({ "anchors", "frame" }, "WorldMapFrame")
                shouldCustomAnchorFieldBeVisible()
            end
        },
        {
            icon = nil,
            label = "Screen",
            value = "UIParent",
            onclick = function()
                setAnchorField({ "anchors", "frame" }, "UIParent")
                shouldCustomAnchorFieldBeVisible()
            end
        },
        {
            icon = nil,
            label = "Custom",
            value = "",
            onclick = function()
                setAnchorField({ "anchors", "frame" }, nil)
                shouldCustomAnchorFieldBeVisible()
            end
        },
    }

    parentFrameDropdown:SetupSelections(presetFrames)


    local customFrameInput = CreateFrame("Frame", nil, anchorConfigFrame, "EchoRaidToolsConfig_EditBox")
    customFrameInput.TopText:SetText("Custom Frame")
    customFrameInput.TopText:Show()
    customFrameInput:SetWidth(200)
    customFrameInput:SetPoint("LEFT", parentFrameDropdown, "RIGHT", 10, 0)

    customFrameInput.Editbox:SetScript("OnTextChanged", function()
        local text = customFrameInput.Editbox:GetText()
        setAnchorField({ "anchors", "frame" }, text ~= "" and text or nil)
    end)

    local sliderX = CreateFrame("FRAME", nil, anchorConfigFrame, "EchoRaidTools_BetterSlider")
    sliderX:SetPoint("TOP", parentFrameDropdown, "BOTTOM", 0, -10)
    sliderX:Show()
    sliderX:SetSize(200, 32)
    sliderX.TopText:SetText("X Offset")
    sliderX.TopText:Show()
    local boundaries = { -1000, 1000, 1 }
    sliderX:Setup(
        boundaries[1], boundaries[2], boundaries[3],
        function()
            return
                temporaryDisplayInfo and module:GetField(temporaryDisplayInfo, { "anchors", "offsetX" }) or 0
        end,
        function(value)
            setAnchorField({ "anchors", "offsetX" }, value)
        end, boundaries[1], boundaries[2])




    local sliderY = CreateFrame("FRAME", nil, anchorConfigFrame, "EchoRaidTools_BetterSlider")
    sliderY:SetPoint("TOP", sliderX, "BOTTOM", 0, -10)
    sliderY:Show()
    sliderY:SetSize(200, 32)
    sliderY.TopText:SetText("Y Offset")
    sliderY.TopText:Show()
    sliderY:Setup(
        boundaries[1], boundaries[2], boundaries[3],
        function()
            return
                temporaryDisplayInfo and module:GetField(temporaryDisplayInfo, { "anchors", "offsetY" }) or 0
        end,
        function(value)
            setAnchorField({ "anchors", "offsetY" }, value)
        end, boundaries[1], boundaries[2])

    local frameStrataDropdown = CreateFrame("Frame", nil, anchorConfigFrame,
        "EchoRaidToolsConfig_Dropdown")

    frameStrataDropdown.TopText:SetText("Frame Strata")
    frameStrataDropdown.TopText:Show()
    frameStrataDropdown:SetWidth(200)
    frameStrataDropdown:SetPoint("TOP", sliderY, "BOTTOM", 0, -10)

    local strataOptions = {
        {
            icon = nil,
            label = "BACKGROUND",
            value = "BACKGROUND",
            onclick = function()
                setAnchorField({ "anchors", "strata" }, "BACKGROUND")
            end
        },
        {
            icon = nil,
            label = "LOW",
            value = "LOW",
            onclick = function()
                setAnchorField({ "anchors", "strata" }, "LOW")
            end
        },
        {
            icon = nil,
            label = "MEDIUM",
            value = "MEDIUM",
            onclick = function()
                setAnchorField({ "anchors", "strata" }, "MEDIUM")
            end
        },
        {
            icon = nil,
            label = "HIGH",
            value = "HIGH",
            onclick = function()
                setAnchorField({ "anchors", "strata" }, "HIGH")
            end
        },
        {
            icon = nil,
            label = "DIALOG",
            value = "DIALOG",
            onclick = function()
                setAnchorField({ "anchors", "strata" }, "DIALOG")
            end
        },
        {
            icon = nil,
            label = "FULLSCREEN",
            value = "FULLSCREEN",
            onclick = function()
                setAnchorField({ "anchors", "strata" }, "FULLSCREEN")
            end
        },
        {
            icon = nil,
            label = "FULLSCREEN_DIALOG",
            value = "FULLSCREEN_DIALOG",
            onclick = function()
                setAnchorField({ "anchors", "strata" }, "FULLSCREEN_DIALOG")
            end
        },
        {
            icon = nil,
            label = "TOOLTIP",
            value = "TOOLTIP",
            onclick = function()
                setAnchorField({ "anchors", "strata" }, "TOOLTIP")
            end
        },
    }

    frameStrataDropdown:SetupSelections(strataOptions)



    anchorConfigFrame.sliderX = sliderX
    anchorConfigFrame.sliderY = sliderY
    anchorConfigFrame.parentFrameDropdown = parentFrameDropdown
    anchorConfigFrame.anchorDropdown = anchorDropdown
    anchorConfigFrame.relativeAnchorDropdown = relativeAnchorDropdown
    anchorConfigFrame.customFrameInput = customFrameInput
    anchorConfigFrame.frameStrataDropdown = frameStrataDropdown
    anchorConfigFrame:SetScript("OnHide",
        function()
            closeAnchorConfig(false)
            -- double calls this function on clicking the confirm/cancel buttons, but is needed to revert to previous screen on echort hiding
        end)

    editor = window
    return editor
end
