package org.westmalle.wayland.output;

import org.freedesktop.wayland.server.Display;
import org.freedesktop.wayland.server.EventLoop;
import org.freedesktop.wayland.server.WlSurfaceResource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import java.util.LinkedList;
import java.util.List;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class CompositorTest {

    @Mock
    private Display     display;
    @Mock
    private ShmRenderer shmRenderer;

    @InjectMocks
    private Compositor compositor;

    @Test
    public void testRequestRender() throws Exception {
        //given
        final EventLoop eventLoop = mock(EventLoop.class);
        when(this.display.getEventLoop()).thenReturn(eventLoop);
        when(eventLoop.addIdle(any())).thenAnswer(invocation -> {
            final Object arg0 = invocation.getArguments()[0];
            final EventLoop.IdleHandler idleHandler = (EventLoop.IdleHandler) arg0;
            idleHandler.handle();
            return null;
        });

        final WlSurfaceResource wlSurfaceResource0 = mock(WlSurfaceResource.class);
        final WlSurfaceResource wlSurfaceResource1 = mock(WlSurfaceResource.class);
        final WlSurfaceResource wlSurfaceResource2 = mock(WlSurfaceResource.class);
        this.compositor.getSurfacesStack()
                       .add(wlSurfaceResource0);
        this.compositor.getSurfacesStack()
                       .add(wlSurfaceResource1);
        this.compositor.getSurfacesStack()
                       .add(wlSurfaceResource2);

        //when
        this.compositor.requestRender();
        //then
        final InOrder inOrder = inOrder(this.shmRenderer,
                                        this.display);
        inOrder.verify(this.shmRenderer)
               .beginRender();
        inOrder.verify(this.shmRenderer)
               .render(wlSurfaceResource0);
        inOrder.verify(this.shmRenderer)
               .render(wlSurfaceResource1);
        inOrder.verify(this.shmRenderer)
               .render(wlSurfaceResource2);
        inOrder.verify(this.shmRenderer)
               .endRender();
        inOrder.verify(this.display)
               .flushClients();
    }

    @Test
    public void testRequestRenderPreviousRenderBusy() throws Exception {
        //given
        final EventLoop eventLoop = mock(EventLoop.class);
        when(this.display.getEventLoop()).thenReturn(eventLoop);

        final List<EventLoop.IdleHandler> idleHandlers = new LinkedList<>();
        when(eventLoop.addIdle(any())).thenAnswer(invocation -> {

            final Object arg0 = invocation.getArguments()[0];
            final EventLoop.IdleHandler idleHandler = (EventLoop.IdleHandler) arg0;
            idleHandlers.add(idleHandler);
            return null;
        });

        final WlSurfaceResource wlSurfaceResource0 = mock(WlSurfaceResource.class);
        final WlSurfaceResource wlSurfaceResource1 = mock(WlSurfaceResource.class);
        final WlSurfaceResource wlSurfaceResource2 = mock(WlSurfaceResource.class);
        this.compositor.getSurfacesStack()
                       .add(wlSurfaceResource0);
        this.compositor.getSurfacesStack()
                       .add(wlSurfaceResource1);
        this.compositor.getSurfacesStack()
                       .add(wlSurfaceResource2);

        //when
        this.compositor.requestRender();
        this.compositor.requestRender();
        //then
        assertThat((Iterable<EventLoop.IdleHandler>) idleHandlers).hasSize(1);
        //and when
        idleHandlers.get(0)
                    .handle();
        this.compositor.requestRender();
        //then
        assertThat((Iterable<EventLoop.IdleHandler>) idleHandlers).hasSize(2);
    }
}
@@ -128,16 +128,67 @@
 ntLoop;%0A
+import org.freedesktop.wayland.server.EventSource;%0A
 import o
@@ -232,24 +232,24 @@
 ceResource;%0A
-
 import org.j
@@ -1027,16 +1027,93 @@
 tLoop);%0A
+        final List%3CEventLoop.IdleHandler%3E idleHandlers = new LinkedList%3C%3E();%0A
         
@@ -1339,24 +1339,33 @@
 eHandler
-.h
+s.add(idleH
 andle
-(
+r
 );%0A     
@@ -1370,36 +1370,55 @@
          return 
-null
+mock(EventSource.class)
 ;%0A        %7D);%0A%0A 
@@ -1952,32 +1952,32 @@
 %0A        //when%0A
-
         this.com
@@ -1993,32 +1993,70 @@
 equestRender();%0A
+        idleHandlers.get(0).handle();%0A
         //then%0A 

fix request render unit test