-module(code_lock).
-behaviour(gen_fsm).

-export([init/1, button/1, locked/2, open/2]).

-export([start/1, handle_event/3, handle_sync_event/4, handle_info/3,
         terminate/3, code_change/4]).

handle_event(_Event, StateName, State) ->
    {next_state, StateName, State}.

handle_sync_event(_Event, _From, StateName, State) ->
    Reply = ok,
    {reply, Reply, StateName, State}.

handle_info(_Info, StateName, State) ->
    {next_state, StateName, State}.

terminate(_Reason, _StateName, _State) ->
    ok.

code_change(_OldVsn, StateName, State, _Extra) ->
    {ok, StateName, State}.

start(Code) ->
    gen_fsm:start({local, code_lock}, code_lock, Code, []).

button(Digit) ->
    gen_fsm:send_event(code_lock, {button, Digit}).

init(Code) ->
    {ok, locked, {[], Code}}.

locked({button, 9}, {SoFar, Code}) ->
    9/0,
    {next_state, locked, {SoFar, Code}};
locked({button, Digit}, {SoFar, Code}) ->
    case [Digit|SoFar] of
        Code ->
            do_unlock(),
            {next_state, open, {[], Code}, 3000};
        Incomplete when length(Incomplete)<length(Code) ->
            {next_state, locked, {Incomplete, Code}};
        _Wrong ->
            {next_state, locked, {[], Code}}
    end.

open(timeout, State) ->
    do_lock(),
    {next_state, locked, State}.

do_lock() ->
    io:format("~nI am a locked lock.~n").

do_unlock() ->
    io:format("~nI am an unlocked lock.~n").
