local _AddonName, _EchoRaidTools = ...;


local module = _EchoRaidTools:GetModule("todo-list")
module.config = module.config or {}
local config = module.config
config.open = false

local configSettings = {}

local editor, refreshMods

local rowPool = {}
local userModRows = {}
local defaultModRows = {}


local function getNeighbourStates(state)
    local ret = {}
    local mods
    local identifier = state.identifier
    if state.isDefaultMod then
        mods = module:GetDefaultModsWithOverrides()
    else
        mods = module:GetUserMods()
    end

    for i = 1, #mods do
        local mod = mods[i]
        if mod.identifier == identifier then
            ret["previous"] = mods[i - 1]
            ret["next"] = mods[i + 1]
        end
    end
    return ret
end

local function addRow(pageType)
    local mainEditor = config:GetUserEditor()
    local rowPoolCount = #rowPool
    local row
    if rowPoolCount == 0 then
        row = CreateFrame("FRAME", nil)

        row.texture = row:CreateTexture()
        row.texture:SetAllPoints()
        row.texture:SetTexture("Interface\\TARGETINGFRAME\\UI-StatusBar")
        row.enableButton = CreateFrame("CheckButton", nil, row,
            "EchoRaidToolsConfig_CheckButton")
        row.enableButton:SetSize(18, 18)
        row.enableButton.CheckButton:SetSize(18, 18)
        row.enableButton.CheckButton:SetScript("OnClick", function(self)
            local tick = self:GetChecked()
            if row.modData then
                row.modData.disabled = not tick
                module:SaveModField(row.modData, { "disabled" }, row.modData.disabled)
                module:ReloadModFromStorage(row.modData.identifier)
                refreshMods()
            end
        end)
        row.enableButton.TopText:Hide()
        row.enableButton.tooltip = "description"
        row.enableButton:SetPoint("LEFT", row, "LEFT", 5, 0)

        row.resetButton = CreateFrame("Button", nil, row)
        row.resetButton:SetPoint("RIGHT", row, "RIGHT", -5, 0)
        row.resetButton:SetSize(20, 20)
        row.resetButton:Show()

        row.resetButton:SetScript("OnClick", function()
            if row.modData then
                if row.modData.isDefaultMod then
                    module:ResetAdminOverridesForMod(row.modData.identifier)
                    module:ReloadModFromStorage(row.modData.identifier)
                else
                    module:RemoveUserMod(row.modData.identifier)
                end
                refreshMods()
                --config.openModConfigEditor(row.modData)
            end
        end)

        row.resetButton.texture = row.resetButton:CreateTexture("OVERLAY")
        row.resetButton.texture:SetAllPoints()
        row.resetButton.texture:SetAtlas("BattleBar-SwapPetIcon")
        row.resetButton.texture:Show()

        row.resetButton.textureAlt = row.resetButton:CreateTexture("OVERLAY")
        row.resetButton.textureAlt:SetAllPoints()
        row.resetButton.textureAlt:SetAtlas("BattleBar-SwapPetFrame-DeadIcon")
        row.resetButton.textureAlt:Hide()

        -----
        row.configButton = CreateFrame("Button", nil, row)
        row.configButton:SetPoint("RIGHT", row.resetButton, "LEFT", -4, 1)
        row.configButton:SetSize(20, 20)
        row.configButton:Show()

        row.configButton:SetScript("OnClick", function()
            if row.modData then
                config.openModConfigEditor(row.modData)
            end
        end)

        row.configButton.texture = row.configButton:CreateTexture("OVERLAY")
        row.configButton.texture:SetAllPoints()
        row.configButton.texture:SetAtlas("Crosshair_interact_128")
        row.configButton.texture:Show()

        row.downButton = CreateFrame("Button", nil, row)
        row.downButton:SetPoint("RIGHT", row.configButton, "LEFT", -5, -1)
        row.downButton:SetSize(20, 20)
        row.downButton:Show()

        row.downButton:SetScript("OnClick", function()
            if row.modData then
                local neighBourStates = getNeighbourStates(row.modData)
                local nextMod = neighBourStates["next"]
                if nextMod then
                    module:SaveModField(nextMod, { "index" }, row.modData.index)
                    module:SaveModField(row.modData, { "index" }, row.modData.index + 1)
                    module:ReloadModFromStorage(nextMod.identifier)
                    module:ReloadModFromStorage(row.modData.identifier)
                    refreshMods()
                end
            end
        end)

        row.downButton.texture = row.downButton:CreateTexture("OVERLAY")
        row.downButton.texture:SetAllPoints()
        row.downButton.texture:SetAtlas("CovenantSanctum-Renown-Arrow")
        row.downButton.texture:SetRotation(math.rad(90))
        row.downButton.texture:Show()

        row.upButton = CreateFrame("Button", nil, row)
        row.upButton:SetPoint("RIGHT", row.downButton, "LEFT", 4, 0)

        row.upButton:SetSize(20, 20)
        row.upButton:Show()

        row.upButton:SetScript("OnClick", function()
            if row.modData then
                local neighBourStates = getNeighbourStates(row.modData)
                local previousMod = neighBourStates["previous"]
                if previousMod then
                    module:SaveModField(previousMod, { "index" }, row.modData.index)
                    module:SaveModField(row.modData, { "index" }, row.modData.index - 1)
                    module:ReloadModFromStorage(previousMod.identifier)
                    module:ReloadModFromStorage(row.modData.identifier)
                    refreshMods()
                end
            end
        end)

        row.upButton.texture = row.upButton:CreateTexture("OVERLAY")
        row.upButton.texture:SetAllPoints()
        row.upButton.texture:SetAtlas("CovenantSanctum-Renown-Arrow")
        row.upButton.texture:SetRotation(math.rad(270))
        row.upButton.texture:Show()


        row.title = row:CreateFontString(nil, "OVERLAY", "GameFontNormal")

        row.title:SetPoint("LEFT", row.enableButton, "RIGHT", 10, 0)
        --do something cool
    else
        row = rowPool[rowPoolCount]
        rowPool[rowPoolCount] = nil
    end

    local parentFrame = pageType == "user" and mainEditor.userModsPage.moduleFrame or
        mainEditor.adminModsPage.moduleFrame

    local rowTable = pageType == "user" and userModRows or defaultModRows

    row:SetParent(parentFrame)
    table.insert(rowTable, row)
    row:Show()
