package jp.sourceforge.glad.collection.iteration;

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

import jp.sourceforge.glad.collection.closure.ClosureSupport;
import jp.sourceforge.glad.collection.exception.CheckedException;
import jp.sourceforge.glad.collection.exception.ReturnException;
import jp.sourceforge.glad.collection.function.Function;
import junit.framework.TestCase;

public class IterableIterationHandlerTest extends TestCase {

    IterableIterationHandler<String> handler;

    protected void setUp() throws Exception {
        List<String> source = Arrays.asList("a", "b", "c");
        handler = new IterableIterationHandler<String>(source);
    }

    protected void tearDown() throws Exception {
        handler = null;
    }

    public void testIterate() {
        final List<String> target = new ArrayList<String>();
        handler.iterate(new ClosureSupport<String>() {
            public void execute(String each) {
                target.add(each);
            }
        });
        assertEquals(3, target.size());
        assertEquals("[a, b, c]", target.toString());
    }

    public void testContinue() {
        final List<String> target = new ArrayList<String>();
        handler.iterate(new ClosureSupport<String>() {
            public void execute(String each) {
                if ("b".equals(each)) {
                    doContinue();
                }
                target.add(each);
            }
        });
        assertEquals(2, target.size());
        assertEquals("[a, c]", target.toString());
    }

    public void testBreak() {
        final List<String> target = new ArrayList<String>();
        handler.iterate(new ClosureSupport<String>() {
            public void execute(String each) {
                if ("b".equals(each)) {
                    doBreak();
                }
                target.add(each);
            }
        });
        assertEquals(1, target.size());
        assertEquals("[a]", target.toString());
    }

    public void testReturn() {
        final List<String> target = new ArrayList<String>();
        try {
            handler.iterate(new ClosureSupport<String>() {
                public void execute(String each) {
                    if ("b".equals(each)) {
                        doReturn(-1);
                    }
                    target.add(each);
                }
            });
            fail();
        } catch (ReturnException e) {
            assertEquals(-1, e.getResult());
        }
        assertEquals(1, target.size());
        assertEquals("[a]", target.toString());
    }

    public void testRuntimeException() {
        final List<String> target = new ArrayList<String>();
        try {
            handler.iterate(new ClosureSupport<String>() {
                public void execute(String each) {
                    if ("b".equals(each)) {
                        throw new RuntimeException("test");
                    }
                    target.add(each);
                }
            });
            fail();
        } catch (RuntimeException e) {
            assertEquals("test", e.getMessage());
        }
        assertEquals(1, target.size());
        assertEquals("[a]", target.toString());
    }

    public void testCheckedException() {
        final List<String> target = new ArrayList<String>();
        try {
            handler.iterate(new ClosureSupport<String>() {
                public void execute(String each) throws Exception {
                    if ("b".equals(each)) {
                        throw new Exception("test");
                    }
                    target.add(each);
                }
            });
            fail();
        } catch (CheckedException e) {
            assertEquals("test", e.getCause().getMessage());
        }
        assertEquals(1, target.size());
        assertEquals("[a]", target.toString());
    }

    public void testConvert() {
        List<String> source = Arrays.asList("1", "2", "3");
        IterationHandler<Double> adapter =
                new IterationHandlerAdapter<String, Double>(
                        new IterableIterationHandler<String>(source),
        new Function<String, Double>() {
            public Double apply(String source) {
                return Double.parseDouble(source);
            }
        });
        final List<Double> target = new ArrayList<Double>();
        adapter.iterate(new ClosureSupport<Double>() {
            public void execute(Double each) {
                target.add(each);
            }
        });
        assertEquals(3, target.size());
        assertEquals("[1.0, 2.0, 3.0]", target.toString());
    }

}
