-module(sprocket@context). -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, context/0]). -type event_handler() :: {event_handler, sprocket@internal@utils@unique:unique(), sprocket@internal@identifiable_callback:callback_fn()}. -type updater(JXZ) :: {updater, fun((JXZ) -> {ok, nil} | {error, nil})}. -type component_wip() :: {component_wip, sprocket@internal@utils@ordered_map:ordered_map(integer(), sprocket@hooks:hook()), integer(), boolean()}. -type context() :: {context, component_wip(), list(event_handler()), gleam@option:option(gleam@erlang@process:subject(glisten@handler:handler_message())), fun(() -> nil), fun((sprocket@internal@utils@unique:unique(), fun((sprocket@hooks:hook()) -> sprocket@hooks:hook())) -> nil)}. -spec new( gleam@option:option(gleam@erlang@process:subject(glisten@handler:handler_message())) ) -> context(). new(Ws) -> {context, {component_wip, sprocket@internal@utils@ordered_map:new(), 0, true}, [], Ws, fun() -> nil end, fun(_, _) -> nil end}. -spec reset_for_render(context()) -> context(). reset_for_render(Ctx) -> erlang:setelement(3, Ctx, []). -spec fetch_or_init_hook(context(), fun(() -> sprocket@hooks:hook())) -> {context(), sprocket@hooks:hook(), integer()}. fetch_or_init_hook(Ctx, Init) -> Index = erlang:element(3, erlang:element(2, Ctx)), Hooks = erlang:element(2, erlang:element(2, Ctx)), case sprocket@internal@utils@ordered_map:get(Hooks, Index) of {ok, Hook} -> {erlang:setelement( 2, Ctx, erlang:setelement(3, erlang:element(2, Ctx), Index + 1) ), Hook, Index}; {error, nil} -> case erlang:element(4, erlang:element(2, Ctx)) of true -> nil; false -> sprocket@internal@logger:error( <<<<" Hook not found for index: "/utf8, (gleam@int:to_string(Index))/binary>>/binary, ". This indicates a hook was dynamically created since first render which is not allowed. "/utf8>> ), erlang:error(#{gleam_error => panic, message => <<"panic expression evaluated"/utf8>>, module => <<"sprocket/context"/utf8>>, function => <<"fetch_or_init_hook"/utf8>>, line => 84}) end, Hook@1 = Init(), {erlang:setelement( 2, Ctx, {component_wip, sprocket@internal@utils@ordered_map:insert( erlang:element(2, erlang:element(2, Ctx)), Index, Hook@1 ), Index + 1, erlang:element(4, erlang:element(2, Ctx))} ), Hook@1, Index} end. -spec update_hook(context(), sprocket@hooks:hook(), integer()) -> context(). update_hook(Ctx, Hook, Index) -> erlang:setelement( 2, Ctx, erlang:setelement( 2, erlang:element(2, Ctx), sprocket@internal@utils@ordered_map:update( erlang:element(2, erlang:element(2, Ctx)), Index, Hook ) ) ). -spec push_event_handler( context(), sprocket@internal@identifiable_callback:identifiable_callback() ) -> {context(), sprocket@internal@utils@unique:unique()}. push_event_handler(Ctx, Identifiable_cb) -> {identifiable_callback, Id, Cb} = Identifiable_cb, {erlang:setelement( 3, Ctx, [{event_handler, Id, Cb} | erlang:element(3, Ctx)] ), Id}. -spec get_event_handler(context(), sprocket@internal@utils@unique:unique()) -> {context(), {ok, event_handler()} | {error, nil}}. get_event_handler(Ctx, Id) -> Handler = gleam@list:find( erlang:element(3, Ctx), fun(H) -> {event_handler, I, _} = H, I =:= Id end ), {Ctx, Handler}.