local basalt = require("/lib/basalt")

config = {}
if fs.exists("config.json") then
    
    local config_file = fs.open("/config.json","r")
    local config_text = config_file.readAll()
    config = textutils.unserialiseJSON(config_text)
    config_file.close()
    
end

if config.password then

    while true do

        if config.password == "" then
            break
        end

        term.setCursorPos(1, 1) 
        term.clear()
        print("This device requires a password to start.")
        write("Password: ")
        local msg = read()

        if msg == config.password then
            break
        else
            print("Incorrect!")
            sleep(1)
        end

    end
end

local main = basalt.getMainFrame()

local FRAME_WIDTH = 26
local FRAME_HEIGHT = 19
local CONTROL_BUTTON_Y = 20 

local homescreen = main:addFrame()
    :setPosition(1, 1)
    :setSize(FRAME_WIDTH, FRAME_HEIGHT)
    :setBackground(colours.blue)
    :setVisible(true) 

if config.wallpaperColour then
    homescreen:setBackground(colours[config.wallpaperColour])
end

local active_app_frames = {}
local current_active_frame = homescreen 

local app_switcher_frame = main:addFrame()
    :setPosition(1, 1)
    :setSize(FRAME_WIDTH, FRAME_HEIGHT)
    :setBackground(colours.brown)
    :setVisible(false) 

function show_payment_confirmation(amount, purpose, callback)

    local payment_confirmation_frame = main:addFrame()
        :setPosition(1, 1) 
        :setSize(FRAME_WIDTH, FRAME_HEIGHT / 3) 
        :setBackground(colours.black) 
    payment_confirmation_frame.z = 99
    payment_confirmation_frame.focused = true

    payment_confirmation_frame:addLabel()
        :setText("Confirm Payment") 
        :setForeground(colours.white) 

    payment_confirmation_frame:addLabel()
        :setPosition(1, 3) 
        :setText(amount .. "G -> " .. purpose) 
        :setForeground(colours.white) 

    payment_confirmation_frame:addButton()
        :setText("Confirm") 
        :setPosition(1, 6) 
        :setSize(13, 1) 
        :setBackground(colours.green) 

        :onClick(function()
            if callback then
                callback(true)
            end
            payment_confirmation_frame:destroy()
        end)

    payment_confirmation_frame:addButton()
        :setText("Deny") 
        :setPosition(14, 6) 
        :setSize(13, 1) 
        :setBackground(colours.red) 

        :onClick(function()

            if callback then
                callback(false)
            end

            payment_confirmation_frame:destroy()
        end)
        sleep(0.01)
end

local function payment_listener()
    local modem = peripheral.find("modem")
    local lchannel = tonumber(os.getComputerID() .. 43)
    modem.open(lchannel)
    while true do

        local event, side, channel, replyChannel, message, distance
        repeat
        event, side, channel, replyChannel, message, distance = os.pullEvent("modem_message")
        until channel == lchannel

        local payload = textutils.unserialiseJSON(message)
        if payload.type == "confirmTransaction" then
            show_payment_confirmation(payload.amount, payload.vendor,function(bruh)
                if bruh then

                    local confirmation_payload = {
                        type = "transactionConfirmation",
                        transaction_id = payload.transaction_id,
                        confirmed = true
                    }

                    modem.transmit(replyChannel,channel,textutils.serialiseJSON(confirmation_payload))

                else

                    local confirmation_payload = {
                        type = "transactionConfirmation",
                        transaction_id = payload.transaction_id,
                        confirmed = false
                    }

                    modem.transmit(replyChannel,channel,textutils.serialiseJSON(confirmation_payload))

                end
            end)

        end

    end

end

