// Path: Source/src/de/tum/in/www1/jReto/module/api/Address.java
// public interface Address {
//     /** 
//     * Called to establish a new outgoing connection.
//     * @return A new connection to the peer.
//     */
// 	Connection createConnection();
// 	/** The cost of an address gives an heuristic about which Address should be used if multiple are available. Lower cost is preferred. An WlanAddress uses a cost of 10. */ 
// 	int getCost();
// }
// 
// Path: Source/src/de/tum/in/www1/jReto/module/api/Browser.java
// public interface Browser {
// 	/**
// 	* The Browser.Handler interface allows an implementation of the Browser protocol to inform it's delegate about various events.
// 	*/
// 	public static interface Handler {
// 	    /** Called when the Browser started to browse. */
// 		void onBrowsingStarted(Browser browser);
// 	    /** Called when the Browser stopped to browse. */
// 		void onBrowsingStopped(Browser browser, Object error);
// 	    /** Called when the Browser discovered an address. */
// 		void onAddressDiscovered(Browser browser, Address address, UUID identifier);
// 	    /** Called when the Browser lost an address, i.e. when that address becomes invalid for any reason. */
// 		void onAddressRemoved(Browser browser, Address address, UUID identifier);
// 	}
// 	
//     /** Sets the Browser's delegate */
// 	void setBrowserHandler(Handler handler);
//     /** The Browser's delegate */
// 	Handler getBrowserHandler();
// 	
//     /** Whether the Browser is currently active. */
// 	boolean isBrowsing();
// 	
//     /** Starts browsing for other peers. */
// 	void startBrowsing();
//     /** Stops browsing for other peers. */
// 	void stopBrowsing();
// }
// 
// Path: Source/src/de/tum/in/www1/jReto/util/StartStopHelper.java
// public class StartStopHelper {
// 	/**
// 	 * Represents the desired states this class should help reach.
// 	 * */
// 	private static enum State {
// 		Started, 
// 		Stopped
// 	}
// 	
// 	/** A RetryableActionExecutor that attempts to exectute the start action */
// 	private final RetryableActionExecutor starter;
// 	/** A RetryableActionExecutor that attempts to exectute the stop action */
// 	private final RetryableActionExecutor stopper;
// 	
// 	/** The state that should be reached. 
// 	 * 
// 	 * E.g.: When the switching the desired state to the started state (by calling start), the StartStopHelper will call 
// 	 * the start action until it is notified about a successful start via onStart(). */
// 	private State desiredState = State.Stopped;
// 	
// 	/**
// 	 * Creates a new StartStopHelper.
// 	 * 
// 	 * @param startAction The start action
// 	 * @param stopAction The stop action
// 	 * @param timerSettings The timer settings used to retry the start and stop actions
// 	 * @param executor The executor to execute the start and stop action on.
// 	 * */
// 	public StartStopHelper(RetryableAction startAction, RetryableAction stopAction, Timer.BackoffTimerSettings timerSettings, Executor executor) {
// 		this.starter = new RetryableActionExecutor(startAction, timerSettings, executor);
// 		this.stopper = new RetryableActionExecutor(stopAction, timerSettings, executor);
// 	}
// 	
// 	/**
// 	 * Runs the startAction in delays until onStart is called.
// 	 * */
// 	public void start() {
// 		this.desiredState = State.Started;
// 		
// 		this.stopper.stop();
// 		this.starter.start();
// 	}
// 	/**
// 	 * Runs the startAction in delays until onStart is called.
// 	 * */
// 	public void stop() {
// 		this.desiredState = State.Stopped;
// 		
// 		this.starter.stop();
// 		this.stopper.start();
// 	}
// 
// 	/**
// 	 * Call this method when the startAction succeeds, or a start occurs for another reason. Stops calling the start action. Starts calling the stop action if the stop() was called last (as opposed to start()).
// 	 * */
// 	public void onStart() {
// 		this.starter.stop();
// 		if (this.desiredState == State.Stopped) this.stopper.start();
// 	}
// 	/**
// 	 * Call this method when the stopAction succeeds, or a start occurs for another reason. Stops calling the stop action. Starts calling the start action if the start() was called last (as opposed to stop()).
// 	 * */
// 	public void onStop() {
// 		this.stopper.stop();
// 		if (this.desiredState == State.Started) this.starter.start();
// 	}
// }


import java.util.Date;
import java.util.UUID;
import java.util.concurrent.Executor;
import de.tum.in.www1.jReto.module.api.Address;
import de.tum.in.www1.jReto.module.api.Browser;
import de.tum.in.www1.jReto.util.StartStopHelper;
			attemptNumber -> attemptStop(attemptNumber), 
			ManagedModule.DEFAULT_TIMER_SETTINGS, 
			executor
		);
	}
	
	private void attemptStart(int attemptNumber) {
		if (attemptNumber > 1) System.out.println(new Date()+": Retrying to start browser (attempt "+attemptNumber+"): "+ this.browser);
		
		this.browser.startBrowsing();
	}
	private void attemptStop(int attemptNumber) {
		if (attemptNumber > 1) System.out.println(new Date()+": Retrying to stop browser (attempt "+attemptNumber+"): "+ this.browser);
		
		this.browser.stopBrowsing();
	}
	
	@Override
	public void onBrowsingStarted(Browser browser) {
		this.startStopHelper.onStart();
		this.handler.onBrowsingStarted(this);
	}

	@Override
	public void onBrowsingStopped(Browser browser, Object error) {
		this.startStopHelper.onStop();
		this.handler.onBrowsingStopped(this, error);
	}

	@Override