end

local function removeRow(pageType)
    local rowTable
    if pageType == "user" then
        rowTable = userModRows
    elseif pageType == "default" then
        rowTable = defaultModRows
    end
    local rowTableCount = #rowTable
    if rowTableCount == 0 then return end
    local row = rowTable[rowTableCount]
    table.insert(rowPool, row)
    rowTable[rowTableCount] = nil
    row:Hide()
end

local function onShow()
    --temporarily reanchor todo-window to enchort
    config.open = true

    module.display:updateDisplaySettings()
end

local function onHide()
    config.open = false
    module.display:updateDisplaySettings()
end

---where would we call this? on mod added, on mod deleted, on mod recieved, on first show
function refreshMods()
    local rowHeight = 20
    local padding = 1
    local mainEditor = config:GetUserEditor()

    for i, mods in pairs({ module:GetUserMods(), module:GetDefaultModsWithOverrides() }) do
        local modFrame = i == 1 and mainEditor.userModsPage.moduleFrame or mainEditor.adminModsPage.moduleFrame
        local numMods = #mods
        local rowFrames = i == 1 and userModRows or defaultModRows
        local rows = #rowFrames
        local rowType = i == 1 and "user" or "default"
        if numMods > rows then
            for j = 1, numMods - rows do
                addRow(rowType)
            end
        elseif numMods < rows then
            for j = 1, rows - numMods do
                removeRow(rowType)
            end
        end

        for j, modTable in ipairs(mods) do
            local row = rowFrames[j]
            module:applyDefaultFieldsToState(modTable)
            row.modData = modTable
            row.enableButton.CheckButton:SetChecked(not row.modData.disabled)

            if j == 1 then
                row:SetPoint("TOPLEFT", modFrame, "TOPLEFT")
                row:SetPoint("TOPRIGHT", modFrame, "TOPRIGHT")
            else
                row:SetPoint("TOPLEFT", rowFrames[j - 1], "BOTTOMLEFT", 0, -padding)
                row:SetPoint("TOPRIGHT", rowFrames[j - 1], "BOTTOMRIGHT", 0, -padding)
            end
            row:SetHeight(rowHeight)
            local titleText = row.modData.name or row.modData.type .. ": " .. (row.modData.text or "")
            row.title:SetText(titleText)
            row.title:SetTextColor(unpack(modTable.textColour))


            local font = module.lsm:GetFontPath(modTable.font)
            row.title:SetFont(font, row.title:GetFontHeight())
            local texture = module.lsm:GetStatusbarPath(modTable.texture)
            row.texture:SetTexture(texture)
            if not row.texture:GetTexture() then
                row.texture:SetAtlas(texture)
            end
            local r, g, b, a = unpack(modTable.colour)
            row.texture:SetVertexColor(r, g, b, row.modData.disabled and 0.5 or 1)

            if i == 1 then
                row.resetButton.texture:Hide()
                row.resetButton.textureAlt:Show()
            else
                row.resetButton.textureAlt:Hide()
                row.resetButton.texture:Show()

                local hasoverride = module:GetAdminOverridesForMod(modTable.identifier) and true or false
                row.resetButton.texture:SetDesaturated(not hasoverride)
            end
        end

        modFrame:SetHeight((rowHeight * numMods) + 1)
    end
    ---get list of mods, set window height based on mod count
    ---if row count doesn't match mod count then adjust
    ---loop through all mods, set row info based on info recieved
    ---loop through default mods too
    ---adjust height of both windows
