local addonName, addon = ...

local UI = addon.UI

local CONTENT_WIDTH = 790

local function RowBoxHeight()
    return UI:Metric(56, 52, 84)
end

local function RowStep()
    return UI:Metric(60, 56, 90)
end

local function CheckSize()
    return UI:Metric(28, 24, 38)
end

local function DeleteSize()
    return UI:Metric(22, 20, 34)
end

local TIME_WIDTH = 112

local CATEGORY_LABELS = {
    OTHER = "OTHER",
    CHARACTER = "CHARACTER",
    DUNGEON = "KEYS",
    RAID = "RAID",
    PROFESSION = "PROFESSION",
    MOUNT = "MOUNT",
    ACHIEVEMENT = "ACHIEVEMENT",
}

local FALLBACK_ICONS = {
    OTHER = "Interface\\Icons\\INV_Misc_Note_01",
    CHARACTER = "Interface\\Icons\\Achievement_Character_Human_Female",
    DUNGEON = "Interface\\Icons\\INV_Relics_Hourglass",
    RAID = "Interface\\Icons\\Achievement_Raid_ClassicRaid",
    PROFESSION = "Interface\\Icons\\Trade_Archaeology",
    MOUNT = "Interface\\Icons\\Ability_Mount_RidingHorse",
    ACHIEVEMENT = "Interface\\Icons\\Achievement_General",
}

local CLASS_ICON_TEXTURE =
    "Interface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES"

local function GetTaskIconInfo(task)

    if not task then
        return FALLBACK_ICONS.OTHER
    end

    --------------------------------------------------------
    -- CHARACTER: class icon from Blizzard game files.
    --------------------------------------------------------

    if task.category == "CHARACTER" then

        local character =
            addon.GameData
            and addon.GameData:GetCharacter(
                task.characterKey
            )
            or nil

        if character
            and character.classFile
            and CLASS_ICON_TCOORDS
            and CLASS_ICON_TCOORDS[
                character.classFile
            ]
        then

            local coords =
                CLASS_ICON_TCOORDS[
                    character.classFile
                ]

            return
                CLASS_ICON_TEXTURE,
                coords[1],
                coords[2],
                coords[3],
                coords[4]

        end

        -- Fallback to the specialization icon if class
        -- coordinates are unavailable for any reason.
        if addon.GameData
            and addon.GameData.GetSpec
        then

            local spec =
                addon.GameData:GetSpec(
                    task.characterKey,
                    task.specID
                )

            if spec and spec.icon then
                return spec.icon
            end

        end

    --------------------------------------------------------
    -- PROFESSION: real profession icon returned by WoW.
    --------------------------------------------------------

    elseif task.category == "PROFESSION" then

        if addon.GameData
            and addon.GameData.GetProfession
        then

            local profession =
                addon.GameData:GetProfession(
                    task.characterKey,
                    task.professionID
                )

            if profession and profession.icon then
                return profession.icon
            end

        end

    --------------------------------------------------------
    -- RAID: Encounter Journal raid button texture.
    --------------------------------------------------------

    elseif task.category == "RAID" then

        if addon.GameData
            and addon.GameData.FindRaid
        then

            local raid =
                addon.GameData:FindRaid(
                    task.instanceID
                )

            if raid and raid.icon then
                return raid.icon
            end

        end

    --------------------------------------------------------
    -- DUNGEON / KEYS: Mythic+ map texture from WoW.
    --------------------------------------------------------

    elseif task.category == "DUNGEON" then

        if addon.GameData
            and addon.GameData.FindDungeon
        then

            local dungeon =
                addon.GameData:FindDungeon(
                    task.instanceID,
                    "KEYS"
                )

            if dungeon and dungeon.texture then
                return dungeon.texture
            end

        end

    end

    return
        FALLBACK_ICONS[task.category]
        or FALLBACK_ICONS.OTHER
end

local function CreateDateHeader(
    parent,
    text,
    y
)

    local header =
        parent:CreateFontString(
            nil,
            "OVERLAY"
        )

    header:SetFontObject(
        GameFontNormalLarge
    )

    header:SetPoint(
        "TOPLEFT",
        parent,
        "TOPLEFT",
        5,
        y
    )

    header:SetText(text)

    header:SetTextColor(
        unpack(UI.COLORS.gold)
    )

    return header
end

------------------------------------------------------------
-- DELETE POPUP
------------------------------------------------------------

function UI:CloseDeletePopup()

    if self.DeletePopup then

        self.DeletePopup:Hide()
        self.DeletePopup:SetParent(nil)

        self.DeletePopup = nil

    end

end

