package com.zuehlke.carrera.javapilot.akka.experimental;

import akka.actor.ActorRef;
import akka.actor.Props;
import akka.actor.UntypedActor;
import com.zuehlke.carrera.javapilot.akka.PowerAction;
import com.zuehlke.carrera.relayapi.messages.PenaltyMessage;
import com.zuehlke.carrera.relayapi.messages.RaceStartMessage;
import com.zuehlke.carrera.relayapi.messages.SensorEvent;
import com.zuehlke.carrera.timeseries.FloatingHistory;
import org.apache.commons.lang.StringUtils;

/**
 *  this logic node increases the power level by 10 units per 0.5 second until it receives a penalty
 *  then reduces by ten units.
 */
public class PowerUpUntilPenalty extends UntypedActor {

    private final ActorRef kobayashi;

    private int currentPower = 0;

    private long lastIncrease = 0;

    private int maxPower = 180; // Max for this phase;

    private boolean probing = true;

    private FloatingHistory gyrozHistory = new FloatingHistory(8);

    /**
     * @param pilotActor The central pilot actor
     * @param duration the period between two increases
     * @return the actor props
     */
    public static Props props( ActorRef pilotActor, int duration ) {
        return Props.create(
                PowerUpUntilPenalty.class, () -> new PowerUpUntilPenalty(pilotActor, duration ));
    }
    private final int duration;

    public PowerUpUntilPenalty(ActorRef pilotActor, int duration) {
        lastIncrease = System.currentTimeMillis();
        this.kobayashi = pilotActor;
        this.duration = duration;
    }


    @Override
    public void onReceive(Object message) throws Exception {

        if ( message instanceof SensorEvent ) {
            handleSensorEvent((SensorEvent) message);

        } else if ( message instanceof PenaltyMessage) {
            handlePenaltyMessage ( (PenaltyMessage) message );

        } else if ( message instanceof RaceStartMessage) {
            handleRaceStart();

        } else {
            unhandled(message);
        }
    }

    private void handleRaceStart() {
        currentPower = 0;
        lastIncrease = 0;
        maxPower = 180; // Max for this phase;
        probing = true;
        gyrozHistory = new FloatingHistory(8);
    }

    private void handlePenaltyMessage(PenaltyMessage message) {

        currentPower -= 10;
        kobayashi.tell(new PowerAction(currentPower), getSelf());
        probing = false;
    }

    /**
     * Strategy: increase quickly when standing still to overcome haptic friction
     * then increase slowly. Probing phase will be ended by the first penalty
     * @param message the sensor event coming in
     */
    private void handleSensorEvent(SensorEvent message) {

        double gyrz = gyrozHistory.shift(message.getG()[2]);
         show ((int)gyrz);

        if (probing) {
            if (iAmStillStanding()) {
                increase(5);
            } else if (message.getTimeStamp() > lastIncrease + duration) {
                lastIncrease = message.getTimeStamp();
                increase(3);
            }
        }

        kobayashi.tell(new PowerAction(currentPower), getSelf());
    }

    private int increase ( int val ) {
        currentPower = Math.min ( currentPower + val, maxPower );
        return currentPower;
    }

    private boolean iAmStillStanding() {
        return gyrozHistory.currentStDev() < 3;
    }

    private void show(int gyr2) {
        int scale = 120 * (gyr2 - (-10000) ) / 20000;
        System.out.println(StringUtils.repeat(" ", scale) + gyr2);
    }


}

@@ -191,16 +191,84 @@
 Action;%0A
+import com.zuehlke.carrera.javapilot.services.EndpointAnnouncement;%0A
 import c
@@ -375,32 +375,95 @@
 ceStartMessage;%0A
+import com.zuehlke.carrera.relayapi.messages.RoundTimeMessage;%0A
 import com.zuehl
@@ -1956,17 +1956,16 @@
 sage );%0A
-%0A
         
@@ -2046,17 +2046,195 @@
 tart();%0A
+        %7D else if (message instanceof RoundTimeMessage) %7B%0A            handleRoundTime();%0A        %7D else if(message instanceof EndpointAnnouncement)%7B%0A            handleEndpoint();
 %0A
-
         
@@ -2242,16 +2242,17 @@
  else %7B%0A
+%0A
         
@@ -2275,16 +2275,16 @@
 ssage);%0A
-
         
@@ -2284,32 +2284,195 @@
        %7D%0A    %7D%0A%0A
+    private void handleEndpoint()%7B%0A        System.out.println(%22ROUND%22);%0A    %7D%0A%0A    private void handleRoundTime()%7B%0A        System.out.println(%22ROUNDTIME%22);%0A    %7D%0A%0A
     private void

add javapilot class diagram