local hostname = "redstone_toggle" .. os.getComputerID()

function dump(o)
    if o == nil then
        return ""
    end

    if type(o) == 'table' then
        local s = '{ '
        for k,v in pairs(o) do
            if type(k) ~= 'number' then k = '"'..k..'"' end
            s = s .. '['..k..'] = ' .. dump(v) .. ','
        end
        return s .. '} '
    end

    return tostring(o)
end

function recv()
    local master = rednet.lookup("rmm", "master")
    while true do
        local event, id, data = os.pullEvent()
        if event == "rednet_message" then
            print(id .. " (" .. event .. ")> " .. dump(data))
            if type(data) == 'table' then
                if data[1] == 'eval' then
                    local cmd_fn, err = loadstring(data[2])
                    if not cmd_fn then
                        print("Failed to compile '" .. data[2] .. "': " .. err)
                        rednet.send(master, "Failed to compile '" .. data[2] .. "': " .. err)
                    else
                        local success, output = pcall(cmd_fn)
                        if success then
                            if output then
                                print("Command output from '" .. data[2] .. "': " .. dump(output))
                                rednet.send(master, "Command output from '" .. data[2] .. "': " .. dump(output))
                            else
                                print("There is no command output from '" .. data[2] .. "'")
                                rednet.send(master, "There is no command output from '" .. data[2] .. "'")
                            end
                        else
                            print("Runtime error: " .. output)
                            rednet.send(master, "Runtime error: " .. output)
                        end
                    end
                end
            elseif type(data) == 'string' then
                if data == 'ping' then
                    print("Pong!")
                    rednet.send(master, "Pong!")
                elseif data == 'toggle' then
                    output_state = !output_state
                    redstone.setOutput("back", output_state)
                    print("Toggled output to: " .. output_state)
                    rednet.send(master, "Toggled output to: " .. output_state)
                end
            end
        end
    end
end

function lever_input()
    while true do
        local new_lever_state = redstone.getInput("top")
        if new_lever_state != lever_state then
            lever_state = new_lever_state
            output_state = !output_state
            redstone.setOutput("back", output_state)
        end
        sleep(1)
    end
end

local output_state = redstone.getInput("back")
local lever_state = redstone.getInput("top")

local sides = peripheral.getNames()
for i = 1, #sides do
    if peripheral.getType(sides[i]) == "modem" then
        modemSide = sides[i]
        break
    end
end

rednet.open(modemSide)
rednet.host("rmm", hostname)

parallel.waitForAny(recv, lever_input)

rednet.close(modemSide)