package com.github.davidmoten.fsm;

import static org.junit.Assert.assertEquals;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.junit.Test;

import com.github.davidmoten.fsm.example.generated.MicrowaveBehaviour;
import com.github.davidmoten.fsm.example.generated.MicrowaveBehaviourBase;
import com.github.davidmoten.fsm.example.generated.MicrowaveStateMachine;
import com.github.davidmoten.fsm.example.generated.ShipBehaviour;
import com.github.davidmoten.fsm.example.generated.ShipBehaviourBase;
import com.github.davidmoten.fsm.example.generated.ShipStateMachine;
import com.github.davidmoten.fsm.example.microwave.ButtonPressed;
import com.github.davidmoten.fsm.example.microwave.DoorOpened;
import com.github.davidmoten.fsm.example.microwave.Microwave;
import com.github.davidmoten.fsm.example.ship.In;
import com.github.davidmoten.fsm.example.ship.Out;
import com.github.davidmoten.fsm.example.ship.Ship;
import com.github.davidmoten.fsm.runtime.Create;
import com.github.davidmoten.fsm.runtime.EntityStateMachine;
import com.github.davidmoten.fsm.runtime.Signaller;
import com.github.davidmoten.fsm.runtime.rx.Processor;

import rx.functions.Func1;
import rx.observers.TestSubscriber;

public class StateMachineTest {

	@Test
	public void testShipRuntime() {
		final Ship ship = new Ship("12345", "6789", 35.0f, 141.3f);
		List<Integer> list = new ArrayList<>();
		ShipBehaviour shipBehaviour = new ShipBehaviourBase() {

			@Override
			public Ship onEntry_Outside(Signaller signaller, Ship ship, Out out) {
				list.add(1);
				return new Ship(ship.imo(), ship.mmsi(), out.lat, out.lon);
			}

			@Override
			public Ship onEntry_NeverOutside(Signaller signaller, Create created) {
				list.add(2);
				return ship;
			}

			@Override
			public Ship onEntry_InsideNotRisky(Signaller signaller, Ship ship, In in) {
				list.add(3);
				return new Ship(ship.imo(), ship.mmsi(), in.lat, in.lon);
			}

		};
		ShipStateMachine.create(shipBehaviour)
				//
				.signal(Create.instance())
				//
				.signal(new In(1.0f, 2.0f))
				//
				.signal(new Out(1.0f, 3.0f));

		assertEquals(Arrays.asList(2, 1), list);
	}

	@Test
	public void testMicrowaveRuntime() {
		Microwave microwave = new Microwave("1");
		MicrowaveBehaviour behaviour = new MicrowaveBehaviourBase();
		MicrowaveStateMachine m = MicrowaveStateMachine.create(microwave, behaviour,
				MicrowaveStateMachine.State.READY_TO_COOK);
		m.signal(new ButtonPressed()).signal(new DoorOpened());
	}

	@Test
	public void testMicrowaveProcessor() {
		Microwave microwave = new Microwave("1");
		MicrowaveBehaviour behaviour = new MicrowaveBehaviourBase();
		Func1<Object, String> identifier = x -> ((Microwave) x).id();
		Func1<String, EntityStateMachine<?>> stateMachineCreator = id -> MicrowaveStateMachine.create(new Microwave(id),
				behaviour, MicrowaveStateMachine.State.READY_TO_COOK);
		Processor<String> processor = Processor.create(identifier, stateMachineCreator);
		TestSubscriber<EntityStateMachine<?>> ts = TestSubscriber.create();
		processor.observable().subscribe(ts);
		processor.signal(microwave, new DoorOpened());
		processor.onCompleted();
		ts.awaitTerminalEvent();
		ts.assertNoErrors();
		ts.assertValueCount(1);
		System.out.println(ts.getOnNextEvents());
	}

}

@@ -150,16 +150,54 @@
 il.List;
+%0Aimport java.util.concurrent.TimeUnit;
 %0A%0Aimport
@@ -830,16 +830,82 @@
 rowave;%0A
+import com.github.davidmoten.fsm.example.microwave.TimerTimesOut;%0A
 import c
@@ -2643,19 +2643,47 @@
 cessor()
+ throws InterruptedException
  %7B%0A
-
 %09%09Microw
@@ -2775,24 +2775,248 @@
 aviourBase()
+ %7B%0A%09%09%09@Override%0A%09%09%09public Microwave onEntry_Cooking(Signaller signaller, Microwave microwave, ButtonPressed event) %7B%0A%09%09%09%09signaller.signalToSelf(new TimerTimesOut(), 500, TimeUnit.MILLISECONDS);%0A%09%09%09%09return microwave;%0A%09%09%09%7D%0A%09%09%7D
 ;%0A%09%09Func1%3COb
@@ -3421,16 +3421,41 @@
 vable().
+doOnNext(m -%3E m.state()).
 subscrib
@@ -3491,36 +3491,61 @@
 rowave, new 
-DoorOpened()
+ButtonPressed());%0A%09%09Thread.sleep(1000
 );%0A%09%09process

test dev