package com.salisburyclan.lpviewport.device;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.truth.Truth8;

import com.salisburyclan.lpviewport.api.Color;
import com.salisburyclan.lpviewport.api.Viewport;
import com.salisburyclan.lpviewport.api.ViewExtent;
import com.salisburyclan.lpviewport.device.AggregateViewport;

import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.mockito.quality.Strictness;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

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

@RunWith(JUnit4.class)
public class AggregateViewportTest {

  @Rule public MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
  @Mock private Viewport mockViewport1;
  @Mock private Viewport mockViewport2;

  private AggregateViewport viewport;

  @Before
  public void setUp() {
    // Two 10x20 Viewports, attached left-to-right.
    when(mockViewport1.getExtent()).thenReturn(new ViewExtent(0, 0, 9, 19));
    when(mockViewport2.getExtent()).thenReturn(new ViewExtent(10, 10, 19, 29));

    AggregateViewport.Builder builder = new AggregateViewport.Builder();
    builder.add(mockViewport1, 0, 0);
    builder.add(mockViewport2, 10, 0);
    viewport = builder.build();
  }

  @Test
  public void testGetExtent() throws Exception {
    assertThat(viewport.getExtent()).isEqualTo(new ViewExtent(0, 0, 19, 19));
  }

  @Test
  public void testSetLight() throws Exception {
    Color color = Color.RED;
    viewport.setLight(0, 0, color);
    viewport.setLight(9, 19, color);
    verify(mockViewport1).setLight(0, 0, color);
    verify(mockViewport1).setLight(9, 19, color);

    viewport.setLight(10, 0, color);
    viewport.setLight(19, 19, color);
    verify(mockViewport2).setLight(10, 10, color);
    verify(mockViewport2).setLight(19, 29, color);
  }

  @Test
  public void testAddListener() throws Exception {
    // TODO(mpsalisbury): implement
  }
}

@@ -262,16 +262,74 @@
 ewport;%0A
+import com.salisburyclan.lpviewport.api.ViewportListener;%0A
 import c
@@ -569,24 +569,59 @@
 unit.Test;%0A%0A
+import org.mockito.ArgumentCaptor;%0A
 import org.m
@@ -1209,16 +1209,63 @@
 ewport2;
+%0A  @Mock private ViewportListener mockListener;
 %0A%0A  priv
@@ -1860,32 +1860,139 @@
  19, 19));%0A  %7D%0A%0A
+  // Test that when we set lights on the aggregate viewport, the correct%0A  // sub-viewport lights get set.%0A
   @Test%0A  public
@@ -2414,107 +2414,1221 @@
 r);%0A
-  %7D%0A%0A  @Test%0A  public void testAddListener() throws Exception %7B%0A    // TODO(mpsalisbury): implement
+%0A    // TODO Check out of range%0A  %7D%0A%0A  // Test that when a sub-viewport button gets pressed, the correct%0A  // aggregate viewport button location gets notified.%0A  @Test%0A  public void testAddListener() throws Exception %7B%0A    ArgumentCaptor%3CViewportListener%3E viewport1ListenerCaptor =%0A      ArgumentCaptor.forClass(ViewportListener.class);%0A    ArgumentCaptor%3CViewportListener%3E viewport2ListenerCaptor =%0A      ArgumentCaptor.forClass(ViewportListener.class);%0A%0A    viewport.addListener(mockListener);%0A    verify(mockViewport1).addListener(viewport1ListenerCaptor.capture());%0A    verify(mockViewport2).addListener(viewport2ListenerCaptor.capture());%0A%0A    ViewportListener viewport1Listener = viewport1ListenerCaptor.getValue();%0A    ViewportListener viewport2Listener = viewport2ListenerCaptor.getValue();%0A%0A    viewport1Listener.onButtonPressed(0, 0);%0A    viewport1Listener.onButtonPressed(9, 19);%0A    verify(mockListener).onButtonPressed(0, 0);%0A    verify(mockListener).onButtonPressed(9, 19);%0A%0A    viewport2Listener.onButtonPressed(10, 10);%0A    viewport2Listener.onButtonPressed(19, 29);%0A    verify(mockListener).onButtonPressed(10, 0);%0A    verify(mockListener).onButtonPressed(19, 19);%0A%0A    // TODO Check out of range
 %0A  %7D

Add test for aggregate viewport listener.