% Autogenerated with DRAKON Editor 1.31

-module(code_door).
-behaviour(gen_fsm).
-export([locked/2]).
-export([open/2]).
-export([opening/2]).
-export([start_link/2]).
-export([cancel/1, code_change/4, create/1, handle_event/3, handle_info/3, handle_sync_event/4, init/1, key/2, stop/1, terminate/3]).
% The timeout between two button clicks - 10 sec.
-define(TIMEOUT1, 5000).

% The timeout while the door remains open - 30 sec.
-define(TIMEOUT2, 10000).

cancel(Name) ->
    % item 107
    gen_fsm:send_event(Name, cancel)
.

cancelled() ->
    % item 82
    io:fwrite("Cancel pressed.~n", [])
.

code_change(_OldVsn, StateName, StateData, _Extra) ->
    % item 147
    {ok, StateName, StateData}
.

create(Code) ->
    % item 94
    AlreadyTyped = [],
    State = {AlreadyTyped, Code},
    % item 95
    Options = [],
    % item 93
    start_link(State, Options)
.

do_lock() ->
    % item 78
    io:fwrite("The door is locked.~n", [])
.

do_open() ->
    % item 74
    io:fwrite("The door is opened.~n", [])
.

handle_event(stop, _StateName, StateData) ->
    % item 120
    {stop, normal, StateData}
.

handle_info(_Info, StateName, StateData) ->
    % item 153
    {next_state, StateName, StateData}
.

handle_sync_event(_Event, _From, StateName, StateData) ->
    % item 159
    {next_state, StateName, StateData}
.

init(State) ->
    % item 137
    io:fwrite("init!~n", []),
    % item 136
    {ok, locked, State}
.

key(Name, Key) ->
    % item 101
    gen_fsm:send_event(Name, {button, Key})
.

report_key(Key) ->
    % item 70
    io:fwrite("key: ~s~n", [Key])
.

stop(Name) ->
    % item 126
    gen_fsm:send_all_state_event(Name, stop)
.

terminate(normal, _StateName, _StateData) ->
    % item 114
    io:fwrite("Code door: terminating.~n", []),
    % item 113
    ok
.

timeout_hit() ->
    % item 86
    io:fwrite("Timeout reached.~n", [])
.
locked(Message_, State) ->
    case Message_ of
    {button, Key} ->
        % item 64
        report_key(Key),
        % item 49
        {_, Code} = State,
        % item 45
        {next_state, opening, {Key, Code}, ?TIMEOUT1}
    ;
    _ ->
        % item 46
        {next_state, locked, State}
    end
.
open(Message_, State) ->
    case Message_ of
    timeout ->
        % item 61
        timeout_hit(),
        % item 62
        do_lock(),
        % item 53
        {next_state, locked, State}
    ;
    dummy ->
        % item 62
        do_lock(),
        % item 53
        {next_state, locked, State}
    ;
    _ ->
        % item 54
        {next_state, open, State}
    end
.
opening(Message_, State) ->
    case Message_ of
    {button, Key} ->
        % item 63
        report_key(Key),
        % item 47
        {SoFar, Code} = State,
        Typed = SoFar ++ Key,
        % item 41
        case Typed =:= Code of true -> 
            % item 57
            do_open(),
            % item 50
            {next_state, open, {[], Code}, ?TIMEOUT2}
        ; false ->
            % item 48
            {next_state, opening, {Typed, Code}, ?TIMEOUT1}
        end
    ;
    cancel ->
        % item 58
        cancelled(),
        % item 59
        do_lock(),
        % item 51
        {next_state, locked, State}
    ;
    timeout ->
        % item 60
        timeout_hit(),
        % item 59
        do_lock(),
        % item 51
        {next_state, locked, State}
    ;
    _ ->
        throw({invalid_state, "Message not supported by state 'opening'."})
    end
.


start_link(State, Options) ->
    gen_fsm:start_link(?MODULE, State, Options).



