package it.playfellas.superapp.activities.slave;

import com.squareup.otto.Subscribe;

import java.util.Timer;
import java.util.TimerTask;

import it.playfellas.superapp.events.EventFactory;
import it.playfellas.superapp.events.game.RTTUpdateEvent;
import it.playfellas.superapp.logic.Config;
import it.playfellas.superapp.logic.slave.SlaveController;
import it.playfellas.superapp.logic.tiles.Tile;
import it.playfellas.superapp.network.TenBus;

/**
 * Created by affo on 04/08/15.
 * <p/>
 * A `TileDisposer` posts `NewTileEvent`s basing on the current rtt.
 * It subscribes to `RTTUpdateEvent`s and reacts internally to the changes in RTT.
 * It lefts the decision to really post a `NewTileEvent` to implementors
 * leaving `shouldIStayOrShouldISpawn` method abstract (random boolean?).
 * <p/>
 * A `TileDisposer`, after instantiation, has to be started (`start` method),
 * and it should be stopped (`stop` method) when unused.
 */
public abstract class TileDisposer {
    private SlaveController sc;
    private int tileDensity;
    private float baseRtt;

    private Timer tilePoser;

    private Object busListener;

    public TileDisposer(final SlaveController sc, final Config conf) {
        super();
        this.sc = sc;
        this.tileDensity = conf.getTileDensity();
        this.baseRtt = conf.getDefaultRtt();
        this.tilePoser = new Timer();
        this.busListener = new Object() {
            @Subscribe
            public void onRttUpdate(RTTUpdateEvent e) {
                reschedule(e.getRtt());
            }
        };
    }

    private TimerTask getSpawnTask(){
        return new TimerTask() {
            @Override
            public void run() {
                newTile();
            }
        };
    }

    private void reschedule(float rttInSeconds) {
        tilePoser.purge();

        long rtt = (long) (rttInSeconds * 1000); // from s to ms
        tilePoser.schedule(getSpawnTask(), rtt / tileDensity, rtt / tileDensity);
    }

    private void newTile() {
        if (shouldIStayOrShouldISpawn()) {
            Tile t = sc.getTile();
            TenBus.get().post(EventFactory.newTile(t));
        }
    }

    protected abstract boolean shouldIStayOrShouldISpawn();

    public void start() {
        reschedule(baseRtt);
        TenBus.get().register(busListener);
    }

    public void stop() {
        tilePoser.purge();
        tilePoser.cancel();
    }
}

@@ -1803,29 +1803,91 @@
   tilePoser.
-purge
+cancel();%0A        tilePoser.purge();%0A%0A        tilePoser = new Timer
 ();%0A%0A       
@@ -2419,29 +2419,30 @@
   tilePoser.
-purge
+cancel
 ();%0A        
@@ -2443,34 +2443,33 @@
       tilePoser.
-cancel
+purge
 ();%0A    %7D%0A%7D%0A

Fix in tileDisposer timer. Purge removes "canceled" tasks. Every time reschedule is invoked we have to: cancel the timer (it becomes unusable); purge it (for garbage collection); rectreate timer; schedule new task.