end

function config:GetUserEditor()
    if editor then return editor end


    local window = CreateFrame("FRAME", nil, _EchoRaidTools.panels.main, "EchoRaidToolsMainConfigWindow")
    window.Header.HeaderText:SetText("To-Do List")
    window.Header.EnableModule:SetChecked(module.GetModuleState())
    window.Header.EnableModule:SetScript("OnClick", function(self)
        module.ToggleModuleState()
        self:SetChecked(module.GetModuleState())
    end)
    window:SetScript("OnShow", onShow)
    window:SetScript("OnHide", onHide)

    local panel = CreateFrame("FRAME", nil, window, "EchoRaidToolsMainConfigPanel_NoScroll")
    window.panel = panel
    panel:SetPoint("TOPLEFT", window.Header, "BOTTOMLEFT")
    panel:SetPoint("BOTTOMRIGHT")
    local tabControl = CreateFrame("Frame", nil, panel, "EchoRaidTools_TabMainPanel")
    window.panel.tabControl = tabControl
    tabControl:ClearAllPoints()
    tabControl:SetPoint("TOPLEFT", 5, -2)
    tabControl:SetPoint("TOPRIGHT", -5, -2)
    tabControl:SetHeight(510)
    tabControl:SetScript("OnShow", refreshMods)


    local tabs = { "User Tasks", "Default Tasks", "Config" }
    local panels = tabControl:SetTabs(tabs)

    local userModsPage = 1
    window.userModsPage = panels[userModsPage]
    local adminModsPage = 2
    window.adminModsPage = panels[adminModsPage]
    local configPage = 3
    window.configPage = panels[configPage]



    local buttonWidth = 140
    local buttonHeight = 20

    for i, contentPanel in ipairs(panels) do
        if i == userModsPage or i == adminModsPage then
            local scrollFrame = CreateFrame("ScrollFrame", nil, contentPanel, "UIPanelScrollFrameTemplate")
            scrollFrame:SetPoint("TOPLEFT", contentPanel, "TOPLEFT", 0, -8)
            scrollFrame:SetPoint("BOTTOMRIGHT", contentPanel, "BOTTOMRIGHT", -20, 0)
            scrollFrame.ScrollBar:ClearAllPoints()
            scrollFrame.ScrollBar:SetPoint("TOPLEFT", contentPanel, "TOPRIGHT", -15, -15)
            scrollFrame.ScrollBar:SetPoint("BOTTOMRIGHT", contentPanel, "BOTTOMRIGHT", 0, 15)
            local moduleFrame = CreateFrame("FRAME", nil, scrollFrame, nil)

            moduleFrame:ClearAllPoints()
            moduleFrame:SetWidth(910)
            moduleFrame:SetHeight(1)
            scrollFrame:SetScrollChild(moduleFrame)

            contentPanel:SetScript("OnShow", refreshMods)
            if i == userModsPage then
                local addNewButton = CreateFrame("FRAME", nil, contentPanel, "EchoRaidToolsConfig_Button") --should probably be a child of scrollframe so that it gets clipped
                addNewButton:SetPoint("TOP", moduleFrame, "BOTTOM", 0, -10)
                addNewButton.Button:SetText("Add New Task")
                addNewButton:SetSize(buttonWidth, buttonHeight)
                addNewButton:Show()
                addNewButton.Button:SetScript("OnClick", function()
                    config.openModConfigEditor()
                end)


                local exportTasksFrame = CreateFrame("FRAME", nil, contentPanel)

                exportTasksFrame:SetPoint("CENTER",
                    window,
                    "CENTER", 0, 0)
                exportTasksFrame.editBox = CreateFrame("Frame", nil, exportTasksFrame,
                    "EchoRaidToolsConfig_EditBox")
                exportTasksFrame:SetSize(20, 20)
                exportTasksFrame.editBox.Editbox:SetMaxLetters(0)
                exportTasksFrame.editBox.TopText:SetText("Export string")
                exportTasksFrame.editBox.TopText:Show()
                exportTasksFrame.editBox:SetWidth(200)
                exportTasksFrame.editBox:SetPoint("TOP",
                    exportTasksFrame,
                    "TOP", 0, 0)

                exportTasksFrame.button = CreateFrame("FRAME", nil, exportTasksFrame, "EchoRaidToolsConfig_Button")
                exportTasksFrame.button.Button:SetText("Close")
                exportTasksFrame.button:SetSize(buttonWidth, buttonHeight)
                exportTasksFrame.button:SetPoint("TOP", exportTasksFrame.editBox, "BOTTOM", -10, 0)

                exportTasksFrame.button.Button:SetScript("OnClick", function()
                    exportTasksFrame:Hide()
                end)

                exportTasksFrame:Hide()
                local exportButton = CreateFrame("FRAME", nil, contentPanel, "EchoRaidToolsConfig_Button")
                exportButton.Button:SetText("Export Tasks")
                local importTasksFrame
                exportButton.Button:SetScript("OnClick", function()
                    importTasksFrame:Hide()
                    if exportTasksFrame:IsShown() then
                        exportTasksFrame:Hide()
                        return
                    end
                    local mods = module:GetUserMods()
                    local exportString = module:Compress(mods)
                    exportTasksFrame.editBox.Editbox:SetText(exportString)
                    exportTasksFrame:Show()
                end)
                exportButton:SetSize(buttonWidth, buttonHeight)
                exportButton:SetPoint("TOPRIGHT", panel, "TOPRIGHT", -20, -8)
                exportButton:Show()


                importTasksFrame = CreateFrame("FRAME", nil, contentPanel)

                importTasksFrame:SetPoint("CENTER",
                    window,
                    "CENTER", 0, 0)
                importTasksFrame.editBox = CreateFrame("Frame", nil, importTasksFrame,
                    "EchoRaidToolsConfig_EditBox")
                importTasksFrame:SetSize(20, 20)
                importTasksFrame.editBox.Editbox:SetMaxLetters(0)
                importTasksFrame.editBox.TopText:SetText("Paste string here")
                importTasksFrame.editBox.TopText:Show()
                importTasksFrame.editBox:SetWidth(200)
                importTasksFrame.editBox:SetPoint("TOP",
                    importTasksFrame,
                    "TOP", 0, 0)

                importTasksFrame.button = CreateFrame("FRAME", nil, importTasksFrame, "EchoRaidToolsConfig_Button")
                importTasksFrame.button.Button:SetText("Import")
                importTasksFrame.button:SetSize(buttonWidth, buttonHeight)
                importTasksFrame.button:SetPoint("TOP", importTasksFrame.editBox, "BOTTOM", -10, 0)

                importTasksFrame.button.Button:SetScript("OnClick", function()
                    importTasksFrame:Hide()

                    local importString = importTasksFrame.editBox.Editbox:GetText()
                    local data = module:Decompress(importString)
                    if not data then
                        print("bad import string"); return
                    end
                    for _, modData in ipairs(data) do
                        module:SaveUserMod(modData)
                    end
                    importTasksFrame:Hide()
                    refreshMods()
                end)
                importTasksFrame:Hide()



                local importButton = CreateFrame("FRAME", nil, contentPanel, "EchoRaidToolsConfig_Button")
                importButton.Button:SetText("Import Tasks")
                importButton:SetSize(buttonWidth, buttonHeight)
                importButton:SetPoint("RIGHT", exportButton, "LEFT", -10, 0)
                importButton.Button:SetScript("OnClick", function()
                    exportTasksFrame:Hide()
                    if importTasksFrame:IsShown() then
                        importTasksFrame:Hide()
                        return
                    end
                    importTasksFrame.editBox.Editbox:SetText("")
                    importTasksFrame:Show()
                end)
                importButton:Show()
            end
            panels[i].moduleFrame = moduleFrame
        elseif i == configPage then
            local moduleFrame = config:GetDisplayConfig(contentPanel)
            panels[i].moduleFrame = moduleFrame
        end
    end


    editor = window
    refreshMods()
    onShow()
    return window
end
