/*
 *  Copyright 2014 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

package org.appspot.apprtc.test;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.appspot.apprtc.AppRTCClient.SignalingParameters;
import org.appspot.apprtc.PeerConnectionClient;
import org.appspot.apprtc.PeerConnectionClient.PeerConnectionEvents;
import org.appspot.apprtc.PeerConnectionClient.PeerConnectionParameters;
import org.appspot.apprtc.util.LooperExecutor;
import org.webrtc.EglBase;
import org.webrtc.IceCandidate;
import org.webrtc.MediaCodecVideoEncoder;
import org.webrtc.PeerConnection;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.SessionDescription;
import org.webrtc.StatsReport;
import org.webrtc.VideoRenderer;

import android.os.Build;
import android.test.InstrumentationTestCase;
import android.util.Log;

public class PeerConnectionClientTest extends InstrumentationTestCase
    implements PeerConnectionEvents {
  private static final String TAG = "RTCClientTest";
  private static final int ICE_CONNECTION_WAIT_TIMEOUT = 10000;
  private static final int WAIT_TIMEOUT = 7000;
  private static final int CAMERA_SWITCH_ATTEMPTS = 3;
  private static final int VIDEO_RESTART_ATTEMPTS = 3;
  private static final int VIDEO_RESTART_TIMEOUT = 500;
  private static final int EXPECTED_VIDEO_FRAMES = 10;
  private static final String VIDEO_CODEC_VP8 = "VP8";
  private static final String VIDEO_CODEC_VP9 = "VP9";
  private static final String VIDEO_CODEC_H264 = "H264";
  private static final int AUDIO_RUN_TIMEOUT = 1000;
  private static final String LOCAL_RENDERER_NAME = "Local renderer";
  private static final String REMOTE_RENDERER_NAME = "Remote renderer";

  // The peer connection client is assumed to be thread safe in itself; the
  // reference is written by the test thread and read by worker threads.
  private volatile PeerConnectionClient pcClient;
  private volatile boolean loopback;

  // EGL context that can be used by hardware video decoders to decode to a texture.
  private EglBase eglBase;

  // These are protected by their respective event objects.
  private LooperExecutor signalingExecutor;
  private boolean isClosed;
  private boolean isIceConnected;
  private SessionDescription localSdp;
  private List<IceCandidate> iceCandidates = new LinkedList<IceCandidate>();
  private final Object localSdpEvent = new Object();
  private final Object iceCandidateEvent = new Object();
  private final Object iceConnectedEvent = new Object();
  private final Object closeEvent = new Object();

  // Mock renderer implementation.
  private static class MockRenderer implements VideoRenderer.Callbacks {
    // These are protected by 'this' since we gets called from worker threads.
    private String rendererName;
    private boolean renderFrameCalled = false;

    // Thread-safe in itself.
    private CountDownLatch doneRendering;

    public MockRenderer(int expectedFrames, String rendererName) {
      this.rendererName = rendererName;
      reset(expectedFrames);
    }

    // Resets render to wait for new amount of video frames.
    public synchronized void reset(int expectedFrames) {
      renderFrameCalled = false;
      doneRendering = new CountDownLatch(expectedFrames);
    }

    @Override
    public synchronized void renderFrame(VideoRenderer.I420Frame frame) {
      if (!renderFrameCalled) {
        if (rendererName != null) {
          Log.d(TAG, rendererName + " render frame: "
              + frame.rotatedWidth() + " x " + frame.rotatedHeight());
        } else {
          Log.d(TAG, "Render frame: " + frame.rotatedWidth() + " x " + frame.rotatedHeight());
        }
      }
      renderFrameCalled = true;
      VideoRenderer.renderFrameDone(frame);
      doneRendering.countDown();
    }


    // This method shouldn't hold any locks or touch member variables since it
    // blocks.
    public boolean waitForFramesRendered(int timeoutMs)
        throws InterruptedException {
      doneRendering.await(timeoutMs, TimeUnit.MILLISECONDS);
      return (doneRendering.getCount() <= 0);
    }
  }

  // Peer connection events implementation.
  @Override
  public void onLocalDescription(SessionDescription sdp) {
    Log.d(TAG, "LocalSDP type: " + sdp.type);
    synchronized (localSdpEvent) {
      localSdp = sdp;
      localSdpEvent.notifyAll();
    }
  }

  @Override
  public void onIceCandidate(final IceCandidate candidate) {
    synchronized(iceCandidateEvent) {
      Log.d(TAG, "IceCandidate #" + iceCandidates.size() + " : " + candidate.toString());
      if (loopback) {
        // Loopback local ICE candidate in a separate thread to avoid adding
        // remote ICE candidate in a local ICE candidate callback.
        signalingExecutor.execute(new Runnable() {
          @Override
          public void run() {
            pcClient.addRemoteIceCandidate(candidate);
          }
        });
      }
      iceCandidates.add(candidate);
      iceCandidateEvent.notifyAll();
    }
  }

  @Override
  public void onIceConnected() {
    Log.d(TAG, "ICE Connected");
    synchronized(iceConnectedEvent) {
      isIceConnected = true;
      iceConnectedEvent.notifyAll();
    }
  }

  @Override
  public void onIceDisconnected() {
    Log.d(TAG, "ICE Disconnected");
    synchronized(iceConnectedEvent) {
      isIceConnected = false;
      iceConnectedEvent.notifyAll();
    }
  }

  @Override
  public void onPeerConnectionClosed() {
    Log.d(TAG, "PeerConnection closed");
    synchronized(closeEvent) {
      isClosed = true;
      closeEvent.notifyAll();
    }
  }

  @Override
  public void onPeerConnectionError(String description) {
    fail("PC Error: " + description);
  }

  @Override
  public void onPeerConnectionStatsReady(StatsReport[] reports) {
  }

  // Helper wait functions.
  private boolean waitForLocalSDP(int timeoutMs)
      throws InterruptedException {
    synchronized(localSdpEvent) {
      if (localSdp == null) {
        localSdpEvent.wait(timeoutMs);
      }
      return (localSdp != null);
    }
  }

  private boolean waitForIceCandidates(int timeoutMs)
      throws InterruptedException {
    synchronized(iceCandidateEvent) {
      if (iceCandidates.size() == 0) {
        iceCandidateEvent.wait(timeoutMs);
      }
      return (iceCandidates.size() > 0);
    }
  }

  private boolean waitForIceConnected(int timeoutMs)
      throws InterruptedException {
    synchronized(iceConnectedEvent) {
      if (!isIceConnected) {
        iceConnectedEvent.wait(timeoutMs);
      }
      if (!isIceConnected) {
        Log.e(TAG, "ICE connection failure");
      }

      return isIceConnected;
    }
  }

  private boolean waitForPeerConnectionClosed(int timeoutMs)
      throws InterruptedException {
    synchronized(closeEvent) {
      if (!isClosed) {
        closeEvent.wait(timeoutMs);
      }
      return isClosed;
    }
  }

  PeerConnectionClient createPeerConnectionClient(
      MockRenderer localRenderer, MockRenderer remoteRenderer,
      PeerConnectionParameters peerConnectionParameters, boolean useTexures) {
    List<PeerConnection.IceServer> iceServers =
        new LinkedList<PeerConnection.IceServer>();
    SignalingParameters signalingParameters = new SignalingParameters(
        iceServers, true, // iceServers, initiator.
        null, null, null, // clientId, wssUrl, wssPostUrl.
        null, null); // offerSdp, iceCandidates.

    PeerConnectionClient client = PeerConnectionClient.getInstance();
    PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
    options.networkIgnoreMask = 0;
    options.disableNetworkMonitor = true;
    client.setPeerConnectionFactoryOptions(options);
    client.createPeerConnectionFactory(
        getInstrumentation().getContext(), peerConnectionParameters, this);
    client.createPeerConnection(useTexures ? eglBase.getEglBaseContext() : null,
        localRenderer, remoteRenderer, signalingParameters);
    client.createOffer();
    return client;
  }

  private PeerConnectionParameters createParametersForAudioCall() {
    PeerConnectionParameters peerConnectionParameters =
        new PeerConnectionParameters(
            false, true, false, // videoCallEnabled, loopback, tracing.
            0, 0, 0, 0, "", true, false, // video codec parameters.
            0, "OPUS", false, false, false); // audio codec parameters.
    return peerConnectionParameters;
  }

  private PeerConnectionParameters createParametersForVideoCall(
      String videoCodec, boolean captureToTexture) {
    PeerConnectionParameters peerConnectionParameters =
        new PeerConnectionParameters(
            true, true, false, // videoCallEnabled, loopback, tracing.
            0, 0, 0, 0, videoCodec, true, captureToTexture, // video codec parameters.
            0, "OPUS", false, false, false); // audio codec parameters.
    return peerConnectionParameters;
  }

  @Override
  public void setUp() {
    signalingExecutor = new LooperExecutor();
    signalingExecutor.requestStart();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
      eglBase = EglBase.create();
    }
  }

  @Override
  public void tearDown() {
    signalingExecutor.requestStop();
    if (eglBase != null) {
      eglBase.release();
    }
  }

  public void testSetLocalOfferMakesVideoFlowLocally()
      throws InterruptedException {
    Log.d(TAG, "testSetLocalOfferMakesVideoFlowLocally");
    MockRenderer localRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, LOCAL_RENDERER_NAME);
    pcClient = createPeerConnectionClient(
        localRenderer, new MockRenderer(0, null),
        createParametersForVideoCall(VIDEO_CODEC_VP8, false), false);

    // Wait for local SDP and ice candidates set events.
    assertTrue("Local SDP was not set.", waitForLocalSDP(WAIT_TIMEOUT));
    assertTrue("ICE candidates were not generated.",
        waitForIceCandidates(WAIT_TIMEOUT));

    // Check that local video frames were rendered.
    assertTrue("Local video frames were not rendered.",
        localRenderer.waitForFramesRendered(WAIT_TIMEOUT));

    pcClient.close();
    assertTrue("PeerConnection close event was not received.",
        waitForPeerConnectionClosed(WAIT_TIMEOUT));
    Log.d(TAG, "testSetLocalOfferMakesVideoFlowLocally Done.");
  }

  private void doLoopbackTest(PeerConnectionParameters parameters, boolean decodeToTexure)
      throws InterruptedException {
    loopback = true;
    MockRenderer localRenderer = null;
    MockRenderer remoteRenderer = null;
    if (parameters.videoCallEnabled) {
      Log.d(TAG, "testLoopback for video " + parameters.videoCodec);
      localRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, LOCAL_RENDERER_NAME);
      remoteRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, REMOTE_RENDERER_NAME);
    } else {
      Log.d(TAG, "testLoopback for audio.");
    }
    pcClient = createPeerConnectionClient(
        localRenderer, remoteRenderer, parameters, decodeToTexure);

    // Wait for local SDP, rename it to answer and set as remote SDP.
    assertTrue("Local SDP was not set.", waitForLocalSDP(WAIT_TIMEOUT));
    SessionDescription remoteSdp = new SessionDescription(
        SessionDescription.Type.fromCanonicalForm("answer"),
        localSdp.description);
    pcClient.setRemoteDescription(remoteSdp);

    // Wait for ICE connection.
    assertTrue("ICE connection failure.", waitForIceConnected(ICE_CONNECTION_WAIT_TIMEOUT));

    if (parameters.videoCallEnabled) {
      // Check that local and remote video frames were rendered.
      assertTrue("Local video frames were not rendered.",
          localRenderer.waitForFramesRendered(WAIT_TIMEOUT));
      assertTrue("Remote video frames were not rendered.",
          remoteRenderer.waitForFramesRendered(WAIT_TIMEOUT));
    } else {
      // For audio just sleep for 1 sec.
      // TODO(glaznev): check how we can detect that remote audio was rendered.
      Thread.sleep(AUDIO_RUN_TIMEOUT);
    }

    pcClient.close();
    assertTrue(waitForPeerConnectionClosed(WAIT_TIMEOUT));
    Log.d(TAG, "testLoopback done.");
  }

  public void testLoopbackAudio() throws InterruptedException {
    doLoopbackTest(createParametersForAudioCall(), false);
  }

  public void testLoopbackVp8() throws InterruptedException {
    doLoopbackTest(createParametersForVideoCall(VIDEO_CODEC_VP8, false), false);
  }

  public void DISABLED_testLoopbackVp9() throws InterruptedException {
    doLoopbackTest(createParametersForVideoCall(VIDEO_CODEC_VP9, false), false);
  }

  public void testLoopbackH264() throws InterruptedException {
    doLoopbackTest(createParametersForVideoCall(VIDEO_CODEC_H264, false), false);
  }

  public void testLoopbackVp8DecodeToTexture() throws InterruptedException {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
      Log.i(TAG, "Decode to textures is not supported, requires SDK version 19.");
      return;
    }
    doLoopbackTest(createParametersForVideoCall(VIDEO_CODEC_VP8, false), true);
  }

  public void DISABLED_testLoopbackVp9DecodeToTexture() throws InterruptedException {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
      Log.i(TAG, "Decode to textures is not supported, requires SDK version 19.");
      return;
    }
    doLoopbackTest(createParametersForVideoCall(VIDEO_CODEC_VP9, false), true);
  }

  public void testLoopbackH264DecodeToTexture() throws InterruptedException {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
      Log.i(TAG, "Decode to textures is not supported, requires SDK version 19.");
      return;
    }
    doLoopbackTest(createParametersForVideoCall(VIDEO_CODEC_H264, false), true);
  }

  public void testLoopbackVp8CaptureToTexture() throws InterruptedException {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
      Log.i(TAG, "Encode to textures is not supported. Requires SDK version 19");
      return;
    }
    // TODO(perkj): If we can always capture to textures, there is no need to check if the
    // hardware encoder supports to encode from a texture.
    if (!MediaCodecVideoEncoder.isVp8HwSupportedUsingTextures()) {
      Log.i(TAG, "VP8 encode to textures is not supported.");
      return;
    }
    doLoopbackTest(createParametersForVideoCall(VIDEO_CODEC_VP8, true), true);
  }

  public void testLoopbackH264CaptureToTexture() throws InterruptedException {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
      Log.i(TAG, "Encode to textures is not supported. Requires KITKAT");
      return;
    }
    // TODO(perkj): If we can always capture to textures, there is no need to check if the
    // hardware encoder supports to encode from a texture.
    if (!MediaCodecVideoEncoder.isH264HwSupportedUsingTextures()) {
      Log.i(TAG, "H264 encode to textures is not supported.");
      return;
    }
    doLoopbackTest(createParametersForVideoCall(VIDEO_CODEC_H264, true), true);
  }


  // Checks if default front camera can be switched to back camera and then
  // again to front camera.
  public void testCameraSwitch() throws InterruptedException {
    Log.d(TAG, "testCameraSwitch");
    loopback = true;

    MockRenderer localRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, LOCAL_RENDERER_NAME);
    MockRenderer remoteRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, REMOTE_RENDERER_NAME);

    pcClient = createPeerConnectionClient(
        localRenderer, remoteRenderer, createParametersForVideoCall(VIDEO_CODEC_VP8, false), false);

    // Wait for local SDP, rename it to answer and set as remote SDP.
    assertTrue("Local SDP was not set.", waitForLocalSDP(WAIT_TIMEOUT));
    SessionDescription remoteSdp = new SessionDescription(
        SessionDescription.Type.fromCanonicalForm("answer"),
        localSdp.description);
    pcClient.setRemoteDescription(remoteSdp);

    // Wait for ICE connection.
    assertTrue("ICE connection failure.", waitForIceConnected(ICE_CONNECTION_WAIT_TIMEOUT));

    // Check that local and remote video frames were rendered.
    assertTrue("Local video frames were not rendered before camera switch.",
        localRenderer.waitForFramesRendered(WAIT_TIMEOUT));
    assertTrue("Remote video frames were not rendered before camera switch.",
        remoteRenderer.waitForFramesRendered(WAIT_TIMEOUT));

    for (int i = 0; i < CAMERA_SWITCH_ATTEMPTS; i++) {
      // Try to switch camera
      pcClient.switchCamera();

      // Reset video renders and check that local and remote video frames
      // were rendered after camera switch.
      localRenderer.reset(EXPECTED_VIDEO_FRAMES);
      remoteRenderer.reset(EXPECTED_VIDEO_FRAMES);
      assertTrue("Local video frames were not rendered after camera switch.",
          localRenderer.waitForFramesRendered(WAIT_TIMEOUT));
      assertTrue("Remote video frames were not rendered after camera switch.",
          remoteRenderer.waitForFramesRendered(WAIT_TIMEOUT));
    }
    pcClient.close();
    assertTrue(waitForPeerConnectionClosed(WAIT_TIMEOUT));
    Log.d(TAG, "testCameraSwitch done.");
  }

  // Checks if video source can be restarted - simulate app goes to
  // background and back to foreground.
  public void testVideoSourceRestart() throws InterruptedException {
    Log.d(TAG, "testVideoSourceRestart");
    loopback = true;

    MockRenderer localRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, LOCAL_RENDERER_NAME);
    MockRenderer remoteRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, REMOTE_RENDERER_NAME);

    pcClient = createPeerConnectionClient(
        localRenderer, remoteRenderer, createParametersForVideoCall(VIDEO_CODEC_VP8, false), false);

    // Wait for local SDP, rename it to answer and set as remote SDP.
    assertTrue("Local SDP was not set.", waitForLocalSDP(WAIT_TIMEOUT));
    SessionDescription remoteSdp = new SessionDescription(
        SessionDescription.Type.fromCanonicalForm("answer"),
        localSdp.description);
    pcClient.setRemoteDescription(remoteSdp);

    // Wait for ICE connection.
    assertTrue("ICE connection failure.", waitForIceConnected(ICE_CONNECTION_WAIT_TIMEOUT));

    // Check that local and remote video frames were rendered.
    assertTrue("Local video frames were not rendered before video restart.",
        localRenderer.waitForFramesRendered(WAIT_TIMEOUT));
    assertTrue("Remote video frames were not rendered before video restart.",
        remoteRenderer.waitForFramesRendered(WAIT_TIMEOUT));

    // Stop and then start video source a few times.
    for (int i = 0; i < VIDEO_RESTART_ATTEMPTS; i++) {
      pcClient.stopVideoSource();
      Thread.sleep(VIDEO_RESTART_TIMEOUT);
      pcClient.startVideoSource();

      // Reset video renders and check that local and remote video frames
      // were rendered after video restart.
      localRenderer.reset(EXPECTED_VIDEO_FRAMES);
      remoteRenderer.reset(EXPECTED_VIDEO_FRAMES);
      assertTrue("Local video frames were not rendered after video restart.",
          localRenderer.waitForFramesRendered(WAIT_TIMEOUT));
      assertTrue("Remote video frames were not rendered after video restart.",
          remoteRenderer.waitForFramesRendered(WAIT_TIMEOUT));
    }
    pcClient.close();
    assertTrue(waitForPeerConnectionClosed(WAIT_TIMEOUT));
    Log.d(TAG, "testVideoSourceRestart done.");
  }

}
