/**
   * Test method for {@link AbstractMediaRouteController#addMediaStateListener(MediaStateListener)}
   *
   * <p>Tests that listeners are not used (state not initialized) when the media router is not
   * initialized.
   */
  @Test
  @Feature({"MediaRemote"})
  public void testAddMediaStateListenerInitFailed() {
    MediaStateListener listener = mock(MediaStateListener.class);

    AbstractMediaRouteController mediaRouteController = new DummyMediaRouteController();
    mediaRouteController.addMediaStateListener(listener);

    verify(listener, never()).onRouteAvailabilityChanged(anyBoolean());
  }
  /** Test method for {@link AbstractMediaRouteController#isRemotePlaybackAvailable()}. */
  @Test
  @Feature({"MediaRemote"})
  public void testIsRemotePlaybackAvailable() {
    MediaRouter mediaRouter = mock(MediaRouter.class);
    AbstractMediaRouteController mediaRouteCtrl = new DummyMediaRouteController();
    when(mediaRouter.getSelectedRoute())
        .thenReturn(createRouteInfo(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE));
    when(mediaRouter.isRouteAvailable(any(MediaRouteSelector.class), anyInt())).thenReturn(true);

    // Default
    assertFalse(mediaRouteCtrl.isRemotePlaybackAvailable());

    ShadowMediaRouter.sMediaRouter = mediaRouter;
    mediaRouteCtrl = spy(new DummyMediaRouteController());
    assertTrue(mediaRouteCtrl.isRemotePlaybackAvailable());

    when(mediaRouter.getSelectedRoute())
        .thenReturn(createRouteInfo(MediaRouter.RouteInfo.PLAYBACK_TYPE_LOCAL));
    assertTrue(mediaRouteCtrl.isRemotePlaybackAvailable());

    when(mediaRouter.isRouteAvailable(any(MediaRouteSelector.class), anyInt())).thenReturn(false);
    assertFalse(mediaRouteCtrl.isRemotePlaybackAvailable());

    when(mediaRouter.getSelectedRoute())
        .thenReturn(createRouteInfo(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE));
    assertTrue(mediaRouteCtrl.isRemotePlaybackAvailable());
  }
  /** Test method for {@link AbstractMediaRouteController#prepareMediaRoute()}. */
  @Test
  @Feature({"MediaRemote"})
  public void testPrepareMediaRoute() {
    // Check when no media router, check that not done twice

    ShadowMediaRouter.sMediaRouter = mock(MediaRouter.class);
    AbstractMediaRouteController mediaRouteCtrl = new DummyMediaRouteController();

    verify(ShadowMediaRouter.sMediaRouter, times(0))
        .addCallback(any(MediaRouteSelector.class), any(Callback.class), anyInt());

    mediaRouteCtrl.prepareMediaRoute();
    verify(ShadowMediaRouter.sMediaRouter, times(1))
        .addCallback(
            eq(DummyMediaRouteController.sMediaRouteSelector),
            any(Callback.class),
            eq(MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY));

    mediaRouteCtrl.prepareMediaRoute();
    verify(ShadowMediaRouter.sMediaRouter, times(1))
        .addCallback(any(MediaRouteSelector.class), any(Callback.class), anyInt());
  }
  /**
   * Test method for {@link AbstractMediaRouteController#addMediaStateListener(MediaStateListener)}
   * and {@link AbstractMediaRouteController#removeMediaStateListener(MediaStateListener)}
   *
   * <p>Makes sure that listeners gets notified when they are added and don't get notified when
   * removed.
   */
  @Test
  @Feature({"MediaRemote"})
  public void testAddRemoveMediaStateListener() {
    MediaStateListener listener = mock(MediaStateListener.class);
    MediaStateListener otherListener = mock(MediaStateListener.class);
    MediaRouter mediaRouter = ShadowMediaRouter.createCapturingMock();
    when(mediaRouter.isRouteAvailable(any(MediaRouteSelector.class), anyInt())).thenReturn(true);
    ShadowMediaRouter.sMediaRouter = mediaRouter;

    // Creating the MediaRouteController
    AbstractMediaRouteController mediaRouteController = new DummyMediaRouteController();
    assertNotNull(mediaRouteController.getMediaRouter());

    // 1. #addMediaStateListener()
    mediaRouteController.addMediaStateListener(listener);

    // The route selector should get notified of new states.
    verify(mediaRouter).addCallback(any(MediaRouteSelector.class), any(Callback.class), anyInt());
    verify(listener).onRouteAvailabilityChanged(true);

    // Check the behavior difference between the first and subsequent additions.
    mediaRouteController.addMediaStateListener(otherListener);
    verify(otherListener).onRouteAvailabilityChanged(true);
    // The call count should not change.
    verify(mediaRouter).addCallback(any(MediaRouteSelector.class), any(Callback.class), anyInt());
    verify(listener).onRouteAvailabilityChanged(true);

    // 2. #removeMediaStateListener()
    mediaRouteController.removeMediaStateListener(otherListener);

    // The removed listener should not be notified of changes anymore.
    when(mediaRouter.isRouteAvailable(any(MediaRouteSelector.class), anyInt())).thenReturn(false);
    ShadowMediaRouter.sCallback.onRouteRemoved(mediaRouter, null);
    verifyNoMoreInteractions(otherListener);
    verify(listener).onRouteAvailabilityChanged(false);
    verify(mediaRouter, times(0)).removeCallback(any(Callback.class));

    mediaRouteController.removeMediaStateListener(listener);

    when(mediaRouter.isRouteAvailable(any(MediaRouteSelector.class), anyInt())).thenReturn(true);
    ShadowMediaRouter.sCallback.onRouteAdded(mediaRouter, null);
    verifyNoMoreInteractions(otherListener);
    verifyNoMoreInteractions(listener);
    verify(mediaRouter).removeCallback(any(Callback.class));
  }
  /**
   * Test method for {@link AbstractMediaRouteController#isPlaying()}.
   *
   * <p>Checks that it returns the correct value for all possible playback states.
   */
  @Test
  @Feature({"MediaRemote"})
  public void testIsPlaying() {
    // Using a spy here to override some methods.
    AbstractMediaRouteController mediaRouteCtrl = spy(new DummyMediaRouteController());

    // Default
    assertFalse(mediaRouteCtrl.isPlaying());

    mediaRouteCtrl.setPlayerStateForMediaItemState(MediaItemStatus.PLAYBACK_STATE_BUFFERING);
    assertTrue(mediaRouteCtrl.isPlaying());

    mediaRouteCtrl.setPlayerStateForMediaItemState(MediaItemStatus.PLAYBACK_STATE_CANCELED);
    assertFalse(mediaRouteCtrl.isPlaying());

    mediaRouteCtrl.setPlayerStateForMediaItemState(MediaItemStatus.PLAYBACK_STATE_ERROR);
    assertFalse(mediaRouteCtrl.isPlaying());

    mediaRouteCtrl.setPlayerStateForMediaItemState(MediaItemStatus.PLAYBACK_STATE_FINISHED);
    assertFalse(mediaRouteCtrl.isPlaying());

    mediaRouteCtrl.setPlayerStateForMediaItemState(MediaItemStatus.PLAYBACK_STATE_INVALIDATED);
    assertFalse(mediaRouteCtrl.isPlaying());

    doReturn(0L).when(mediaRouteCtrl).getPosition();
    doReturn(5000L).when(mediaRouteCtrl).getDuration();
    mediaRouteCtrl.setPlayerStateForMediaItemState(MediaItemStatus.PLAYBACK_STATE_PAUSED);
    assertFalse(mediaRouteCtrl.isPlaying());

    doReturn(5000L).when(mediaRouteCtrl).getPosition();
    doReturn(5000L).when(mediaRouteCtrl).getDuration();
    mediaRouteCtrl.setPlayerStateForMediaItemState(MediaItemStatus.PLAYBACK_STATE_PAUSED);
    assertFalse(mediaRouteCtrl.isPlaying());

    mediaRouteCtrl.setPlayerStateForMediaItemState(MediaItemStatus.PLAYBACK_STATE_PENDING);
    assertFalse(mediaRouteCtrl.isPlaying());

    mediaRouteCtrl.setPlayerStateForMediaItemState(MediaItemStatus.PLAYBACK_STATE_PLAYING);
    assertTrue(mediaRouteCtrl.isPlaying());
  }
  /** Test method for {@link AbstractMediaRouteController#shouldResetState(MediaStateListener)}. */
  @Test
  @Feature({"MediaRemote"})
  public void testShouldResetState() {
    AbstractMediaRouteController mediaRouteCtrl = new DummyMediaRouteController();
    MediaStateListener listener = mock(MediaStateListener.class);

    mediaRouteCtrl.setMediaStateListener(null);

    assertTrue(mediaRouteCtrl.shouldResetState(null));
    assertTrue(mediaRouteCtrl.shouldResetState(mock(MediaStateListener.class)));

    mediaRouteCtrl.setPlayerStateForMediaItemState(MediaItemStatus.PLAYBACK_STATE_PLAYING);

    assertFalse(mediaRouteCtrl.shouldResetState(null));
    assertTrue(mediaRouteCtrl.shouldResetState(mock(MediaStateListener.class)));

    mediaRouteCtrl.setPlayerStateForMediaItemState(MediaItemStatus.PLAYBACK_STATE_FINISHED);
    mediaRouteCtrl.setMediaStateListener(listener);

    assertTrue(mediaRouteCtrl.shouldResetState(null));
    assertTrue(mediaRouteCtrl.shouldResetState(mock(MediaStateListener.class)));
    assertTrue(mediaRouteCtrl.shouldResetState(listener));

    mediaRouteCtrl.setPlayerStateForMediaItemState(MediaItemStatus.PLAYBACK_STATE_PLAYING);

    assertTrue(mediaRouteCtrl.shouldResetState(null));
    assertTrue(mediaRouteCtrl.shouldResetState(mock(MediaStateListener.class)));
    assertFalse(mediaRouteCtrl.shouldResetState(listener));
  }