package org.langera.freud.core.iterator.resource;

import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.api.Invocation;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.action.CustomAction;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.langera.freud.core.listener.AnalysisListener;
import org.langera.freud.optional.text.Text;

import java.io.File;
import java.io.FilenameFilter;

@RunWith(JMock.class)
public class ResourceDirectoryIteratorTest
{
    private final Mockery mockery = new JUnit4Mockery();

    private File tmpDir;
    private ResourceDirectoryIterator<Text> iterator;
    private File file2;
    private File file1;
    private ResourceParser parser;
    private AnalysisListener listener;


    @Test
    public void shouldIterateOverFilesInDirectories() throws Exception
    {
        mockery.checking(new Expectations()
        {
            {
                allowing(parser).parseResource(with(any(String.class)), with((any(Resource.class))));
                will(new CustomAction("fake parsing")
                {
                    @Override
                    public Object invoke(final Invocation invocation) throws Throwable
                    {
                        return new Text("", (String) invocation.getParameter(0));
                    }
                });
            }
        });
        Assert.assertTrue(iterator.hasNext());
        Text text1 = iterator.next();

        Assert.assertEquals(file1.getAbsolutePath(), text1.getResourceIdentifier());

        Assert.assertTrue(iterator.hasNext());
        Text text2 = iterator.next();

        Assert.assertEquals(file2.getAbsolutePath(), text2.getResourceIdentifier());

        Assert.assertFalse(iterator.hasNext());
    }

    @Test
    public void shouldIterateOverFilesEvenIfParserBlowsUp() throws Exception
    {
        mockery.checking(new Expectations()
        {
            {
                one(listener).unexpected(with(aNull(Object.class)), with(any(RuntimeException.class)));

                one(parser).parseResource(with(file1.getAbsolutePath()), with((any(Resource.class))));
                will(throwException(new ResourceParserException("boom", null)));
                one(parser).parseResource(with(file2.getAbsolutePath()), with((any(Resource.class))));
                will(new CustomAction("fake parsing")
                {
                    @Override
                    public Object invoke(final Invocation invocation) throws Throwable
                    {
                        return new Text("", (String) invocation.getParameter(0));
                    }
                });
            }
        });

        Assert.assertTrue(iterator.hasNext());
        Text text2 = iterator.next();

        Assert.assertEquals(file2.getAbsolutePath(), text2.getResourceIdentifier());

        Assert.assertFalse(iterator.hasNext());
    }

    @Before
    public void setUp() throws Exception
    {
        tmpDir = new File(System.getProperty("java.io.tmpdir"));

        File dir = new File(tmpDir, "test " + System.currentTimeMillis());
        dir.mkdir();
        dir.deleteOnExit();

        final String tempFilename = "file" + System.currentTimeMillis() + ".tmp";

        file1 = new File(tmpDir, tempFilename);
        file1.createNewFile();
        file1.deleteOnExit();
        file2 = new File(dir, tempFilename);
        file2.createNewFile();
        file2.deleteOnExit();

        parser = mockery.mock(ResourceParser.class);

        mockery.checking(new Expectations()
        {
            {
                allowing(parser).getType();
                will(returnValue(Text.class));
            }
        });
        iterator = new ResourceDirectoryIterator<Text>(parser,
                true, new FilenameFilter()
        {
            public boolean accept(File dir, String name)
            {
                return name.equals(tempFilename);
            }
        }, true, System.getProperty("java.io.tmpdir"));
        listener = mockery.mock(AnalysisListener.class);
        iterator.setListener(listener);

    }
}

@@ -3140,24 +3140,46 @@
 tmpdir%22));%0A%0A
+        cleanDirs();%0A%0A
         File
@@ -3207,17 +3207,17 @@
 r, %22test
- 
+_
 %22 + Syst
@@ -4239,11 +4239,701 @@
 ;%0A%0A    %7D
+%0A%0A    private void cleanDirs()%0A    %7B%0A        File%5B%5D dirs = tmpDir.listFiles(new FilenameFilter()%0A        %7B%0A            @Override%0A            public boolean accept(final File dir, final String name)%0A            %7B%0A                return name.startsWith(%22test_%22);%0A            %7D%0A        %7D);%0A%0A        for (int i = 0, size = dirs.length; i %3C size; i++)%0A        %7B%0A            File dir = dirs%5Bi%5D;%0A            if (dir.isDirectory())%0A            %7B%0A                File%5B%5D files = dir.listFiles();%0A                for (int j = 0, size2 = files.length; j %3C size2; j++)%0A                %7B%0A                    files%5Bj%5D.delete();%0A                %7D%0A                dir.delete();%0A            %7D%0A        %7D%0A    %7D
 %0A%7D%0A

test cleanup