a cabal implementation in erlang
-module(cabal_transport_sup).
-behaviour(supervisor).

-export([start_link/1, get_transport_pid/1]).
-export([init/1]).

%% Retrieve the transport worker PID from the supervisor
get_transport_pid(SupPid) ->
    Children = supervisor:which_children(SupPid),
    case lists:keyfind(cabal_transport, 1, Children) of
        {cabal_transport, Pid, _, _} when is_pid(Pid) -> {ok, Pid};
        _ -> {error, not_found}
    end.

%% Start the transport supervisor with configuration
%% This uses a two-phase approach:
%% 1. Start supervisor with transport child
%% 2. Dynamically add cabal_accept_worker once we have transport PID
start_link(Args) ->
    case supervisor:start_link(?MODULE, {phase1, Args}) of
        {ok, SupPid} ->
            %% Get the transport PID from the supervisor's children
            Children = supervisor:which_children(SupPid),
            Transport = lists:keyfind(cabal_transport, 1, Children),
            {cabal_transport, TransportPid, worker, [cabal_transport]} = Transport,

            %% Now start cabal_accept_worker with the transport PID
            AcceptWorkerSpec = #{
                id => cabal_accept_worker,
                start => {
                    cabal_accept_worker,
                    start_link,
                    [
                        [{transport_pid, TransportPid}]
                    ]
                },
                restart => permanent,
                shutdown => 5000,
                type => worker,
                modules => [cabal_accept_worker]
            },
            {ok, _AcceptWorkerPid} = supervisor:start_child(SupPid, AcceptWorkerSpec),

            {ok, SupPid};
        Error ->
            Error
    end.

%% Supervisor callback
init({phase1, Args}) ->
    %% Phase 1: Start only transport
    %% Accept worker will be added dynamically once we have transport PID

    %% Extract configuration
    ListenAddr = proplists:get_value(listen_addr, Args),
    KeyPair = proplists:get_value(key_pair, Args),
    EventHandler = proplists:get_value(event_handler, Args),

    %% rest_for_one strategy:
    %% - Transport starts first
    %% - Accept worker starts second (depends on transport for listener info)
    %% - If transport crashes, cabal_accept_worker restarts too (correct: listener is gone)
    %% - If cabal_accept_worker crashes, transport keeps running (correct: just restart accept loop)
    SupFlags = #{
        strategy => rest_for_one,
        intensity => 5,
        period => 10
    },

    %% Start transport first
    TransportSpec = #{
        id => cabal_transport,
        start =>
            {cabal_transport, start_link, [
                [
                    {listen_addr, ListenAddr},
                    {key_pair, KeyPair},
                    {event_handler, EventHandler}
                ]
            ]},
        restart => permanent,
        shutdown => 5000,
        type => worker,
        modules => [cabal_transport]
    },

    {ok, {SupFlags, [TransportSpec]}}.