anchor.diff:      ref :: reference(),
       pid :: undefined | pid(),
       config = maps:new() :: config(),
  +    overlaykeys = [] :: [term()],
       kill_timer :: undefined | timer:tref()
   }).
   
  
positive.code: -export([init/1, callback_mode/0, terminate/3, code_change/4]).
  
  %% state API
  -export([unconfigured/3, configuring/3, batching/3]).
  
  -define(SERVER, ?MODULE).
  -define(HEAPSIZE, 100). %% In MB
  -define(KILL_TIMER, 300000). %% 5 min
  -define(LISTEN_TIMEOUT, 5000). %% 5 secs
  
  -include_lib("stdlib/include/ms_transform.hrl").
  
  
negative.code:     lager:debug("Done applying configuration: ~p", [DeltaConfig]),
      NewConfig = update_config(DeltaConfig, OldConfig),
      Data1 = Data0#data{config = NewConfig},
      ReapplyTimeout = application:get_env(navstar_overlay, reapply_timeout, ?REAPPLY_TIMEOUT),
      {next_state, batching, Data1, {timeout, ReapplyTimeout, reapply}};
  configuring(info, _EventContent, _Data) ->
      {keep_state_and_data, postpone}.
              
  batching(info, EventContent, _Data) ->
      {keep_state_and_data, {timeout, ?LISTEN_TIMEOUT, {do_configure, EventContent}}};
  batching(timeout, {do_configure, EventContent}, Data) ->
      {next_state, configuring, Data, {next_event, internal, EventContent}};
  batching(timeout, reapply, Data) ->
      {next_state , reapplying, Data, {next_event, internal, reapply}}.
  
  reapplying(internal, reapply, Data0 = #data{config = Config, overlaykeys = OverlayKeys}) ->
      AllKeys = maps:keys(Config),
      RemainingKeys = ordsets:to_list(ordsets:subtract(ordsets:from_list(AllKeys), ordsets:from_list(OverlayKeys))),
      case RemainingKeys of
          [] ->
              Data1 = Data0#data{overlaykeys = []},
              ReapplyTimeout = application:get_env(navstar_overlay, reapply_timeout, ?REAPPLY_TIMEOUT), 
              {next_state, batching, Data1, {timeout, ReapplyTimeout, reapply}};
          [Key|_] ->
              Value = maps:get(Key, Config),
              DeltaConfig = #{key => Key, value => Value},
              lager:debug("Reapplying config ~p~n", [DeltaConfig]),
              {ok, Timer} = timer:kill_after(?KILL_TIMER),
              navstar_overlay_configure:start_link(DeltaConfig),
              Data1 = Data0#data{kill_timer = Timer},
              {keep_state, Data1}
      end;
  reapplying(info, {navstar_overlay_configure, applied_config, DeltaConfig = #{key := Key}},
             Data0 = #data{kill_timer = Timer, overlaykeys = OverlayKeys0}) ->
      timer:cancel(Timer),
      lager:debug("Done reapplying config ~p~n", [DeltaConfig]),
      OverlayKeys1 = [Key|OverlayKeys0],
      Data1 = Data0#data{overlaykeys = OverlayKeys1},
      {next_state, reapplying, Data1, {next_event, internal, reapply}};
  reapplying(info, _EventContent, _Data) ->
      {keep_state_and_data, postpone}.
  
  %% private API
  
  