/*
 * libjingle
 * Copyright 2015 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.webrtc;

import android.graphics.SurfaceTexture;
import android.opengl.GLES20;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.SystemClock;
import android.test.ActivityTestCase;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;

import java.nio.ByteBuffer;

public final class SurfaceTextureHelperTest extends ActivityTestCase {
  /**
   * Mock texture listener with blocking wait functionality.
   */
  public static final class MockTextureListener
      implements SurfaceTextureHelper.OnTextureFrameAvailableListener {
    public int oesTextureId;
    public float[] transformMatrix;
    private boolean hasNewFrame = false;
    // Thread where frames are expected to be received on.
    private final Thread expectedThread;

    MockTextureListener() {
      this.expectedThread = null;
    }

    MockTextureListener(Thread expectedThread) {
      this.expectedThread = expectedThread;
    }

    @Override
    public synchronized void onTextureFrameAvailable(
        int oesTextureId, float[] transformMatrix, long timestampNs) {
      if (expectedThread != null && Thread.currentThread() != expectedThread) {
        throw new IllegalStateException("onTextureFrameAvailable called on wrong thread.");
      }
      this.oesTextureId = oesTextureId;
      this.transformMatrix = transformMatrix;
      hasNewFrame = true;
      notifyAll();
    }

    /**
     * Wait indefinitely for a new frame.
     */
    public synchronized void waitForNewFrame() throws InterruptedException {
      while (!hasNewFrame) {
        wait();
      }
      hasNewFrame = false;
    }

    /**
     * Wait for a new frame, or until the specified timeout elapses. Returns true if a new frame was
     * received before the timeout.
     */
    public synchronized boolean waitForNewFrame(final long timeoutMs) throws InterruptedException {
      final long startTimeMs = SystemClock.elapsedRealtime();
      long timeRemainingMs = timeoutMs;
      while (!hasNewFrame && timeRemainingMs > 0) {
        wait(timeRemainingMs);
        final long elapsedTimeMs = SystemClock.elapsedRealtime() - startTimeMs;
        timeRemainingMs = timeoutMs - elapsedTimeMs;
      }
      final boolean didReceiveFrame = hasNewFrame;
      hasNewFrame = false;
      return didReceiveFrame;
    }
  }

  /**
   * Test normal use by receiving three uniform texture frames. Texture frames are returned as early
   * as possible. The texture pixel values are inspected by drawing the texture frame to a pixel
   * buffer and reading it back with glReadPixels().
   */
  @MediumTest
  public static void testThreeConstantColorFrames() throws InterruptedException {
    final int width = 16;
    final int height = 16;
    // Create EGL base with a pixel buffer as display output.
    final EglBase eglBase = EglBase.create(null, EglBase.CONFIG_PIXEL_BUFFER);
    eglBase.createPbufferSurface(width, height);
    final GlRectDrawer drawer = new GlRectDrawer();

    // Create SurfaceTextureHelper and listener.
    final SurfaceTextureHelper surfaceTextureHelper =
        SurfaceTextureHelper.create(eglBase.getEglBaseContext());
    final MockTextureListener listener = new MockTextureListener();
    surfaceTextureHelper.setListener(listener);
    surfaceTextureHelper.getSurfaceTexture().setDefaultBufferSize(width, height);

    // Create resources for stubbing an OES texture producer. |eglOesBase| has the SurfaceTexture in
    // |surfaceTextureHelper| as the target EGLSurface.
    final EglBase eglOesBase =
        EglBase.create(eglBase.getEglBaseContext(), EglBase.CONFIG_PLAIN);
    eglOesBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
    assertEquals(eglOesBase.surfaceWidth(), width);
    assertEquals(eglOesBase.surfaceHeight(), height);

    final int red[] = new int[] {79, 144, 185};
    final int green[] = new int[] {66, 210, 162};
    final int blue[] = new int[] {161, 117, 158};
    // Draw three frames.
    for (int i = 0; i < 3; ++i) {
      // Draw a constant color frame onto the SurfaceTexture.
      eglOesBase.makeCurrent();
      GLES20.glClearColor(red[i] / 255.0f, green[i] / 255.0f, blue[i] / 255.0f, 1.0f);
      GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
      // swapBuffers() will ultimately trigger onTextureFrameAvailable().
      eglOesBase.swapBuffers();

      // Wait for an OES texture to arrive and draw it onto the pixel buffer.
      listener.waitForNewFrame();
      eglBase.makeCurrent();
      drawer.drawOes(listener.oesTextureId, listener.transformMatrix);

      surfaceTextureHelper.returnTextureFrame();

      // Download the pixels in the pixel buffer as RGBA. Not all platforms support RGB, e.g.
      // Nexus 9.
      final ByteBuffer rgbaData = ByteBuffer.allocateDirect(width * height * 4);
      GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, rgbaData);
      GlUtil.checkNoGLES2Error("glReadPixels");

      // Assert rendered image is expected constant color.
      while (rgbaData.hasRemaining()) {
        assertEquals(rgbaData.get() & 0xFF, red[i]);
        assertEquals(rgbaData.get() & 0xFF, green[i]);
        assertEquals(rgbaData.get() & 0xFF, blue[i]);
        assertEquals(rgbaData.get() & 0xFF, 255);
      }
    }

    drawer.release();
    surfaceTextureHelper.disconnect();
    eglBase.release();
  }

  /**
   * Test disconnecting the SurfaceTextureHelper while holding a pending texture frame. The pending
   * texture frame should still be valid, and this is tested by drawing the texture frame to a pixel
   * buffer and reading it back with glReadPixels().
   */
  @MediumTest
  public static void testLateReturnFrame() throws InterruptedException {
    final int width = 16;
    final int height = 16;
    // Create EGL base with a pixel buffer as display output.
    final EglBase eglBase = EglBase.create(null, EglBase.CONFIG_PIXEL_BUFFER);
    eglBase.createPbufferSurface(width, height);

    // Create SurfaceTextureHelper and listener.
    final SurfaceTextureHelper surfaceTextureHelper =
        SurfaceTextureHelper.create(eglBase.getEglBaseContext());
    final MockTextureListener listener = new MockTextureListener();
    surfaceTextureHelper.setListener(listener);
    surfaceTextureHelper.getSurfaceTexture().setDefaultBufferSize(width, height);

    // Create resources for stubbing an OES texture producer. |eglOesBase| has the SurfaceTexture in
    // |surfaceTextureHelper| as the target EGLSurface.
    final EglBase eglOesBase =
        EglBase.create(eglBase.getEglBaseContext(), EglBase.CONFIG_PLAIN);
    eglOesBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
    assertEquals(eglOesBase.surfaceWidth(), width);
    assertEquals(eglOesBase.surfaceHeight(), height);

    final int red = 79;
    final int green = 66;
    final int blue = 161;
    // Draw a constant color frame onto the SurfaceTexture.
    eglOesBase.makeCurrent();
    GLES20.glClearColor(red / 255.0f, green / 255.0f, blue / 255.0f, 1.0f);
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    // swapBuffers() will ultimately trigger onTextureFrameAvailable().
    eglOesBase.swapBuffers();
    eglOesBase.release();

    // Wait for OES texture frame.
    listener.waitForNewFrame();
    // Diconnect while holding the frame.
    surfaceTextureHelper.disconnect();

    // Draw the pending texture frame onto the pixel buffer.
    eglBase.makeCurrent();
    final GlRectDrawer drawer = new GlRectDrawer();
    drawer.drawOes(listener.oesTextureId, listener.transformMatrix);
    drawer.release();

    // Download the pixels in the pixel buffer as RGBA. Not all platforms support RGB, e.g. Nexus 9.
    final ByteBuffer rgbaData = ByteBuffer.allocateDirect(width * height * 4);
    GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, rgbaData);
    GlUtil.checkNoGLES2Error("glReadPixels");
    eglBase.release();

    // Assert rendered image is expected constant color.
    while (rgbaData.hasRemaining()) {
      assertEquals(rgbaData.get() & 0xFF, red);
      assertEquals(rgbaData.get() & 0xFF, green);
      assertEquals(rgbaData.get() & 0xFF, blue);
      assertEquals(rgbaData.get() & 0xFF, 255);
    }
    // Late frame return after everything has been disconnected and released.
    surfaceTextureHelper.returnTextureFrame();
  }

  /**
   * Test disconnecting the SurfaceTextureHelper, but keep trying to produce more texture frames. No
   * frames should be delivered to the listener.
   */
  @MediumTest
  public static void testDisconnect() throws InterruptedException {
    // Create SurfaceTextureHelper and listener.
    final SurfaceTextureHelper surfaceTextureHelper =
        SurfaceTextureHelper.create(null);
    final MockTextureListener listener = new MockTextureListener();
    surfaceTextureHelper.setListener(listener);
    // Create EglBase with the SurfaceTexture as target EGLSurface.
    final EglBase eglBase = EglBase.create(null, EglBase.CONFIG_PLAIN);
    eglBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
    eglBase.makeCurrent();
    // Assert no frame has been received yet.
    assertFalse(listener.waitForNewFrame(1));
    // Draw and wait for one frame.
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    // swapBuffers() will ultimately trigger onTextureFrameAvailable().
    eglBase.swapBuffers();
    listener.waitForNewFrame();
    surfaceTextureHelper.returnTextureFrame();

    // Disconnect - we should not receive any textures after this.
    surfaceTextureHelper.disconnect();

    // Draw one frame.
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    eglBase.swapBuffers();
    // swapBuffers() should not trigger onTextureFrameAvailable() because we are disconnected.
    // Assert that no OES texture was delivered.
    assertFalse(listener.waitForNewFrame(500));

    eglBase.release();
  }

  /**
   * Test disconnecting the SurfaceTextureHelper immediately after is has been setup to use a
   * shared context. No frames should be delivered to the listener.
   */
  @SmallTest
  public static void testDisconnectImmediately() {
    final SurfaceTextureHelper surfaceTextureHelper =
        SurfaceTextureHelper.create(null);
    surfaceTextureHelper.disconnect();
  }

  /**
   * Test use SurfaceTextureHelper on a separate thread. A uniform texture frame is created and
   * received on a thread separate from the test thread.
   */
  @MediumTest
  public static void testFrameOnSeparateThread() throws InterruptedException {
    final HandlerThread thread = new HandlerThread("SurfaceTextureHelperTestThread");
    thread.start();
    final Handler handler = new Handler(thread.getLooper());

    // Create SurfaceTextureHelper and listener.
    final SurfaceTextureHelper surfaceTextureHelper =
        SurfaceTextureHelper.create(null, handler);
    // Create a mock listener and expect frames to be delivered on |thread|.
    final MockTextureListener listener = new MockTextureListener(thread);
    surfaceTextureHelper.setListener(listener);

    // Create resources for stubbing an OES texture producer. |eglOesBase| has the
    // SurfaceTexture in |surfaceTextureHelper| as the target EGLSurface.
    final EglBase eglOesBase = EglBase.create(null, EglBase.CONFIG_PLAIN);
    eglOesBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
    eglOesBase.makeCurrent();
    // Draw a frame onto the SurfaceTexture.
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    // swapBuffers() will ultimately trigger onTextureFrameAvailable().
    eglOesBase.swapBuffers();
    eglOesBase.release();

    // Wait for an OES texture to arrive.
    listener.waitForNewFrame();

    // Return the frame from this thread.
    surfaceTextureHelper.returnTextureFrame();
    surfaceTextureHelper.disconnect(handler);
  }

  /**
   * Test use SurfaceTextureHelper on a separate thread. A uniform texture frame is created and
   * received on a thread separate from the test thread and returned after disconnect.
   */
  @MediumTest
  public static void testLateReturnFrameOnSeparateThread() throws InterruptedException {
    final HandlerThread thread = new HandlerThread("SurfaceTextureHelperTestThread");
    thread.start();
    final Handler handler = new Handler(thread.getLooper());

    // Create SurfaceTextureHelper and listener.
    final SurfaceTextureHelper surfaceTextureHelper =
        SurfaceTextureHelper.create(null, handler);
    // Create a mock listener and expect frames to be delivered on |thread|.
    final MockTextureListener listener = new MockTextureListener(thread);
    surfaceTextureHelper.setListener(listener);

    // Create resources for stubbing an OES texture producer. |eglOesBase| has the
    // SurfaceTexture in |surfaceTextureHelper| as the target EGLSurface.
    final EglBase eglOesBase = EglBase.create(null, EglBase.CONFIG_PLAIN);
    eglOesBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
    eglOesBase.makeCurrent();
    // Draw a frame onto the SurfaceTexture.
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    // swapBuffers() will ultimately trigger onTextureFrameAvailable().
    eglOesBase.swapBuffers();
    eglOesBase.release();

    // Wait for an OES texture to arrive.
    listener.waitForNewFrame();

    surfaceTextureHelper.disconnect(handler);

    surfaceTextureHelper.returnTextureFrame();
  }
}
