package org.westmalle.wayland.core;

import org.freedesktop.wayland.server.Client;
import org.freedesktop.wayland.server.Display;
import org.freedesktop.wayland.server.WlKeyboardResource;
import org.freedesktop.wayland.server.WlSurfaceResource;
import org.freedesktop.wayland.shared.WlKeyboardKeyState;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.westmalle.wayland.nativ.NativeFileFactory;
import org.westmalle.wayland.nativ.libc.Libc;

import java.util.Collections;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class KeyboardDeviceTest {

    @Mock
    private Display           display;
    @Mock
    private NativeFileFactory nativeFileFactory;
    @Mock
    private Libc              libc;
    @Mock
    private Compositor        compositor;
    @InjectMocks
    private KeyboardDevice    keyboardDevice;

    @Test
    public void testKey() throws Exception {
        //given
        final Client client0 = mock(Client.class);
        final Client client1 = mock(Client.class);

        final WlKeyboardResource      wlKeyboardResource0 = mock(WlKeyboardResource.class);
        final WlKeyboardResource      wlKeyboardResource1 = mock(WlKeyboardResource.class);
        final Set<WlKeyboardResource> wlKeyboardResources = new HashSet<>();
        wlKeyboardResources.add(wlKeyboardResource0);
        wlKeyboardResources.add(wlKeyboardResource1);

        when(wlKeyboardResource0.getClient()).thenReturn(client0);
        when(wlKeyboardResource1.getClient()).thenReturn(client1);

        final WlSurfaceResource wlSurfaceResource = mock(WlSurfaceResource.class);
        when(wlSurfaceResource.getClient()).thenReturn(client0);
        this.keyboardDevice.setFocus(Collections.singleton(wlKeyboardResource0),
                                     Optional.of(wlSurfaceResource));

        final int                key                        = 123;
        final WlKeyboardKeyState wlKeyboardKeyStatePressed  = WlKeyboardKeyState.PRESSED;
        final WlKeyboardKeyState wlKeyboardKeyStateReleased = WlKeyboardKeyState.RELEASED;

        final int serial0 = 1278;
        final int serial1 = 1279;
        final int serial2 = 1280;
        when(this.display.nextSerial()).thenReturn(serial0,
                                                   serial1,
                                                   serial2);
        final int time0 = 27646;
        final int time1 = 29253;
        final int time2 = 30898;
        when(this.compositor.getTime()).thenReturn(time0,
                                                   time1,
                                                   time2);
        //when
        this.keyboardDevice.key(wlKeyboardResources,
                                key,
                                wlKeyboardKeyStatePressed);

        //then
        assertThat((Iterable<Integer>) this.keyboardDevice.getPressedKeys()).contains(key);
        verify(wlKeyboardResource0).key(serial0,
                                        time0,
                                        key,
                                        wlKeyboardKeyStatePressed.getValue());

        //and when
        this.keyboardDevice.key(wlKeyboardResources,
                                key,
                                wlKeyboardKeyStateReleased);

        //then
        assertThat((Iterable<Integer>) this.keyboardDevice.getPressedKeys()).doesNotContain(key);
        verify(wlKeyboardResource0).key(serial1,
                                        time1,
                                        key,
                                        wlKeyboardKeyStateReleased.getValue());

    }

    @Test
    public void testSetFocus() throws Exception {
        throw new UnsupportedOperationException();
    }

    @Test
    public void testUpdateKeymap() throws Exception {
        throw new UnsupportedOperationException();
    }
}
@@ -719,16 +719,95 @@
 rtThat;%0A
+import static org.mockito.Matchers.any;%0Aimport static org.mockito.Matchers.eq;%0A
 import s
@@ -4125,48 +4125,1299 @@
     
-throw new UnsupportedOperationException(
+//given%0A        final Client client0 = mock(Client.class);%0A%0A        final WlKeyboardResource wlKeyboardResource0 = mock(WlKeyboardResource.class);%0A%0A        when(wlKeyboardResource0.getClient()).thenReturn(client0);%0A%0A        final WlSurfaceResource wlSurfaceResource = mock(WlSurfaceResource.class);%0A        when(wlSurfaceResource.getClient()).thenReturn(client0);%0A%0A        final int serial0 = 1278;%0A        final int serial1 = 1279;%0A        final int serial2 = 1280;%0A        when(this.display.nextSerial()).thenReturn(serial0,%0A                                                   serial1,%0A                                                   serial2);%0A%0A        //when%0A        this.keyboardDevice.setFocus(Collections.singleton(wlKeyboardResource0),%0A                                     Optional.of(wlSurfaceResource));%0A%0A        //then%0A        verify(wlKeyboardResource0).enter(eq(serial0),%0A                                          eq(wlSurfaceResource),%0A                                          any());%0A        //and when%0A        this.keyboardDevice.setFocus(Collections.singleton(wlKeyboardResource0),%0A                                     Optional.empty());%0A%0A        //then%0A        verify(wlKeyboardResource0).leave(eq(serial1),%0A                                          eq(wlSurfaceResource)
 );%0A 

implement keyboard focus unit test