src/lightspeed@navigation.erl

-module(lightspeed@navigation).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/lightspeed/navigation.gleam").
-export([plan/4, mode/1, boundary/1, instructions/1, mode_label/1, boundary_label/1]).
-export_type([navigation_mode/0, mount_boundary/0, navigation_plan/1]).

-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.

?MODULEDOC(" LiveView-style navigation compatibility planner.\n").

-type navigation_mode() :: live_patch | live_navigate.

-type mount_boundary() :: preserve_mount | remount.

-type navigation_plan(LPO) :: {navigation_plan,
        navigation_mode(),
        mount_boundary(),
        lightspeed@router:route_match(LPO),
        lightspeed@router:route_match(LPO),
        list(lightspeed@agent@isa:instruction())}.

-file("src/lightspeed/navigation.gleam", 102).
-spec route_view_id(lightspeed@router:route_match(any())) -> binary().
route_view_id(Route_match) ->
    case Route_match of
        {found, Matched} ->
            erlang:element(4, Matched);

        {not_found, _, View_id} ->
            View_id
    end.

-file("src/lightspeed/navigation.gleam", 95).
-spec same_mount_boundary(
    lightspeed@router:route_match(LPZ),
    lightspeed@router:route_match(LPZ)
) -> boolean().
same_mount_boundary(Current, Next) ->
    route_view_id(Current) =:= route_view_id(Next).

-file("src/lightspeed/navigation.gleam", 109).
-spec route_path(lightspeed@router:route_match(any())) -> binary().
route_path(Route_match) ->
    case Route_match of
        {found, Matched} ->
            erlang:element(2, Matched);

        {not_found, Path, _} ->
            Path
    end.

-file("src/lightspeed/navigation.gleam", 30).
?DOC(" Plan one route transition using LiveView-compatible navigation semantics.\n").
-spec plan(lightspeed@router:router(LPP), binary(), binary(), binary()) -> navigation_plan(LPP).
plan(Table, Current_path, Target_path, Csrf_token) ->
    Current = lightspeed@router:resolve(Table, Current_path),
    Next = lightspeed@router:resolve(Table, Target_path),
    Next_path = route_path(Next),
    case same_mount_boundary(Current, Next) of
        true ->
            {navigation_plan,
                live_patch,
                preserve_mount,
                Current,
                Next,
                [{navigate, Next_path}]};

        false ->
            {navigation_plan,
                live_navigate,
                remount,
                Current,
                Next,
                [{navigate, Next_path} |
                    lightspeed@router:mount_instructions(Next, Csrf_token)]}
    end.

-file("src/lightspeed/navigation.gleam", 65).
?DOC(" Planned mode.\n").
-spec mode(navigation_plan(any())) -> navigation_mode().
mode(Plan) ->
    erlang:element(2, Plan).

-file("src/lightspeed/navigation.gleam", 70).
?DOC(" Planned mount boundary.\n").
-spec boundary(navigation_plan(any())) -> mount_boundary().
boundary(Plan) ->
    erlang:element(3, Plan).

-file("src/lightspeed/navigation.gleam", 75).
?DOC(" Planned route instructions in emit order.\n").
-spec instructions(navigation_plan(any())) -> list(lightspeed@agent@isa:instruction()).
instructions(Plan) ->
    erlang:element(6, Plan).

-file("src/lightspeed/navigation.gleam", 80).
?DOC(" Stable mode string for logs and fixtures.\n").
-spec mode_label(navigation_mode()) -> binary().
mode_label(Mode) ->
    case Mode of
        live_patch ->
            <<"patch"/utf8>>;

        live_navigate ->
            <<"navigate"/utf8>>
    end.

-file("src/lightspeed/navigation.gleam", 88).
?DOC(" Stable mount boundary string for logs and fixtures.\n").
-spec boundary_label(mount_boundary()) -> binary().
boundary_label(Boundary) ->
    case Boundary of
        preserve_mount ->
            <<"preserve_mount"/utf8>>;

        remount ->
            <<"remount"/utf8>>
    end.