-module(sprocket@socket). -compile([no_auto_import, nowarn_unused_vars]). -export([new/1, reset_for_render/1, fetch_or_init_hook/2, update_hook/3, push_event_handler/2, get_event_handler/2]). -export_type([event_handler/0, updater/1, component_wip/0, socket/0]). -type event_handler() :: {event_handler, sprocket@internal@utils@unique:unique(), sprocket@internal@identifiable_callback:callback_fn()}. -type updater(JRB) :: {updater, fun((JRB) -> {ok, nil} | {error, nil})}. -type component_wip() :: {component_wip, sprocket@internal@utils@ordered_map:ordered_map(integer(), sprocket@hooks:hook()), integer()}. -type socket() :: {socket, component_wip(), list(event_handler()), gleam@option:option(gleam@erlang@process:subject(glisten@handler:handler_message())), fun(() -> nil)}. -spec new( gleam@option:option(gleam@erlang@process:subject(glisten@handler:handler_message())) ) -> socket(). new(Ws) -> {socket, {component_wip, sprocket@internal@utils@ordered_map:new(), 0}, [], Ws, fun() -> nil end}. -spec reset_for_render(socket()) -> socket(). reset_for_render(Socket) -> erlang:setelement(3, Socket, []). -spec fetch_or_init_hook(socket(), fun(() -> sprocket@hooks:hook())) -> {socket(), sprocket@hooks:hook(), integer()}. fetch_or_init_hook(Socket, Init) -> Index = erlang:element(3, erlang:element(2, Socket)), Hooks = erlang:element(2, erlang:element(2, Socket)), case sprocket@internal@utils@ordered_map:get(Hooks, Index) of {ok, Hook} -> {erlang:setelement( 2, Socket, erlang:setelement(3, erlang:element(2, Socket), Index + 1) ), Hook, Index}; {error, nil} -> Hook@1 = Init(), {erlang:setelement( 2, Socket, {component_wip, sprocket@internal@utils@ordered_map:insert( erlang:element(2, erlang:element(2, Socket)), Index, Hook@1 ), Index + 1} ), Hook@1, Index} end. -spec update_hook(socket(), sprocket@hooks:hook(), integer()) -> socket(). update_hook(Socket, Hook, Index) -> erlang:setelement( 2, Socket, erlang:setelement( 2, erlang:element(2, Socket), sprocket@internal@utils@ordered_map:update( erlang:element(2, erlang:element(2, Socket)), Index, Hook ) ) ). -spec push_event_handler( socket(), sprocket@internal@identifiable_callback:identifiable_callback() ) -> {socket(), sprocket@internal@utils@unique:unique()}. push_event_handler(Socket, Identifiable_cb) -> {identifiable_callback, Id, Cb} = Identifiable_cb, {erlang:setelement( 3, Socket, [{event_handler, Id, Cb} | erlang:element(3, Socket)] ), Id}. -spec get_event_handler(socket(), sprocket@internal@utils@unique:unique()) -> {socket(), {ok, event_handler()} | {error, nil}}. get_event_handler(Socket, Id) -> Handler = gleam@list:find( erlang:element(3, Socket), fun(H) -> {event_handler, I, _} = H, I =:= Id end ), {Socket, Handler}.