function UI:ShowDeleteMenu(task)

    self:CloseDeletePopup()

    local repeating =
        task.repeatType
        and task.repeatType ~= "none"

    local popup =
        CreateFrame(
            "Frame",
            nil,
            self.MainFrame,
            "BackdropTemplate"
        )

    self.DeletePopup =
        popup

    popup:SetSize(
        320,
        repeating
        and 140
        or 110
    )

    popup:SetPoint(
        "CENTER",
        self.MainFrame,
        "CENTER"
    )

    popup:SetFrameStrata(
        "TOOLTIP"
    )

    popup:EnableMouse(true)

    popup:SetBackdrop({
        bgFile =
            "Interface\\Buttons\\WHITE8X8",

        edgeFile =
            "Interface\\Tooltips\\UI-Tooltip-Border",

        edgeSize = 12,
    })

    popup:SetBackdropColor(
        unpack(self.COLORS.panel)
    )

    popup:SetBackdropBorderColor(
        unpack(self.COLORS.border)
    )

    local message =
        popup:CreateFontString(
            nil,
            "OVERLAY"
        )

    message:SetFontObject(
        GameFontNormal
    )

    message:SetPoint(
        "TOPLEFT",
        popup,
        "TOPLEFT",
        15,
        -15
    )

    message:SetPoint(
        "TOPRIGHT",
        popup,
        "TOPRIGHT",
        -15,
        -15
    )

    message:SetJustifyH(
        "CENTER"
    )

    message:SetText(
        repeating
        and "DELETE REPEATING TASK?"
        or "DELETE TASK?"
    )

    message:SetTextColor(
        unpack(self.COLORS.text)
    )

    local deleteOne =
        CreateFrame(
            "Button",
            nil,
            popup,
            "UIPanelButtonTemplate"
        )

    deleteOne:SetSize(
        90,
        28
    )

    if repeating then

        deleteOne:SetPoint(
            "BOTTOMLEFT",
            popup,
            "BOTTOMLEFT",
            10,
            15
        )

        deleteOne:SetText(UI:LT("THIS ONE"))

    else

        deleteOne:SetPoint(
            "BOTTOM",
            popup,
            "BOTTOM",
            -50,
            15
        )

        deleteOne:SetText(UI:LT("DELETE"))

    end

    deleteOne:SetScript(
        "OnClick",
        function()

            addon.DB:DeleteTask(
                task.id
            )

            self:CloseDeletePopup()
            self:Refresh()

        end
    )

    if repeating then

        local deleteAll =
            CreateFrame(
                "Button",
                nil,
                popup,
                "UIPanelButtonTemplate"
            )

        deleteAll:SetSize(
            90,
            28
        )

        deleteAll:SetPoint(
            "LEFT",
            deleteOne,
            "RIGHT",
            10,
            0
        )

        deleteAll:SetText(UI:LT("ALL"))

        deleteAll:SetScript(
            "OnClick",
            function()

                addon.DB:DeleteTaskSeries(
                    task.seriesID
                    or task.id
                )

                self:CloseDeletePopup()
                self:Refresh()

            end
        )

        local cancel =
            CreateFrame(
                "Button",
                nil,
                popup,
                "UIPanelButtonTemplate"
            )

        cancel:SetSize(
            90,
            28
        )

        cancel:SetPoint(
            "LEFT",
            deleteAll,
            "RIGHT",
            10,
            0
        )

        cancel:SetText(UI:LT("CANCEL"))

        cancel:SetScript(
            "OnClick",
            function()
                self:CloseDeletePopup()
            end
        )

    else

        local cancel =
            CreateFrame(
                "Button",
                nil,
                popup,
                "UIPanelButtonTemplate"
            )

        cancel:SetSize(
            90,
            28
        )

        cancel:SetPoint(
            "LEFT",
            deleteOne,
            "RIGHT",
            10,
            0
        )

        cancel:SetText(UI:LT("CANCEL"))

        cancel:SetScript(
            "OnClick",
            function()
                self:CloseDeletePopup()
            end
        )

    end

end

------------------------------------------------------------
-- TASK CARD
------------------------------------------------------------

