-----------------------------------
--This file contains all the miscellaneous changes for BtA's UI
-----------------------------------

(function()

    local topics = require('lib_ui_topics')
    --local bta = require('btafunctions')
    local utils = require('lib_utils')
    local btaloadouts = require('btaloadouts')
    local datasaver = require('lib_data_saver')

    --Replace the loading screen image with the BtA specific one
    topics.loadscreen.load_bar:bind(9999, function(message, context)
        context.value = "btaloading"
    end)

    topics.loadscreen.initialize:bind(9999, function(message, context)
        local tip_el = message.Document:CreateElement('div')
        tip_el.inner_rml = Tips.tip() -- This function should be moved in here directly probably instead of being a global
        tip_el.style.width = "75%"
        tip_el.style.margin = "auto"
        tip_el.style.position = "absolute"
        tip_el.style.top = "83%"
        tip_el.style.left = "0"
        tip_el.style['text-align'] = "center"
        ScpuiSystem:getRootParent(message.Document):AppendChild(tip_el)

        message.Document:GetElementById("loadingbar").style.width = "10%"
        message.Document:GetElementById("loadingbar").style.top = "86%"

        ScpuiSystem.data.memory.loading_bar.LoopLoadBar = true
    end)

    -- Requires SCPUI 1.1.2
    --[[topics.briefing.modelTeamColor:bind(9999, function(message, context)
        local mission_name = message[1]
        local ship = message[2]
        local icon_id = message[3]

        if mission_name == "bta1_m2_05" then
            if icon_id == 3 then
                context.value = "Smuggler 4"
            end
        end
    end)]]--

    --Add our custom keys to the game help screen
    topics.gamehelp.initialize:bind(9999, function(message, context)
        local addKeys = {
            {"$Alt-Shift-A$", ba.XSTR("Remote Trigger", 2501, false)},
            {"$Alt-Shift-S$", ba.XSTR("Drop Tertiary Payload", 2502, false)},
            {"$Alt-Shift-D$", ba.XSTR("ECM Action", 2503, false)},
            {"$Alt-Shift-Z$", ba.XSTR("Toggle Headlights", 2504, false)},
            {"$Alt-Shift-X$", ba.XSTR("Context Action", 2505, false)},
        }

        --Add to the basic keys table which is section 1
        for _, pair in ipairs(addKeys) do
            table.insert(message.Sections[1].Keys, ba.replaceTokens(pair[1]))
            table.insert(message.Sections[1].Texts, pair[2])
        end
    end)

    --Pause all UI sounds if we're playing a cutscene
    topics.playcutscene.start:bind(9999, function(message, context)
        UISound.pauseAll(true)
    end)

    --Unpause all UI sounds after the cutscene finishes
    topics.playcutscene.finish:bind(9999, function(message, context)
        UISound.pauseAll(false)
    end)

    --Custom mission requirements to launch a mission
    topics.mission.commit:bind(9999, function(message, context)
        context.value = true

        --The show dialog function
        local function show_dialog(ctxt, title, text)
            --We need to stop the ship/weapon/briefing direct draws for the popup
            local draw
            local odraw
            if ScpuiSystem.data.memory.model_rendering then
                draw = ScpuiSystem.data.memory.model_rendering.Class
                ScpuiSystem.data.memory.model_rendering.Class = nil
                odraw = ScpuiSystem.data.memory.model_rendering.OverheadClass
                ScpuiSystem.data.memory.model_rendering.OverheadClass = nil
            end
            --Only stop the briefing map rendering if it's in Screen mode
            if string.lower(ScpuiSystem.data.ScpuiOptionValues.Brief_Render_Option) == "screen" then
                if ScpuiSystem.data.memory.briefing_map then
                    ScpuiSystem.data.memory.briefing_map.Draw = false
                end
            end

            --Build the dialog warning
            local dialogs = require("lib_dialogs")

            local dialog = dialogs.new()
            dialog:title(title)
            dialog:text(text)
            dialog:escape("")
            dialog:button(dialogs.BUTTON_TYPE_POSITIVE, ba.XSTR("Okay", 10819), true, "o")
            dialog:show(ctxt)
            :continueWith(function(response)
                --Reset the ship/weapon/briefing direct draws
                if ScpuiSystem.data.memory.model_rendering then
                    ScpuiSystem.data.memory.model_rendering.Class = draw
                    ScpuiSystem.data.memory.model_rendering.OverheadClass = odraw
                end
                if ScpuiSystem.data.memory.briefing_map then
                    ScpuiSystem.data.memory.briefing_map.Draw = true
                end
            end)
            -- Route input to our context until the user dismisses the dialog box.
            ui.enableInput(ctxt)
        end

        --For bta2_m2_05L, check the player's options will work for the mission
        if mn.getMissionFilename() == "bta2_m2_05L" then
            --Get the user's current settings
            local lighting
            local postProc
            for k, v in pairs(opt.Options) do
                if v.Key == "Graphics.Lighting" then
                    lighting = v
                end
                if v.Key == "Graphics.PostProcessing" then
                    postProc = v
                end
            end

            --Check if we can play
            if lighting.Value.Display ~= ba.XSTR("Ultra", 1721, false) or postProc.Value.Display ~= ba.XSTR("Ultra", 1285, false) then
                context.value = false -- Cannot commit to the mission!

                local msg = ba.XSTR("This mission requires that Post Processing be turned on and that Lighting be set to Ultra. You can change these settings in Options/Detail. Your current settings do not match and are listed below.", 11348)

                local msg = msg .. "<br></br><br></br>" .. postProc.Title .. ": " .. postProc.Value.Display
                local msg = msg .. "<br></br>" .. lighting.Title .. ": " .. lighting.Value.Display

                show_dialog(message.Document.context, ba.XSTR("Settings Warning", 11349), msg)
            end
        end

        --Check if Alpha wing should all have some kind of disruptors
        local disruptors_required = false
        if mn.hasCustomData() then
            if mn.CustomData["AlphaDisruptors"] and mn.CustomData["AlphaDisruptors"] == "true" then
                disruptors_required = true
            end
        end

        --For missions that require disruptors, check that all of Alpha are carrying one of the disruptor weapons
        if disruptors_required then
            local loadoutHandler = require("lib_loadout_handler")

            local no_play = false
            local alpha = {false, false, false, false}
            local names = {}

            --Get Alpha's primary(?) weapons
            --Only do this for Alpha wing (loadout slots 1-4)
            for i = 1, 4, 1 do
                local ship = loadoutHandler:GetShipLoadout(i)

                --save the name for later use in the dialog
                table.insert(names, ship.Name)

                --If the slot is empty then just set it to true
                if ship.ShipClassIndex == -1 then
                    alpha[i] = true
                else
                    --Now check the weapons
                    for w = 1, #ship.Weapons_List, 1 do
                        if tb.WeaponClasses[ship.Weapons_List[w]]:isValid() then
                            local weapon = tb.WeaponClasses[ship.Weapons_List[w]].Name
                            if utils.isOneOf(weapon, "Disruptor", "DisruptorSDG", "Lancet", "Railgun Evo", "Stiletto", "Stiletto II") then
                                alpha[i] = true
                                break
                            end
                        end
                    end
                end
            end

            --Are any of Alpha wing missing a disruptor style weapon?
            for i = 1, #alpha, 1 do
                if not alpha[i] then
                    no_play = true
                    break
                end
            end

            --Check if we can play
            if no_play then
                context.value = false -- Cannot commit to the mission!

                local msg = ba.XSTR("The following ships must have an Anti-subsystem weapon equipped!", 11370)

                --Add the list of ships
                msg = msg .. "<br></br><br></br>"

                for i = 1, #alpha, 1 do
                    if not alpha[i] then
                        msg = msg .. "<br></br>" .. names[i]
                    end
                end

                show_dialog(message.Document.context, ba.XSTR("Weapons Warning", 11369), msg)
            end
        end
    end)

    --Make the alarm voice selector in options play a voice preview
    topics.options.initialize:bind(9999, function(message, context)
        local alarm_el = message.Document:GetElementById("option_alarm_voice_element")
        local select_el = alarm_el.first_child.next_sibling.first_child.first_child
        local dataselect_el = Element.As.ElementFormControlDataSelect(select_el)

        select_el:AddEventListener("change", function(event, _, _)
            local alarms = require('alarms')
            local idx = alarms.getVoiceIndex(dataselect_el.value)
            local file = idx .. "_WepEnergyLow.ogg"
            ad.loadSoundfile(file):play()
        end)
    end)

    --Hide the briefing audio option
    topics.options.initialize:bind(9999, function(message, context)
        local el = message.Document:GetElementById("option_audio_briefingvoice_element")
        el:SetClass("hidden", true)
    end)

    --Show a dialog prompt on Accepting the bta2_m2_05 FV stage
    topics.fictionviewer.accept:bind(9999, function(message, context)
        if mn.getMissionFilename() == "bta2_m2_05" then
            if not message.DialogSeen then
                context.value = false -- Stop Fiction Viewer from continuing to the next screen
                local dialogs = require("lib_dialogs")

                local dialog = dialogs.new()
                dialog:title(ba.XSTR("Continue?", 9290))
                dialog:text(ba.XSTR("This message from Acting Captain Jers contains important information for the next mission that will not be covered again. Are you sure you're ready to proceed to the briefing?", 9291))
                dialog:escape("")
                dialog:button(dialogs.BUTTON_TYPE_NEGATIVE, ba.XSTR("No", 9292), false, "n")
                dialog:button(dialogs.BUTTON_TYPE_POSITIVE, ba.XSTR("Yes", 257), true, "y")
                dialog:show(message.Document.context)
                :continueWith(function(response)
                    if response == true then
                        message:acceptPressed()
                    end
                end)
                -- Route input to our context until the user dismisses the dialog box.
                ui.enableInput(message.Document.context)
                message.DialogSeen = true
            end
        else
            context.value = true
        end
    end)

    --Pause scripted audio
    topics.Scpui.pauseAudio:bind(9999, function(message, context)
        local ScriptedAudio = require("soundhandler")
        ScriptedAudio:pauseScriptedSounds(message)
    end)

    --Update effects volume
    topics.Scpui.pauseAudio:bind(9999, function(message, context)
        local ScriptedAudio = require("soundhandler")
        ScriptedAudio:updateVolumes(false)
    end)

    --Update voice volume
    topics.Scpui.pauseAudio:bind(9999, function(message, context)
        local ScriptedAudio = require("soundhandler")
        ScriptedAudio:updateVolumes(true)
    end)

    --Adds Brief Title to the relevant UI screens
    topics.briefcommon.initialize:bind(1, function(message, context)

        local state = ba.getCurrentGameState().Name
        if not utils.isOneOf(state, "GS_STATE_BRIEFING", "GS_STATE_CMD_BRIEF") then
            return
        end

        local SKIP_STRING = ba.XSTR("none", 5002)

        message.BriefTitle = {}
        --Try and get the brief title information
        if mn.hasCustomData() then
            local date = SKIP_STRING
            local location = SKIP_STRING
            if mn.CustomData["MissionDate"] then
                date = utils.translateCustomXSTR(mn.CustomData["MissionDate"])
            end
            if mn.CustomData["MissionLocation"] then
                location = utils.translateCustomXSTR(mn.CustomData["MissionLocation"])
            end

            if date ~= SKIP_STRING then
                table.insert(message.BriefTitle, date)
            end
            if location ~= SKIP_STRING then
                table.insert(message.BriefTitle, location)
            end
        end

        --If we have a custom setting for command briefing then use it
        if state == "GS_STATE_CMD_BRIEF" then
            if mn.hasCustomData() then
                local date = SKIP_STRING
                local location = SKIP_STRING
                if mn.CustomData["CBriefMissionDate"] then
                    date = utils.translateCustomXSTR(mn.CustomData["CBriefMissionDate"])
                end
                if mn.CustomData["CBriefMissionLocation"] then
                    location = utils.translateCustomXSTR(mn.CustomData["CBriefMissionLocation"])
                end

                if date ~= SKIP_STRING then
                    message.BriefTitle[1] = date
                end
                if location ~= SKIP_STRING then
                    message.BriefTitle[2] = location
                end
            end
        end

        -- Impossible but whatever, check anyway
        if message.BriefTitle == nil then
            return
        end

        if message.BriefTitle[1] == SKIP_STRING then
            return
        end

        local wrap_el = message.Document:CreateElement("div")
        wrap_el.id = "brieftitle_wrapper"
        wrap_el.style.width =  "15%"
        wrap_el.style.height = "auto"
        wrap_el.style.overflow = "hidden"
        wrap_el.style.position = "absolute"
        local pos = "15%"
        wrap_el.style.top = pos
        wrap_el.style.right = "0"

        local panel_el = message.Document:CreateElement("div")
        panel_el.id = "brieftitle_panel"
        panel_el.style.width = "66%"
        panel_el.style.height = "auto"
        panel_el.style.position = "relative"
        panel_el.style.float = "right"

        local text_el = message.Document:CreateElement("div")
        text_el.id = "brieftitle_text_wrapper"
        text_el.style["text-align"] = "center"
        text_el.style["margin-right"] = "3%"
        text_el.style["margin-top"] = "25%"
        text_el.style.position = "absolute"

        if text_el then
            if message.BriefTitle then
                local s = ""
                for i,v in ipairs(message.BriefTitle) do
                    s = s .. "<p>" .. v .. "</p>"
                end
                text_el.inner_rml = s
            else
                text_el.parent_node:SetClass("hidden", true)
            end
        end

        local img_el = message.Document:CreateElement("img")
        img_el:SetAttribute("src", "ops-panel-gen-r.png")
        img_el.style.display = "block"
        img_el.style.width = "100%"
        img_el.style.height = "auto"

        panel_el:AppendChild(text_el)
        panel_el:AppendChild(img_el)
        wrap_el:AppendChild(panel_el)

        local mainbg = ScpuiSystem:getRootParent(message.Document)
        mainbg:InsertBefore(wrap_el, mainbg.first_child)
    end)

    --Adds System Map Button to the relevant UI screens
    topics.briefcommon.initialize:bind(3, function(message, context)

        local state = ba.getCurrentGameState().Name
        if not utils.isOneOf(state, "GS_STATE_BRIEFING", "GS_STATE_CMD_BRIEF") then
            return
        end

        if not mn.isInCampaign() then
            return
        end


		--TODO update this check for tables!
        --Only setup system viewer stuff if the config exists
        local sysviewfilename = "sysview_" .. ba.getCurrentPlayer():getCampaignFilename() .. "_config.cfg"
        if cf.fileExists(sysviewfilename, "data/config", true) then

            --Do the nasty and make the children

            local wrap_el = message.Document:CreateElement("div")
            wrap_el.id = "system_panel_wrapper"
            wrap_el.style.width = "8%"
            wrap_el.style.height = "auto"
            wrap_el.style.overflow = "hidden"
            wrap_el.style.position = "absolute"
            wrap_el.style.bottom = "30%"
            wrap_el.style.right = "0"

            local new_el = message.Document:CreateElement("div")
            new_el.id = "sysmap_new"
            new_el:SetClass("red", true)
            new_el.inner_rml = ba.XSTR("New!", 9294)
            new_el.style.position = "absolute"
            new_el.style["margin-top"] = "25%"

            local side_el = message.Document:CreateElement("div")
            side_el.id = "side_panel"
            side_el.style.width = "66%"
            side_el.style.height = "auto"
            side_el.style.position = "relative"
            side_el.style.float = "right"

            local panel_el = message.Document:CreateElement("div")
            panel_el.id = "s_panel_wrapper"
            panel_el.style.position = "absolute"
            panel_el.style.bottom = "5"
            panel_el.style.width = "100%"

            local panel_img = message.Document:CreateElement("img")
            panel_img:SetAttribute("src", "top-right-panel.png")
            panel_img.style.display = "block"
            panel_img.style.width = "100%"
            panel_img.style.height = "auto"

            local cont_el = message.Document:CreateElement("div")
            cont_el.id = "side_cont"
            cont_el.style.width = "100%"
            cont_el.style.height = "auto"

            local button_el = message.Document:CreateElement("button")
            button_el.id = "system_btn"
            button_el:SetClass("button_2", true)
            button_el.style.display = "block"
            button_el.style.width = "100%"
            button_el.style.height = "auto"

            local button_span_el = message.Document:CreateElement("span")
            button_span_el.id = "system_img"
            button_span_el:SetClass("button_img", true)
            button_span_el.style.display = "block"
            button_span_el.style.width = "100%"
            button_span_el.style.height = "auto"

            local button_img = message.Document:CreateElement("img")
            button_img:SetAttribute("src", "oval.png")
            button_img.style.width = "100%"
            button_img.style.height = "auto"

            local button_text_el = message.Document:CreateElement("span")
            button_text_el:SetClass("pos", true)
            --button_text_el:SetClass("button_text_top", true)
            button_text_el.style.width = "120%"
            button_text_el.style.position = "absolute"
            button_text_el.style.top = "-50%"
            button_text_el.style.right = "0"
            button_text_el.style["text-align"] = "right"
            button_text_el.inner_rml = ba.XSTR("System Map", 9295)

            if button_el then
                button_el:AddEventListener("click", function(_, _, _)
                    ScpuiSystem:beginSubstate("SystemMap")
                end)
                button_el:AddEventListener("mouseover", function(_, _, _)
                    button_img:SetAttribute("src", "oval-h.png")
                end)
                button_el:AddEventListener("mouseout", function(_, _, _)
                    button_img:SetAttribute("src", "oval.png")
                end)
                button_el:AddEventListener("mousedown", function(_, _, _)
                    button_img:SetAttribute("src", "oval-o.png")
                end)
                button_el:AddEventListener("mouseup", function(_, _, _)
                    button_img:SetAttribute("src", "oval-h.png")
                end)
            end
            local SysMapUtils = require("lib_sysmap_utils")
            --New Sysmap Notification
            if not SysMapUtils:checkNew() then
                new_el:SetClass("hidden", true)
            end

            --They are good children, add them to the family
            button_span_el:AppendChild(button_img)
            button_el:AppendChild(button_text_el)
            button_el:AppendChild(button_span_el)
            cont_el:AppendChild(button_el)
            panel_el:AppendChild(cont_el)
            side_el:AppendChild(panel_el)
            side_el:AppendChild(panel_img)
            wrap_el:AppendChild(new_el)
            wrap_el:AppendChild(side_el)

            local mainbg = ScpuiSystem:getRootParent(message.Document)
            mainbg:InsertBefore(wrap_el, mainbg.first_child)

        end

    end)

    --Rearrange Command Brief to be more text focused
    topics.cmdbriefing.initialize:bind(1, function(message, context)
        local cmd_text_el = message.Document:GetElementById("cmd_text")
        ScpuiSystem:setStyle(cmd_text_el, "margin-left", "9%")
        ScpuiSystem:setStyle(cmd_text_el, "height", "90%")

        local cmd_wrapper_el = message.Document:GetElementById("cmd_wrapper")
        ScpuiSystem:setStyle(cmd_wrapper_el, "width", "90%")
        ScpuiSystem:setStyle(cmd_wrapper_el, "position", "absolute")
        ScpuiSystem:setStyle(cmd_wrapper_el, "top", "5%")

        local cmd_text_window_el = message.Document:GetElementById("cmd_text_window")
        ScpuiSystem:setStyle(cmd_text_window_el, "width", "64%")
        ScpuiSystem:setStyle(cmd_text_window_el, "margin-left", "0%")
        ScpuiSystem:setStyle(cmd_text_window_el, "margin-top", "0%")
        cmd_text_window_el.last_child:SetAttribute("src", "debrief-window.png")

        local cmd_anim_window_el = message.Document:GetElementById("cmd_anim_window")
        ScpuiSystem:setStyle(cmd_anim_window_el, "width", "45%")
        ScpuiSystem:setStyle(cmd_anim_window_el, "position", "absolute")
        ScpuiSystem:setStyle(cmd_anim_window_el, "top", "25%")
        ScpuiSystem:setStyle(cmd_anim_window_el, "right", "-5%")

        local cmd_stage_text_el = message.Document:GetElementById("cmd_stage_text")
        ScpuiSystem:setStyle(cmd_stage_text_el, "width", "60%")

        local stage_select_el = message.Document:GetElementById("stage_select")
        ScpuiSystem:setStyle(stage_select_el, "bottom", "1%")
        ScpuiSystem:setStyle(stage_select_el, "right", "2%")
        ScpuiSystem:setStyle(stage_select_el, "height", "5%")
    end)

    --On Debrief init we load and display the backstock report
    topics.debrief.initialize:bind(1, function(message, context)
        if not mn.isInCampaign() then return end

        if Backstock.active then

            --No report for m3_08
            if mn.getMissionFilename() == "bta2_m3_08" then return end

            local total = 0
            local ds = ""

            for i, v in ipairs(Backstock.missionCP) do
                total = total + v.value

                local tstring = {v.description, v.descID}

                ds = ds .. utils.xstr(tstring) .. ": " .. v.value .. " " .. utils.xstr(Backstock.strings.CP) .. "<br></br>"
            end

            local grandTotal = total + Backstock.current.playerCP

            ds = ds .. utils.xstr(Backstock.strings.Earned) .. total .. " " .. utils.xstr(Backstock.strings.CP) .. "<br></br>"
            ds = ds .. "----------<br></br>"
            ds = ds .. utils.xstr(Backstock.strings.Total) .. grandTotal .. " " .. utils.xstr(Backstock.strings.CP)

            --Will probably move this to it's own div, but for now just append
            if Backstock.newReqs == true then
                ds = ds .. "<br></br><br></br><span class=\"red\">" .. utils.xstr(Backstock.strings.NewReqsAvail) .. "</span>"
            end

            --Create the element
            local rep_el = ScpuiSystem:makeElementPanel(message, "backstock_report", "credits-image-window.png")
            rep_el.style.position = "absolute"
            rep_el.style.top = "10%"
            rep_el.style.right = "4%"
            rep_el.style.width = "30%"
            rep_el.style["text-align"] = "right"
            rep_el.first_child.style.top = "5%"
            rep_el.first_child.style.left = "1%"
            rep_el.first_child.style.width = "90%"
            rep_el.first_child.style.height = "93%"
            rep_el.first_child.style.overflow = "hidden"
            rep_el.first_child.inner_rml = ds

            local mainbg = ScpuiSystem:getRootParent(message.Document)
            mainbg:InsertBefore(rep_el, mainbg.first_child)

            --Also we need to bump the awards div down to make room
            message.Document:GetElementById("awards_wrapper").style.width = "30%"
            message.Document:GetElementById("awards_wrapper").style.top = "50%"
        end
    end)

    --On Debrief accept we sum the playerCP and save it
    --If mission is bta2_m3_06 then we export the current backstock report
    topics.debrief.accept:bind(1, function(message, context)
        Backstock:CompleteBackstock(true)
        if mn.isInCampaign() and mn.getMissionFilename() == "bta2_m3_06" then
            Backstock:saveCurrentToFile()
        end
    end)

    --On Debrief reject we discard the playerCP
    topics.debrief.reject:bind(1, function(message, context)
        Backstock:CompleteBackstock(false)
    end)

    --On Debrief skip we sum the playerCP and save it
    topics.debrief.skip:bind(1, function(message, context)
        Backstock:CompleteBackstock(true)
    end)

    --If the force-credits sexp has been called, abort debriefing and go to the credits
    topics.debrief.skip:bind(9999, function(message, context)
        if ScpuiSystem.ForceCredits then
            ba.print("SCPUI Got command to skip the debriefing and go to credits!\n")
            ScpuiSystem:beginSubstate("Credits")
        end
    end)

    --In BtA 2, conditionally remove the Ion Torch stage
    topics.cmdbriefing.stage:bind(9999, function(message, context)
        if mn.getMissionFilename() == "bta2_m3_05" and message[2] == 3 and mn.isInCampaign() == true then
            --Remove this stage if Ion Torch is not unlocked
            if not tb.WeaponClasses["Ion Torch"].InTechDatabase then
                context.value = nil
            end
        end
    end)

    --For the briefing's map window. Changes to a special version when the map is drawn.
    topics.briefing.brief_bg:bind(9999, function(message, context)
        if message then
            context.value = "brief-main-window.png"
        else
            context.value = "brief-main-window-bta.png"
        end
    end)

    --Lists campaigns with additional data instead of just their name
    topics.campaign.listCampaign:bind(9999, function(message, context)
        --Campaign data to add
        local c_data = {
            ["bta1_d"] = {
                c_type = ba.XSTR("Prologue", 11294),
                c_char = ba.XSTR("Play as an Outlaw Pilot", 11297)
            },
            ["bta1_m"] = {
                c_type = ba.XSTR("Main Story", 11295),
                c_char = ba.XSTR("Play as a GTA Commander", 11298)
            },
            ["bta2_d"] = {
                c_type = ba.XSTR("Prologue", 11294),
                c_char = ba.XSTR("Play as a GTA Commander", 11298)
            },
            ["bta2_m"] = {
                c_type = ba.XSTR("Main Story", 11295),
                c_char = ba.XSTR("Play as a GTA Commander", 11298)
            },
            ["bta-tem_m"] = {
                c_type = ba.XSTR("Side Story", 11296),
                c_char = ba.XSTR("Play as a GTVA Lieutenant", 11299)
            }
        }

        local function createDisplay(campaign)
            local s_name = "<span class=\"campaign_name\">" .. campaign[1] .. "</span>"
            local s_type = "<span class=\"campaign_type\">" .. c_data[campaign[2]].c_type .. "</span>"
            local s_char = "<span class=\"campaign_char\">" .. c_data[campaign[2]].c_char .. "</span>"

            return s_type .. s_name .. s_char
        end

        if c_data[message[2]] then
            context.value = createDisplay(message)
        else
            context.value = message[1]
        end
    end)

    --Hides the tutorial from the main list and creates a unique button for it
    topics.campaign.initialize:bind(1, function(message, context)
        local campaign = nil
        for i, v in ipairs(message.Campaigns_List) do
            if v.Name == "Tutorial" then
                campaign = v
            end
        end

        if campaign == nil then
            -- uh.. that's not right
            return
        end

        --Remove the tutorial from the main list
        campaign.Element.parent_node:RemoveChild(campaign.Element)

        --Make the special Tutorial button area
        local panel_el = ScpuiSystem:makeElementPanel(message, "tutorial_panel", "ops-panel-horz.png")

        local cont_el, button_el = ScpuiSystem:makeButton(
            message,
            "tutorial_cont",
            "tutorial_btn",
            {"tutorial_c", "tutorial", "button_1"},
            "tutorial",
            "diamonds.png",
            "tutorial_type",
            {"pos", "tutorial_text_right"},
            ba.XSTR("Play Tutorial", 11287)
        )

        button_el:SetClass("h1", true)

        cont_el.style.position = "absolute"
        cont_el.style.left = "0"
        cont_el.style.top = "0"

        campaign.Element = button_el

        cont_el:AddEventListener("click", function(_, _, _)
            message:selectCampaign(campaign)
        end)

        panel_el.first_child:AppendChild(cont_el)

        local parent_el = ScpuiSystem:getRootParent(message.Document)
        parent_el:AppendChild(panel_el)
    end)

    --Adds the contextual greyed out lines to the campaign room list
    topics.campaign.initialize:bind(9999, function(message, context)
        local pre_el = message.Document:CreateElement("ul")
        pre_el.id = "context_text"

        local pre_text = message.Document:CreateElement("li")
        pre_text.style.color = "#494949"
        pre_text.inner_rml = ba.XSTR("2335/06 - End of the Great War and the Hades Rebellion", 9296)

        pre_el:AppendChild(pre_text)

        local post_el = message.Document:CreateElement("ul")
        post_el.id = "context_text"

        local post_text = message.Document:CreateElement("li")
        post_text.style.color = "#494949"
        post_text.inner_rml = ba.XSTR("2367/01 - Start of the Second Shivan Incursion", 9297)

        post_el:AppendChild(post_text)

        local parent_el = message.Document:GetElementById("campaignlist")
        parent_el:InsertBefore(pre_el, parent_el.first_child)
        parent_el:AppendChild(post_el)
    end)

    --Colorize campaign descriptions
    topics.campaign.initialize:bind(9999, function(message, context)
        for k, v in pairs(message.Campaigns_List) do
            v.Description = ScpuiSystem:applyKeywordClasses(v.Description)
        end
    end)

    --For the medals UI and making sure the player is always Commander rank
    --Specifically it forces the medal bitmap suffix to "_05"
    topics.medals.setRankBitmap:bind(9999, function(message, context)
        if message[1] == "Rank" then
            context.value = "_05"
        end
    end)

    --Adds the animated background as a hidden element to force librocket to render the
    --background as an animated image unless we're going into bta2_m3_07 or 08. In that case
    --it loads the Taweret or Annwn alt image which is not animated.
    topics.redalert.initialize:bind(9999, function(message, context)
        local backgroundID = ScpuiSystem:getRootParent(message.Document)
        if mn.getMissionFilename() == "bta2_m3_07" or mn.getMissionFilename() == "bta2_m3_08" then
            backgroundID:SetClass(ScpuiSystem:getBackgroundClass(), false)
            if mn.getMissionFilename() == "bta2_m3_07" then
                backgroundID:SetClass("taweret_red_alert_bg", true)
            elseif mn.getMissionFilename() == "bta2_m3_08" then
                backgroundID:SetClass("annwn_red_alert_bg", true)
            end
        else
            local aniEl = message.Document:CreateElement("ani")
            aniEl:SetAttribute("src", "bg-redalert.png")
            backgroundID:AppendChild(aniEl)
            aniEl:SetClass("hidden", true)
        end
    end)

    --Set default countermeasure loadout to an empty array since we just use defaults in red alert
    topics.redalert.initialize:bind(2, function(message, context)
        BtACustomLoadouts["countermeasures"] = {}
    end)

    --For BtA2 M3_07: Hack into the shipsave data for potentially altering it for the red alert
    topics.redalert.initialize:bind(3, function(message, context)
        if mn.getMissionFilename() == "bta2_m3_07" and mn.isInCampaign() then
            btaloadouts:M3_07_load(message)
        end
    end)

    --For BtA2 m3_07: Hack into the shipsave data and save the player's choices for the red alert
    topics.redalert.commit:bind(1, function(message, context)
        if mn.getMissionFilename() == "bta2_m3_07" and mn.isInCampaign() then
            btaloadouts:M3_07_save(message)
        end
    end)

    --Sets the button text for the tech room section buttons
    topics.techroom.initialize:bind(9999, function(message, context)
        message.Document:GetElementById("tech_btn_1").first_child.next_sibling.first_child.inner_rml = ba.XSTR("Technical Database", 9298)
        message.Document:GetElementById("tech_btn_2").first_child.next_sibling.first_child.inner_rml = ba.XSTR("Galaxy Node Map", 9299)
        message.Document:GetElementById("tech_btn_3").first_child.next_sibling.first_child.inner_rml = ba.XSTR("Personnel Database", 11544)
        message.Document:GetElementById("tech_btn_4").first_child.next_sibling.first_child.inner_rml = ba.XSTR("Saved Scan Data", 9301)

        local campaign = ba.getCurrentPlayer():getCampaignFilename()
        --[[if campaign ~= "bta1_m" and campaign ~= "bta2_m" then
            message.Document:GetElementById("tech_btn_3"):SetClass("hidden", true)
        end]]--

        if campaign ~= "bta2_m" then
            message.Document:GetElementById("tech_btn_4"):SetClass("hidden", true)
        end
    end)

    --Sets the second tech room button to our custom state
    topics.techroom.btn2Action:bind(1, function(message, context)
        ScpuiSystem:beginSubstate("NodeMap")
        context.done = true
    end)

    --Sets the third tech room button to our custom state
    topics.techroom.btn3Action:bind(1, function(message, context)
        ScpuiSystem:beginSubstate("Personnel")
        context.done = true
    end)

    --Sets the fourth tech room button to our custom state
    topics.techroom.btn4Action:bind(1, function(message, context)
        ScpuiSystem:beginSubstate("ScanReader")
        context.done = true
    end)

    --Sets up the bonus mission section in the simulator room
    topics.simulator.initialize:bind(1, function(message, context)
        local cont_el, button_el = ScpuiSystem:makeButton(
            message,
            "bullet_cont",
            "bonus_btn",
            {"bullet_c", "bullet", "button_1"},
            "bullet",
            "bullet-r.png",
            "simulator_type",
            {"pos", "button_text_right"},
            ba.XSTR("Bonus Missions", 9302)
        )

        cont_el:AddEventListener("click", function(_, _, _)
            message:change_section(3)
        end)


        local panel_el = message.Document:GetElementById("bot_left_wrapper")
        panel_el:AppendChild(cont_el)

        message.BtaBonusMissions = datasaver:loadDataFromFile("bonusUnlocks", true)

        if message.BtaBonusMissions == nil then
            message.BtaBonusMissions = {}
        end
    end)

    --Hides the campaign filename and filename column header
    topics.simulator.initialize:bind(2, function(message, context)
        message.Document:GetElementById("campaign_file"):SetClass("hidden", true)
        message.Document:GetElementById("column_titles").first_child.next_sibling.next_sibling:SetClass("hidden", true)
    end)

    --Hides the mission filename and adjusts some elements accordingly
    topics.simulator.createitem:bind(2, function(message, context)
        local author_el = message.first_child.next_sibling
        author_el.style.width = "29%"

        local file_el = message.first_child.next_sibling.next_sibling
        file_el:SetClass("hidden", true)
        file_el.style.width = "0%"

        local desc_el = message.first_child.next_sibling.next_sibling.next_sibling
        desc_el.style.width = "47%"
    end)

    --Hides the bonus missions and, optionally, the debug mission from the single missions list
    topics.simulator.listSingle:bind(9999, function(message, context)
        if utils.stringStartsWith(message, "bta1_a") then
            context.value = false
        elseif utils.stringStartsWith(message, "bta2_a") then
          context.value = false
        elseif utils.stringStartsWith(message, "bta_ship_test") then
            if ScpuiSystem.data.ScpuiOptionValues.Verbose_Debugging == "On" then
                context.value = true
            else
                context.value = false
            end
        else
            context.value = true
        end
    end)

    --Builds the bonus missions section
    topics.simulator.newsection:bind(9999, function(message, context)
        if message[2] == "bonus" then
            message[1].Document:GetElementById("campaign_name_wrapper"):SetClass("hidden", true)
            local missionList = ui.TechRoom.SingleMissions
            local i = 0
            local j = 1
            while (i ~= #missionList) do
                if utils.stringStartsWith(missionList[i].Filename, "bta1_a") or utils.stringStartsWith(missionList[i].Filename, "bta2_a") then
                    local filename = missionList[i].Filename
                    filename = filename:gsub("%.fs2", "")
                    local vis = message[1].BtaBonusMissions[filename] or false
                    message[1].Missions_List[j] = {
                        Name = missionList[i].Name,
                        Filename = missionList[i].Filename,
                        Description = missionList[i].Description:gsub("\n", ""),
                        Author = missionList[i].Author,
                        Visible = vis
                    }
                    j = j + 1
                end
                i = i + 1
            end
        end
    end)

    --Returns "bonus" for section index 3
    topics.simulator.sectionname:bind(9999, function(message, context)
        if message == 3 then
            context.value = "bonus"
        end
    end)

    --Disallow ctrl-shift-s for bonus mission section
    topics.simulator.allowall:bind(9999, function(message, context)
        if message.SelectedSection == "bonus" then
            context.value = false
        else
            context.value = true
        end
    end)

    --Account for the Bonus tab when the TAB key is pressed
    topics.simulator.tabkey:bind(9999, function(message, context)
        if message == 2 then
            context.value = 1
        elseif message == 1 then
            context.value = 3
        else
            context.value = 2
        end
    end)

    --Adds the cutscene category to the cutscene item
    topics.cutscenes.addParam:bind(1, function(message, context)
        if not message[1].Visible then
            return
        end
        message[1].category = utils.xstr(utils.parseCustomXSTR(message[2].CustomData["Category"]))
    end)

    --Adds the cutscene thumbnail file to the cutscene item
    topics.cutscenes.addParam:bind(2, function(message, context)
        message[1].thumbnail = message[2].CustomData["Thumbnail"]
    end)

    --Creates the cutscene thumbnail divs
    topics.cutscenes.initialize:bind(9999, function(message, context)
        local thm_el = message.Document:CreateElement("div")
        thm_el.id = "cutscene_thumbnail"
        thm_el.style.position = "absolute"
        thm_el.style.top = "3%"
        thm_el.style.right = "4%"
        thm_el.style.width = "54%"
        thm_el.style.height = "auto"

        local img_el = message.Document:CreateElement("img")
        img_el:SetAttribute("src", "thm_intro.png")
        thm_el:AppendChild(img_el)

        local mainbg = message.Document:GetElementById("cutscene_window_wrapper")
        mainbg:InsertBefore(thm_el, mainbg.first_child)
    end)

    --Hides any cutscene globally that doesn't have a category
    topics.cutscenes.hideMovie:bind(9999, function(message, context)
        if message.category == nil then
            context.value = true
        else
            context.value = false
        end
    end)

    --Creates a cutscene category header if a new category is called for
    topics.cutscenes.createList:bind(9999, function(message, context)
        if message[1].category ~= message[2].category and (message[2].Visible == true or message[1].ShowAll) then
            --new section
            message[1].category = message[2].category
            local list_names_el = message[1].Document:GetElementById("cutscene_list_ul")
            local li_el = message[1].Document:CreateElement("li")
            local div_el = message[1].Document:CreateElement("div")

            div_el.id = "cutscene_heading"
            div_el.style.color = "#494949"
            div_el.style["margin-left"] = "0.1%"
            div_el.inner_rml = message[2].category

            li_el:AppendChild(div_el)
            list_names_el:AppendChild(li_el)
        else
            --same section
        end
    end)

    --Creates the cutscene thumbnail image upon cutscene selection
    topics.cutscenes.selectScene:bind(9999, function(message, context)
        local thm_el = message[1].Document:GetElementById("cutscene_thumbnail")

        local img_el = message[1].Document:CreateElement("img")
        img_el:SetAttribute("src", message[2].thumbnail)
        thm_el:ReplaceChild(img_el, thm_el.first_child)
    end)

    topics.deathpopup.setText:bind(9999, function(message, context)
        if (hv.Text == nil or hv.Text == '') and message.DeathTip then
            context.value = message.DeathTip
        end
    end)

end)()