local function populate_homescreen_buttons()

    homescreen:clear()

    local button_width = 11
    local button_height = 3
    local button_spacing_x = 2
    local button_spacing_y = 2
    local current_x = button_spacing_x
    local current_y = button_spacing_y

    local app_files = fs.list("/apps/")

    for i = 1, #app_files do
        local filename = app_files[i]

        local display_name = filename:gsub(".lua$", "")

        if current_x + button_width > homescreen:getWidth() then
            current_x = button_spacing_x 
            current_y = current_y + button_height + button_spacing_y 
        end

        if current_y + button_height > homescreen:getHeight() then
            break
        end
        
        local app_button = homescreen:addButton()
            :setText(display_name) 
            :setPosition(current_x, current_y)
            :setSize(button_width, button_height)
            :setBackground(colours.grey)
            :setForeground(colours.white)
            :onClick(function()

                if current_active_frame then
                    current_active_frame:setVisible(false)
                end

                local app_frame = active_app_frames[filename]
                if not app_frame then

                    app_frame = main:addFrame()
                        :setPosition(1, 1) 
                        :setSize(FRAME_WIDTH, FRAME_HEIGHT)
                        :setBackground(colours.green) 
                        :setVisible(false) 

                    app_frame:addProgram()
                        :setSize(FRAME_WIDTH, FRAME_HEIGHT)
                        :execute("/apps/" .. filename)

                    active_app_frames[filename] = app_frame
                end

                app_frame:setVisible(true)
                current_active_frame = app_frame
            end)

        current_x = current_x + button_width + button_spacing_x
    end
end

local function switch_to_frame(target_frame, frame_name)
    if current_active_frame then
        current_active_frame:setVisible(false)
    end
    target_frame:setVisible(true)
    current_active_frame = target_frame
end

local function populate_app_switcher_ui()
    app_switcher_frame:clear() 

    app_switcher_frame:addLabel()
        :setText("Active Applications")
        :setPosition(5, 1)
        :setSize(FRAME_WIDTH - 2, 1)
        :setForeground(colours.white)
        :setBackground(colours.blue)

    local current_y = 3 

    app_switcher_frame:addButton()
        :setText("Home Screen")
        :setPosition(2, current_y)
        :setSize(FRAME_WIDTH - 3, 1)
        :setBackground(homescreen == current_active_frame and colours.lightGrey or colours.grey) 
        :setForeground(colours.white)
        :onClick(function()
            switch_to_frame(homescreen, "Home Screen")
            app_switcher_frame:setVisible(false) 
        end)
    current_y = current_y + 2

    for filename, app_frame in pairs(active_app_frames) do

        local display_name = filename:gsub(".lua$", "")

        if current_y + 1 > app_switcher_frame:getHeight() - 2 then 
            app_switcher_frame:addLabel()
                :setText("...more apps below...")
                :setPosition(1, current_y)
                :setSize(FRAME_WIDTH - 2, 1)
                :setForeground(colours.orange)
                :setBackground(colours.black)
            break
        end

        app_switcher_frame:addButton()
            :setText(display_name) 
            :setPosition(2, current_y)
            :setSize(FRAME_WIDTH - 8, 1) 
            :setBackground(app_frame == current_active_frame and colours.lightGrey or colours.grey) 
            :setForeground(colours.white)
            :onClick(function()
                switch_to_frame(app_frame, filename)
                app_switcher_frame:setVisible(false) 
            end)

        app_switcher_frame:addButton()
            :setText("X")
            :setPosition(FRAME_WIDTH - 6, current_y)
            :setSize(5, 1)
            :setBackground(colours.red)
            :setForeground(colours.white)
            :onClick(function()

                if app_frame then
                    app_frame:destroy()
                end
                active_app_frames[filename] = nil 

                if current_active_frame == app_frame then
                    switch_to_frame(homescreen, "Home Screen (after close)")
                end

                populate_app_switcher_ui()
            end)
        current_y = current_y + 2
    end
end

populate_homescreen_buttons()

main:addButton()
    :setText("Home")
    :setPosition(0, CONTROL_BUTTON_Y)
    :setSize(14, 1)
    :setBackground(colours.black)
    :setForeground(colours.white)
    :onClick(function()
        populate_homescreen_buttons() 
        if current_active_frame ~= homescreen or app_switcher_frame.visible == true then
            app_switcher_frame:setVisible(false) 
            switch_to_frame(homescreen, "Home Screen")
        end
    end)

main:addButton()
    :setText("Switch")
    :setPosition(14, CONTROL_BUTTON_Y)
    :setSize(13, 1)
    :setBackground(colours.red)
    :setForeground(colours.white)
    :onClick(function()

        if current_active_frame then
            current_active_frame:setVisible(false)
        end
        populate_app_switcher_ui() 
        app_switcher_frame:setVisible(true)
    end)

parallel.waitForAny(basalt.run,payment_listener)