function UI:CreateTaskRow(
    parent,
    task,
    y
)

    local row =
        CreateFrame(
            "Frame",
            nil,
            parent,
            "BackdropTemplate"
        )

    row:SetSize(
        math.max(360, (parent:GetWidth() or CONTENT_WIDTH) - 10),
        RowBoxHeight()
    )

    row:SetPoint(
        "TOPLEFT",
        parent,
        "TOPLEFT",
        5,
        y
    )

    row:SetBackdrop({
        bgFile =
            "Interface\\Buttons\\WHITE8X8",

        edgeFile =
            "Interface\\Buttons\\WHITE8X8",

        edgeSize = 1,
    })

    row:SetBackdropColor(unpack(self.COLORS.card))
    row:SetBackdropBorderColor(unpack(self.COLORS.borderBright))

    --------------------------------------------------------
    -- CHECK
    --------------------------------------------------------

    local check =
        CreateFrame(
            "CheckButton",
            nil,
            row,
            "UICheckButtonTemplate"
        )

    check:SetSize(
        CheckSize(),
        CheckSize()
    )

    check:SetPoint(
        "LEFT",
        row,
        "LEFT",
        8,
        0
    )

    check:SetChecked(
        task.completed == true
    )

    check:SetScript(
        "OnClick",
        function(button)

            if button:GetChecked() then

                addon.DB:CompleteTask(
                    task.id
                )

            else

                addon.DB:UncompleteTask(
                    task.id
                )

            end

            self:Refresh()

        end
    )

    --------------------------------------------------------
    -- DELETE
    --------------------------------------------------------

    local deleteButton =
        CreateFrame(
            "Button",
            nil,
            row
        )

    deleteButton:SetSize(
        DeleteSize(),
        DeleteSize()
    )

    deleteButton:SetPoint(
        "RIGHT",
        row,
        "RIGHT",
        -6,
        0
    )

    local deleteText =
        deleteButton:CreateFontString(
            nil,
            "OVERLAY"
        )

    deleteText:SetFontObject(
        GameFontNormalLarge
    )

    deleteText:SetAllPoints()
    deleteText:SetText("X")
    deleteText:SetJustifyH("CENTER")
    deleteText:SetJustifyV("MIDDLE")

    deleteText:SetTextColor(
        unpack(self.COLORS.muted)
    )

    deleteButton:SetScript(
        "OnEnter",
        function()

            deleteText:SetTextColor(
                unpack(self.COLORS.warning)
            )

            GameTooltip:SetOwner(
                deleteButton,
                "ANCHOR_TOP"
            )

            GameTooltip:SetText(UI:LT("DELETE TASK"))

            GameTooltip:Show()

        end
    )

    deleteButton:SetScript(
        "OnLeave",
        function()

            deleteText:SetTextColor(
                unpack(self.COLORS.muted)
            )

            GameTooltip:Hide()

        end
    )

    deleteButton:SetScript(
        "OnClick",
        function()
            self:ShowDeleteMenu(task)
        end
    )

    --------------------------------------------------------
    -- EDIT
    --------------------------------------------------------

    local editButton =
        CreateFrame(
            "Button",
            nil,
            row,
            "UIPanelButtonTemplate"
        )

    editButton:SetSize(
        self:Metric(46, 40, 72),
        self:Metric(24, 22, 38)
    )

    editButton:SetPoint(
        "RIGHT",
        deleteButton,
        "LEFT",
        -5,
        0
    )

    editButton:SetText(UI:LT("EDIT"))

    editButton:SetScript(
        "OnClick",
        function()
            if self.BeginEditTask then
                self:BeginEditTask(task.id)
            end
        end
    )

    --------------------------------------------------------
    -- CATEGORY ICON
    --------------------------------------------------------

    local categoryIcon =
        row:CreateTexture(
            nil,
            "ARTWORK"
        )

    categoryIcon:SetSize(
        32,
        32
    )

    categoryIcon:SetPoint(
        "LEFT",
        check,
        "RIGHT",
        6,
        0
    )

    local texture,
        left,
        right,
        top,
        bottom =
        GetTaskIconInfo(task)

    categoryIcon:SetTexture(
        texture
    )

    if left then

        categoryIcon:SetTexCoord(
            left,
            right,
            top,
            bottom
        )

    else

        categoryIcon:SetTexCoord(
            0.07,
            0.93,
            0.07,
            0.93
        )

    end

    --------------------------------------------------------
    -- RESERVED TIME COLUMN
    --
    -- This frame owns the whole right side of the card.
    -- Title/meta are anchored to its left edge, so timer text
    -- can never overlap task text.
    --------------------------------------------------------

    local timeColumn =
        CreateFrame(
            "Frame",
            nil,
            row
        )

    timeColumn:SetSize(
        122,
        RowBoxHeight() - 8
    )

    timeColumn:SetPoint(
        "RIGHT",
        editButton,
        "LEFT",
        -5,
        0
    )

    --------------------------------------------------------
    -- TIME COLUMN
    --------------------------------------------------------

    local taskTime =
        self:GetTaskTimeText(task)

    local timeText =
        row:CreateFontString(
            nil,
            "OVERLAY"
        )

    timeText:SetFontObject(
        GameFontNormal
    )

    timeText:SetWidth(
        112
    )

    timeText:SetPoint(
        "TOPRIGHT",
        timeColumn,
        "TOPRIGHT",
        0,
        -2
    )

    timeText:SetJustifyH(
        "RIGHT"
    )

    timeText:SetText(
        taskTime
    )

    timeText:SetTextColor(
        unpack(self.COLORS.gold)
    )

    --------------------------------------------------------
    -- TITLE
    --------------------------------------------------------

    local title =
        row:CreateFontString(
            nil,
            "OVERLAY"
        )

    title:SetFontObject(
        GameFontNormal
    )

    title:SetPoint(
        "TOPLEFT",
        categoryIcon,
        "TOPRIGHT",
        8,
        -1
    )

    title:SetPoint(
        "RIGHT",
        timeColumn,
        "LEFT",
        -10,
        0
    )

    title:SetHeight(17)
    title:SetJustifyH("LEFT")
    title:SetJustifyV("MIDDLE")
    title:SetWordWrap(false)

    title:SetText(
        tostring(
            task.title
            or ""
        )
    )

    if task.completed then

        title:SetTextColor(
            unpack(self.COLORS.muted)
        )

    else

        title:SetTextColor(
            unpack(self.COLORS.text)
        )

    end

    --------------------------------------------------------
    -- META
    --------------------------------------------------------

    local meta =
        row:CreateFontString(
            nil,
            "OVERLAY"
        )

    meta:SetFontObject(
        GameFontNormalSmall
    )

    meta:SetPoint(
        "BOTTOMLEFT",
        categoryIcon,
        "BOTTOMRIGHT",
        8,
        1
    )

    meta:SetPoint(
        "RIGHT",
        timeColumn,
        "LEFT",
        -10,
        0
    )

    meta:SetHeight(15)
    meta:SetJustifyH("LEFT")
    meta:SetJustifyV("MIDDLE")
    meta:SetWordWrap(false)

    local category =
        addon.DB:GetCategoryLabel(
            task.category
        )

    local context =
        self:GetTaskContextText(
            task
        )

    if context ~= "" then

        meta:SetText(
            category
            .. "  |  "
            .. context
        )

    else

        meta:SetText(
            category
        )

    end

    meta:SetTextColor(
        unpack(self.COLORS.gold)
    )

    --------------------------------------------------------
    -- REPEAT / REMAINING
    --------------------------------------------------------

    local secondary =
        row:CreateFontString(
            nil,
            "OVERLAY"
        )

    secondary:SetFontObject(
        GameFontNormalSmall
    )

    secondary:SetPoint(
        "BOTTOMRIGHT",
        timeColumn,
        "BOTTOMRIGHT",
        0,
        2
    )

    secondary:SetWidth(
        122
    )

    secondary:SetJustifyH(
        "RIGHT"
    )

    if taskTime ~= "" then

        if addon.DB:IsTaskOverdue(
            task
        ) then

            secondary:SetText(UI:LT("OVERDUE"))

            secondary:SetTextColor(
                unpack(self.COLORS.warning)
            )

        else

            secondary:SetText(
                self:FormatRemaining(
                    addon.DB:GetRemainingSeconds(
                        task
                    )
                )
            )

            secondary:SetTextColor(
                unpack(self.COLORS.muted)
            )

        end

    elseif task.repeatType
        and task.repeatType ~= "none"
    then

        local repeatText =
            "REPEATING"

        if task.repeatType == "day" then
            repeatText = "EVERY DAY"
        elseif task.repeatType == "week" then
            repeatText = "EVERY WEEK"
        elseif task.repeatType == "month" then
            repeatText = "EVERY MONTH"
        elseif task.repeatType == "custom" then

            repeatText =
                string.format(
                    "EVERY %d %s",
                    task.repeatInterval or 1,
                    string.upper(
                        task.repeatUnit
                        or "days"
                    )
                )

        end

        secondary:SetText(
            repeatText
        )

        secondary:SetTextColor(
            unpack(self.COLORS.muted)
        )

    end

    return row
end

------------------------------------------------------------
-- GROUPS
------------------------------------------------------------

function UI:CreateTaskGroup(
    parent,
    tasks,
    headerText,
    y
)

    CreateDateHeader(
        parent,
        headerText,
        y
    )

    y = y - 34

    for _, task in ipairs(tasks) do

        self:CreateTaskRow(
            parent,
            task,
            y
        )

        y = y - RowStep()

    end

    y = y - 7

    return y
end
