-----------------------------------
--This file modifies the Tech Database UI with new categories and sorting methods
-----------------------------------

(function()

    local topics = require('lib_ui_topics')
    local bta = require('btafunctions')
    local utils = require('lib_utils')

    local zeroDay = bta:getGameProgress('bta2_m2_05')

    -- Add the hyphen in GTVA display name because internally with the hyphen is one character too long
    topics.intel.name:bind(9999, function(message, context)
        if message.Name == ba.XSTR("Galactic TerranVasudan Alliance", 11365) then
            context.value = ba.XSTR("Galactic Terran-Vasudan Alliance", 11368)
        end
    end)

    -- After Hic Est Draco use intel_inedam_2 for the Inedam intel entry
    topics.techdatabase.initIntelData:bind(9999, function (message, context)
        if bta:getGameProgress() >= bta:getGameProgress('bta2_m3_01') then
            if string.lower(message[2].Anim) == 'intel_inedam' then
                message[2].Anim = 'intel_inedam_2'
            end
        end
    end)

    -- Before "Zero Day", replace I with T for INEDAM ships
    topics.ships.name:bind(9999, function(message, context)
        if bta:getGameProgress() < zeroDay then
            if message.Name == 'IN.E.D.A.M.01' then
                context.value = 'GTF Out'
            elseif message.Species.Name == 'INEDAM' then
                context.value = "T" .. string.sub(context.value, 2)
            end
        end
    end)

    -- Before "Zero Day", reword descriptions to say "raiders" instead of "INEDAM"
    topics.ships.description:bind(9999, function(message, context)
        if bta:getGameProgress() < zeroDay then
            local text = message.CustomData.AltTechDesc
            local xstr = message.CustomData.AltTechDescXSTR
            if text and xstr then
                context.value = ba.XSTR(text, xstr)
            elseif text or xstr then
                ba.warning(message.Name .. ' has an incomplete alt tech description')
            end
        end
    end)

    -- Before "Zero Day", reword descriptions to say "raiders" instead of "INEDAM"
    topics.weapons.description:bind(9999, function(message, context)
        if bta:getGameProgress() < zeroDay then
            local text = message.CustomData.AltTechDesc
            local xstr = message.CustomData.AltTechDescXSTR
            if text and xstr then
                context.value = ba.XSTR(text, xstr)
            elseif text or xstr then
                ba.warning(message.Name .. ' has an incomplete alt tech description')
            end
        end
    end)

    topics.intel.type:bind(0, function(message, context)
        if message:hasCustomData() then
            context.value = utils.xstr(utils.parseCustomXSTR(message.CustomData["Category"]))
        end
    end)

    --Make our custom sorting category buttons
    topics.techdatabase.initialize:bind(1, function(message, context)
        local faction_btn = ScpuiSystem:makeButton(message, "sort_bullet_cont", "faction_cat_btn", {"bullet", "button_1"}, "bullet", "bullet-r.png", "faction_btn_text", {"pos", "button_text_sort"}, ba.XSTR("By Faction", 9303))

        local manufacturer_btn = ScpuiSystem:makeButton(message, "sort_bullet_cont", "manufacturer_cat_btn", {"bullet", "button_1"}, "bullet", "bullet-r.png", "manufacturer_btn_text", {"pos", "button_text_sort"}, ba.XSTR("By Manufacturer", 9304))

        faction_btn:AddEventListener("click", function(_, _, _)
            message:set_sort_category("faction")
        end)

        manufacturer_btn:AddEventListener("click", function(_, _, _)
            message:set_sort_category("manufacturer")
        end)


        local panel_el = message.Document:GetElementById("category_b_panel_wrapper")
        panel_el:AppendChild(faction_btn)
        panel_el:AppendChild(manufacturer_btn)
    end)

    --Setup the custom category tables
    topics.techdatabase.beginDataLoad:bind(1, function(message, context)
        message.s_factions = {}
        message.s_manufacturers = {}
        message.w_factions = {}
        message.w_manufacturers = {}
    end)

    --Add faction and manufacturer to the ship data
    topics.techdatabase.initShipData:bind(1, function(message, context)
        message[2].Faction = Factions:getFactionFromCustomData(tb.ShipClasses[message[2].FsoIndex], true)
        message[2].Manufacturer = Factions:getManufacturerFromCustomData(tb.ShipClasses[message[2].FsoIndex], true)

        --If we're too early in the game, then replace INEDAM with Other/Multiple
        if bta:getGameProgress() < zeroDay then
            if message[2].Manufacturer == ba.XSTR("IN.E.D.A.M", 9305) then
                message[2].Manufacturer = ba.XSTR("Other/Multiple", 9306)
            end
        end

        if not utils.table.contains(message[1].s_factions, message[2].Faction) then
            table.insert(message[1].s_factions, message[2].Faction)
        end

        if not utils.table.contains(message[1].s_manufacturers, message[2].Manufacturer) then
            table.insert(message[1].s_manufacturers, message[2].Manufacturer)
        end
    end)

    --Add faction and manufacturer to the weapon data. Also append to the weapon type
    topics.techdatabase.initWeaponData:bind(1, function(message, context)
        message[2].Faction = Factions:getFactionFromCustomData(tb.WeaponClasses[message[2].FsoIndex])
        message[2].Manufacturer = Factions:getManufacturerFromCustomData(tb.WeaponClasses[message[2].FsoIndex])

        --For BtA we append the subtype to the type
        if tb.WeaponClasses[message[2].FsoIndex]:hasCustomData() then
            if tb.WeaponClasses[message[2].FsoIndex].CustomData["type"] ~= nil then
                local category = utils.xstr(utils.parseCustomXSTR(tb.WeaponClasses[message[2].FsoIndex].CustomData["type"]))
                message[2].Type = message[2].Type .. ": " .. category
            end
        end

        if not utils.table.contains(message[1].w_factions, message[2].Faction) then
            table.insert(message[1].w_factions, message[2].Faction)
        end

        if not utils.table.contains(message[1].w_manufacturers, message[2].Manufacturer) then
            table.insert(message[1].w_manufacturers, message[2].Manufacturer)
        end
    end)

    --Add our custom sort functions
    topics.techdatabase.initSortFuncs:bind(1, function(message, context)
        local function sortByFactionAsc_Alph(a, b)
            if a.Faction == b.Faction then
                return message.ItemSort(a, b)
            else
                return a.Faction < b.Faction
            end
        end
        message.Sort_Functions.sortByFactionAsc_Alph = sortByFactionAsc_Alph

        local function sortByFactionDes_Alph(a, b)
            if a.Faction == b.Faction then
                return message.ItemSort(a, b)
            else
                return a.Faction > b.Faction
            end
        end
        message.Sort_Functions.sortByFactionDes_Alph = sortByFactionDes_Alph

        local function sortByFactionAsc_Idx(a, b)
            local tbl = nil
            if message.SelectedSection == "ships" then
                tbl = message.s_factions
            elseif message.SelectedSection == "weapons" then
                tbl = message.w_factions
            end

            local a_idx = utils.table.ifind(tbl, a.Faction)
            local b_idx = utils.table.ifind(tbl, b.Faction)
            if a.Faction == b.Faction then
                return message.ItemSort(a, b)
            else
                return a_idx < b_idx
            end
        end
        message.Sort_Functions.sortByFactionAsc_Idx = sortByFactionAsc_Idx

        local function sortByFactionDes_Idx(a, b)
            local tbl = nil
            if message.SelectedSection == "ships" then
                tbl = message.s_factions
            elseif message.SelectedSection == "weapons" then
                tbl = message.w_factions
            end

            local a_idx = utils.table.ifind(tbl, a.Faction)
            local b_idx = utils.table.ifind(tbl, b.Faction)
            if a.Faction == b.Faction then
                return message.ItemSort(a, b)
            else
                return a_idx > b_idx
            end
        end
        message.Sort_Functions.sortByFactionDes_Idx = sortByFactionDes_Idx

        local function sortByManufacturerAsc_Alph(a, b)
            if a.Manufacturer == b.Manufacturer then
                return message.ItemSort(a, b)
            else
                return a.Manufacturer < b.Manufacturer
            end
        end
        message.Sort_Functions.sortByManufacturerAsc_Alph = sortByManufacturerAsc_Alph

        local function sortByManufacturerDes_Alph(a, b)
            if a.Manufacturer == b.Manufacturer then
                return message.ItemSort(a, b)
            else
                return a.Manufacturer > b.Manufacturer
            end
        end
        message.Sort_Functions.sortByManufacturerDes_Alph = sortByManufacturerDes_Alph

        local function sortByManufacturerAsc_Idx(a, b)
            local tbl = nil
            if message.SelectedSection == "ships" then
                tbl = message.s_manufacturers
            elseif message.SelectedSection == "weapons" then
                tbl = message.w_manufacturers
            end

            local a_idx = utils.table.ifind(tbl, a.Manufacturer)
            local b_idx = utils.table.ifind(tbl, b.Manufacturer)
            if a.Manufacturer == b.Manufacturer then
                return message.ItemSort(a, b)
            else
                return a_idx < b_idx
            end
        end
        message.Sort_Functions.sortByManufacturerAsc_Idx = sortByManufacturerAsc_Idx

        local function sortByManufacturerDes_Idx(a, b)
            local tbl = nil
            if message.SelectedSection == "ships" then
                tbl = message.s_manufacturers
            elseif message.SelectedSection == "weapons" then
                tbl = message.w_manufacturers
            end

            local a_idx = utils.table.ifind(tbl, a.Manufacturer)
            local b_idx = utils.table.ifind(tbl, b.Manufacturer)
            if a.Manufacturer == b.Manufacturer then
                return message.ItemSort(a, b)
            else
                return a_idx > b_idx
            end
        end
        message.Sort_Functions.sortByManufacturerDes_Idx = sortByManufacturerDes_Idx
    end)

    --Handle setting the category properly
    topics.techdatabase.setSortCat:bind(1, function(message, context)
        context.value = true
        if message[2] == "faction" then
            if message[1].CurrentSortCategory == "faction_asc_alph" then
                message[1].CurrentSortCategory = "faction_des_alph"
            elseif message[1].CurrentSortCategory == "faction_des_alph" then
                message[1].CurrentSortCategory = "faction_asc_idx"
            elseif message[1].CurrentSortCategory == "faction_asc_idx" then
                message[1].CurrentSortCategory = "faction_des_idx"
            else
                message[1].CurrentSortCategory = "faction_asc_alph"
            end
        elseif message[2] == "manufacturer" then
            if message[1].CurrentSortCategory == "manu_asc_alph" then
                message[1].CurrentSortCategory = "manu_des_alph"
            elseif message[1].CurrentSortCategory == "manu_des_alph" then
                message[1].CurrentSortCategory = "manu_asc_idx"
            elseif message[1].CurrentSortCategory == "manu_asc_idx" then
                message[1].CurrentSortCategory = "manu_des_idx"
            else
                message[1].CurrentSortCategory = "manu_asc_alph"
            end
        else
            context.value = false
        end
    end)

    --Handle hiding/unhiding the custom buttons based on the current section
    topics.techdatabase.selectSection:bind(1, function(message, context)
        if message[2] == "intel" then
            message[1].Document:GetElementById("faction_cat_btn"):SetClass("hidden", true)
            message[1].Document:GetElementById("manufacturer_cat_btn"):SetClass("hidden", true)
        else
            message[1].Document:GetElementById("faction_cat_btn"):SetClass("hidden", false)
            message[1].Document:GetElementById("manufacturer_cat_btn"):SetClass("hidden", false)
        end
    end)

    --Does the custom category sorting
    topics.techdatabase.sortCategories:bind(1, function(message, context)
        context.value = true
        if message.CurrentSortCategory == "faction_asc_alph" then
            table.sort(message.Current_List, message.Sort_Functions.sortByFactionAsc_Alph)
            message.Document:GetElementById("faction_cat_btn"):SetPseudoClass("checked", true)
        elseif message.CurrentSortCategory == "faction_des_alph" then
            table.sort(message.Current_List, message.Sort_Functions.sortByFactionDes_Alph)
            message.Document:GetElementById("faction_cat_btn"):SetPseudoClass("checked", true)
        elseif message.CurrentSortCategory == "faction_asc_idx" then
            table.sort(message.Current_List, message.Sort_Functions.sortByFactionAsc_Idx)
            message.Document:GetElementById("faction_cat_btn"):SetPseudoClass("checked", true)
        elseif message.CurrentSortCategory == "faction_des_idx" then
            table.sort(message.Current_List, message.Sort_Functions.sortByFactionDes_Idx)
            message.Document:GetElementById("faction_cat_btn"):SetPseudoClass("checked", true)
        elseif message.CurrentSortCategory == "manu_asc_alph" then
            table.sort(message.Current_List, message.Sort_Functions.sortByManufacturerAsc_Alph)
            message.Document:GetElementById("manufacturer_cat_btn"):SetPseudoClass("checked", true)
        elseif message.CurrentSortCategory == "manu_des_alph" then
            table.sort(message.Current_List, message.Sort_Functions.sortByManufacturerDes_Alph)
            message.Document:GetElementById("manufacturer_cat_btn"):SetPseudoClass("checked", true)
        elseif message.CurrentSortCategory == "manu_asc_idx" then
            table.sort(message.Current_List, message.Sort_Functions.sortByManufacturerAsc_Idx)
            message.Document:GetElementById("manufacturer_cat_btn"):SetPseudoClass("checked", true)
        elseif message.CurrentSortCategory == "manu_des_idx" then
            table.sort(message.Current_List, message.Sort_Functions.sortByManufacturerDes_Idx)
            message.Document:GetElementById("manufacturer_cat_btn"):SetPseudoClass("checked", true)
        else
            context.value = false
        end
    end)

    --Uncheck our custom sorting buttongs
    topics.techdatabase.uncheckSorts:bind(1, function(message, context)
        message.Document:GetElementById("faction_cat_btn"):SetPseudoClass("checked", false)
        message.Document:GetElementById("manufacturer_cat_btn"):SetPseudoClass("checked", false)
    end)

    --Create the special headers for our custom sorts
    topics.techdatabase.createHeader:bind(1, function(message, context)
        local list_names_el = message[1].Document:GetElementById("list_items_ul")
        if utils.extractString(message[1].CurrentSortCategory, "_") == "manu" then
            if message[2].Visible or message[1].ShowAll then
                if message[2].Manufacturer ~= message[1].CurrentCategory then
                    message[1].CurrentCategory = message[2].Manufacturer
                    local entry = Factions:getFactionByName(message[2].Manufacturer)
                    local selectable = Factions:checkFactionExists(entry.Name)
                    list_names_el:AppendChild(message[1]:createListItemElement(entry, nil, selectable, true))
                end
            end
        elseif utils.extractString(message[1].CurrentSortCategory, "_") == "faction" then
            if message[2].Visible or message[1].ShowAll then
                if message[2].Faction ~= message[1].CurrentCategory then
                    message[1].CurrentCategory = message[2].Faction
                    local entry = Factions:getFactionByAcronym(message[2].Faction)
                    local selectable = Factions:checkFactionExists(entry.Name)
                    list_names_el:AppendChild(message[1]:createListItemElement(entry, nil, selectable, true))
                end
            end
        end
    end)

    --If a heading is selected, we handle that here
    topics.techdatabase.selectHeader:bind(1, function(message, context)
        message[1].Document:GetElementById("tech_desc").inner_rml = message[2].Description

        ScpuiSystem.data.memory.model_rendering.Class = nil

        --Currently expects a still image. Anims not supported
        local aniEl = message[1].Document:CreateElement("img")
        local divEl = message[1].Document:CreateElement("div")
        divEl.id = "logo"

        if utils.animExists(message[2].Logo) then
            aniEl:SetAttribute("src", message[2].Logo)
        end

        divEl:AppendChild(aniEl)

        local aniWrapper = message[1].Document:GetElementById("tech_view")
        aniWrapper:ReplaceChild(divEl, aniWrapper.first_child)

        message[1]:toggleSliders(false)

        --Scroll to the top of the list
        message[1].Document:GetElementById("tech_desc").scroll_top = 0
    end)

  end)()