// Path: Source/src/de/tum/in/www1/jReto/module/api/Address.java
// public interface Address {
//     /** 
//     * Called to establish a new outgoing connection.
//     * @return A new connection to the peer.
//     */
// 	Connection createConnection();
// 	/** The cost of an address gives an heuristic about which Address should be used if multiple are available. Lower cost is preferred. An WlanAddress uses a cost of 10. */ 
// 	int getCost();
// }
// 
// Path: Source/src/de/tum/in/www1/jReto/module/api/Browser.java
// public interface Browser {
// 	/**
// 	* The Browser.Handler interface allows an implementation of the Browser protocol to inform it's delegate about various events.
// 	*/
// 	public static interface Handler {
// 	    /** Called when the Browser started to browse. */
// 		void onBrowsingStarted(Browser browser);
// 	    /** Called when the Browser stopped to browse. */
// 		void onBrowsingStopped(Browser browser, Object error);
// 	    /** Called when the Browser discovered an address. */
// 		void onAddressDiscovered(Browser browser, Address address, UUID identifier);
// 	    /** Called when the Browser lost an address, i.e. when that address becomes invalid for any reason. */
// 		void onAddressRemoved(Browser browser, Address address, UUID identifier);
// 	}
// 	
//     /** Sets the Browser's delegate */
// 	void setBrowserHandler(Handler handler);
//     /** The Browser's delegate */
// 	Handler getBrowserHandler();
// 	
//     /** Whether the Browser is currently active. */
// 	boolean isBrowsing();
// 	
//     /** Starts browsing for other peers. */
// 	void startBrowsing();
//     /** Stops browsing for other peers. */
// 	void stopBrowsing();
// }
// 
// Path: Source/src/de/tum/in/www1/jReto/util/StartStopHelper.java
// public class StartStopHelper {
// 	/**
// 	 * Represents the desired states this class should help reach.
// 	 * */
// 	private static enum State {
// 		Started, 
// 		Stopped
// 	}
// 	
// 	/** A RetryableActionExecutor that attempts to exectute the start action */
// 	private final RetryableActionExecutor starter;
// 	/** A RetryableActionExecutor that attempts to exectute the stop action */
// 	private final RetryableActionExecutor stopper;
// 	
// 	/** The state that should be reached. 
// 	 * 
// 	 * E.g.: When the switching the desired state to the started state (by calling start), the StartStopHelper will call 
// 	 * the start action until it is notified about a successful start via onStart(). */
// 	private State desiredState = State.Stopped;
// 	
// 	/**
// 	 * Creates a new StartStopHelper.
// 	 * 
// 	 * @param startAction The start action
// 	 * @param stopAction The stop action
// 	 * @param timerSettings The timer settings used to retry the start and stop actions
// 	 * @param executor The executor to execute the start and stop action on.
// 	 * */
// 	public StartStopHelper(RetryableAction startAction, RetryableAction stopAction, Timer.BackoffTimerSettings timerSettings, Executor executor) {
// 		this.starter = new RetryableActionExecutor(startAction, timerSettings, executor);
// 		this.stopper = new RetryableActionExecutor(stopAction, timerSettings, executor);
// 	}
// 	
// 	/**
// 	 * Runs the startAction in delays until onStart is called.
// 	 * */
// 	public void start() {
// 		this.desiredState = State.Started;
// 		
// 		this.stopper.stop();
// 		this.starter.start();
// 	}
// 	/**
// 	 * Runs the startAction in delays until onStart is called.
// 	 * */
// 	public void stop() {
// 		this.desiredState = State.Stopped;
// 		
// 		this.starter.stop();
// 		this.stopper.start();
// 	}
// 
// 	/**
// 	 * Call this method when the startAction succeeds, or a start occurs for another reason. Stops calling the start action. Starts calling the stop action if the stop() was called last (as opposed to start()).
// 	 * */
// 	public void onStart() {
// 		this.starter.stop();
// 		if (this.desiredState == State.Stopped) this.stopper.start();
// 	}
// 	/**
// 	 * Call this method when the stopAction succeeds, or a start occurs for another reason. Stops calling the stop action. Starts calling the start action if the start() was called last (as opposed to stop()).
// 	 * */
// 	public void onStop() {
// 		this.stopper.stop();
// 		if (this.desiredState == State.Started) this.starter.start();
// 	}
// }


// Path: Source/src/de/tum/in/www1/jReto/routing/managed_module/ManagedBrowser.java
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.Executor;
import de.tum.in.www1.jReto.module.api.Address;
import de.tum.in.www1.jReto.module.api.Browser;
import de.tum.in.www1.jReto.util.StartStopHelper;

			attemptNumber -> attemptStop(attemptNumber), 
			ManagedModule.DEFAULT_TIMER_SETTINGS, 
			executor
		);
	}
	
	private void attemptStart(int attemptNumber) {
		if (attemptNumber > 1) System.out.println(new Date()+": Retrying to start browser (attempt "+attemptNumber+"): "+ this.browser);
		
		this.browser.startBrowsing();
	}
	private void attemptStop(int attemptNumber) {
		if (attemptNumber > 1) System.out.println(new Date()+": Retrying to stop browser (attempt "+attemptNumber+"): "+ this.browser);
		
		this.browser.stopBrowsing();
	}
	
	@Override
	public void onBrowsingStarted(Browser browser) {
		this.startStopHelper.onStart();
		this.handler.onBrowsingStarted(this);
	}

	@Override
	public void onBrowsingStopped(Browser browser, Object error) {
		this.startStopHelper.onStop();
		this.handler.onBrowsingStopped(this, error);
	}

	@Override
	public void onAddressDiscovered(Browser browser, Address address, UUID identifier) {