package de.planetswebdesign.fsm.hopcroftminimizer;

import de.planetswebdesign.fsm.DefaultImpl.DefaultGuard;
import de.planetswebdesign.fsm.DefaultImpl.DefaultInputEvent;
import de.planetswebdesign.fsm.State;
import de.planetswebdesign.fsm.acceptor.AcceptorFSM;
import java.util.ArrayList;
import java.util.Collection;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;


public class MinimizerTest {

public MinimizerTest() {
}

@BeforeClass
public static void setUpClass() throws Exception {
}

@AfterClass
public static void tearDownClass() throws Exception {
}

@Before
public void setUp() {
}

@After
public void tearDown() {
}

/**
* Test of partition method, of class Minimizer.
*/
@Test
public void partition() {
AcceptorFSM fsm = new AcceptorFSM();
State s0 = fsm.createState();
State s1 = fsm.createState();
State s2 = fsm.createState();
State s3 = fsm.createState();
s0.setFinal(true);
s2.setFinal(true);
DefaultGuard t = fsm.createGuard();
t.setEvent(new DefaultInputEvent());
DefaultGuard h = fsm.createGuard();
h.setEvent(new DefaultInputEvent());
fsm.createTransition(s0, s0, t);
fsm.createTransition(s0, s1, h);
fsm.createTransition(s1, s1, t);
fsm.createTransition(s1, s2, h);
fsm.createTransition(s2, s2, t);
fsm.createTransition(s2, s3, h);
fsm.createTransition(s3, s3, t);
fsm.createTransition(s3, s0, h);
Collection finalStates = new ArrayList(2);
finalStates.add(s0);
finalStates.add(s2);
Collection nonfinalStates = new ArrayList(2);
nonfinalStates.add(s1);
nonfinalStates.add(s3);
Collection<Block> expResult = null;
Collection<Block> result = Minimizer.partition(fsm);
assertTrue(result.size() == 2);
for (Block b : result) {
assertTrue(b.size() == 2);
assertTrue(b.containsAll(finalStates) || b.containsAll(nonfinalStates));
}
}

@Test
public void partition2() {



AcceptorFSM fsm = new AcceptorFSM();

DefaultGuard[] guards = new DefaultGuard[3];

guards[0] = fsm.createGuard();
guards[0].setEvent(new DefaultInputEvent());
guards[1] = fsm.createGuard();
guards[1].setEvent(new DefaultInputEvent());
guards[2] = fsm.createGuard();
guards[2].setEvent(new DefaultInputEvent());

Collection<State> e0 = new ArrayList<State>(1);
Collection<State> e1 = new ArrayList<State>(3);
Collection<State> e2 = new ArrayList<State>(9);
Collection<State> e3 = new ArrayList<State>(27);

int numStates = 0;

State level0 = fsm.createState();
numStates++;
e0.add(level0);
level0.setLabel("0");
for (int i = 0; i < 3; i++) {
State level1 = fsm.createState();
numStates++;
e1.add(level1);
level1.setLabel(level0.getLabel() + i);
fsm.createTransition(level0, level1, guards[i]);
for (int ii = 0; ii < 3; ii++) {
State level2 = fsm.createState();
numStates++;
e2.add(level2);
level2.setLabel(level1.getLabel() + ii);
fsm.createTransition(level1, level2, guards[ii]);
for (int iii = 0; iii < 3; iii++) {
State level3 = fsm.createState();
numStates++;
e3.add(level3);
level3.setLabel(level2.getLabel() + iii);
level3.setFinal(true);
fsm.createTransition(level2, level3, guards[iii]);
}
}
}

Collection<Block> blocks = Minimizer.partition(fsm);

for (Block block : blocks) {
numStates -= block.size();
}
assertTrue(numStates == 0);

boolean found = false;
for (Block block : blocks) {
if (block.size() == e0.size() && block.containsAll(e0)) {
found = true;
}
}
assertTrue(found);

found = false;
for (Block block : blocks) {

if (block.size() == e1.size() && block.containsAll(e1)) {
found = true;
}
}
assertTrue(found);

found = false;
for (Block block : blocks) {

if (block.size() == e2.size() && block.containsAll(e2)) {
found = true;
}
}
assertTrue(found);

found = false;
for (Block block : blocks) {
System.out.println(block); // print result of computation
if (block.size() == e3.size() && block.containsAll(e3)) {
found = true;
}
}
assertTrue(found);


}
}