package de.tbressler.waterrower;

import de.tbressler.waterrower.discovery.WaterRowerAutoDiscovery;
import de.tbressler.waterrower.log.Log;
import de.tbressler.waterrower.model.ErrorCode;
import de.tbressler.waterrower.model.ModelInformation;
import de.tbressler.waterrower.model.StrokeType;
import de.tbressler.waterrower.subscriptions.*;

import java.io.IOException;
import java.time.Duration;
import java.util.concurrent.Executors;

import static de.tbressler.waterrower.model.StrokeType.END_OF_STROKE;
import static java.time.Duration.ofSeconds;

/**
 * A small application which connects to the WaterRower Performance Monitor and
 * subscribes to some signals.
 *
 * The class can be used to test with a real device.
 *
 * @author Tobias Bressler
 * @version 1.0
 */
public class TestWithRealDevice {

    private static int STROKES = 0;


    public static void main(String...args) throws IOException {

        WaterRowerInitializer initializer = new WaterRowerInitializer(ofSeconds(5), ofSeconds(5), 5);
        WaterRower waterRower = new WaterRower(initializer);
        waterRower.addConnectionListener(new IWaterRowerConnectionListener() {
            @Override
            public void onConnected(ModelInformation modelInformation) {
                Log.debug("Connected to: " + modelInformation.getMonitorType().name() + ", " + modelInformation.getFirmwareVersion());
            }
            
            @Override
            public void onDisconnected() {
                Log.debug("Disconnected.");
                try {
                    // TODO Move this disconnect to the auto-discovery.
                    waterRower.disconnect();
                } catch (IOException e) {
                    Log.error("Couldn't disconnect! " + e.getMessage(), e);
                }
            }
            
            @Override
            public void onError(ErrorCode errorCode) {
                Log.error("An error occurred! Error code is "+errorCode.name()+".", null);
            }

        });

        WaterRowerAutoDiscovery discovery = new WaterRowerAutoDiscovery(waterRower, Executors.newSingleThreadScheduledExecutor());

        waterRower.subscribe(new StrokeSubscription() {
            @Override
            protected void onStroke(StrokeType strokeType) {
                if (strokeType.equals(END_OF_STROKE))
                    return;
                STROKES++;
                Log.info("Stroke(s) = " + STROKES + " counted");
            }
        });

        waterRower.subscribe(new TankVolumeSubscription() {
            @Override
            protected void onTankVolumeUpdated(double tankVolume) {
                Log.info("Tank volume = "+tankVolume);
            }
        });

        waterRower.subscribe(new DisplayedDurationSubscription() {
            @Override
            protected void onDurationUpdated(Duration duration) {
                Log.info("Displayed duration = "+duration.toMinutes());
            }
        });

        waterRower.subscribe(new AverageStrokeTimeSubscription(AverageStrokeTimeSubscription.StrokeType.WHOLE_STROKE) {
            @Override
            protected void onAverageStrokeTimeUpdated(int averageStrokeTime) {
                Log.info("Average stroke time (Whole) = "+averageStrokeTime+"");
            }
        });

        waterRower.subscribe(new AverageStrokeTimeSubscription(AverageStrokeTimeSubscription.StrokeType.PULL_ONLY) {
            @Override
            protected void onAverageStrokeTimeUpdated(int averageStrokeTime) {
                Log.info("Average stroke time (Pull) = "+averageStrokeTime+"");
            }
        });

        waterRower.subscribe(new TotalDistanceSubscription() {
            @Override
            protected void onDistanceUpdated(int distance) {
                Log.info("Total distance = "+distance+" meter(s)");
            }
        });


        discovery.start();
    }

}

@@ -804,46 +804,8 @@
  %7B%0A%0A
-    private static int STROKES = 0;%0A%0A%0A
     
@@ -864,16 +864,16 @@
 ption %7B%0A
+
 %0A       
@@ -2107,834 +2107,8 @@
 );%0A%0A
-        waterRower.subscribe(new StrokeSubscription() %7B%0A            @Override%0A            protected void onStroke(StrokeType strokeType) %7B%0A                if (strokeType.equals(END_OF_STROKE))%0A                    return;%0A                STROKES++;%0A                Log.info(%22Stroke(s) = %22 + STROKES + %22 counted%22);%0A            %7D%0A        %7D);%0A%0A        waterRower.subscribe(new TankVolumeSubscription() %7B%0A            @Override%0A            protected void onTankVolumeUpdated(double tankVolume) %7B%0A                Log.info(%22Tank volume = %22+tankVolume);%0A            %7D%0A        %7D);%0A%0A        waterRower.subscribe(new DisplayedDurationSubscription() %7B%0A            @Override%0A            protected void onDurationUpdated(Duration duration) %7B%0A                Log.info(%22Displayed duration = %22+duration.toMinutes());%0A            %7D%0A        %7D);%0A%0A
     
@@ -2967,24 +2967,24 @@
 meter(s)%22);%0A
-
             
@@ -2998,16 +2998,306 @@
    %7D);%0A%0A
+        waterRower.subscribe(new ClockCountDownSubscription() %7B%0A%0A            @Override%0A            protected void onClockCountDownUpdated(Duration duration) %7B%0A                Log.info(%22Clock count down = %22+duration.toMinutesPart()+%22:%22+duration.toSecondsPart());%0A            %7D%0A%0A        %7D);%0A%0A
 %0A       

Prepare test