/*
 *  Copyright 2018 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.webrtc;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;

import org.chromium.testing.local.LocalRobolectricTestRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.annotation.Config;
import org.webrtc.GlShader;

@RunWith(LocalRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class GlGenericDrawerTest {
  // Simplest possible valid generic fragment shader.
  private static final String FRAGMENT_SHADER = "void main() {\n"
      + "  gl_FragColor = sample(tc);\n"
      + "}\n";
  private static final int TEXTURE_ID = 3;
  private static final float[] TEX_MATRIX =
      new float[] {1, 2, 3, 4, -1, -2, -3, -4, 0, 0, 1, 0, 0, 0, 0, 1};
  private static final int FRAME_WIDTH = 640;
  private static final int FRAME_HEIGHT = 480;
  private static final int VIEWPORT_X = 3;
  private static final int VIEWPORT_Y = 5;
  private static final int VIEWPORT_WIDTH = 500;
  private static final int VIEWPORT_HEIGHT = 500;

  // Replace OpenGLES GlShader dependency with a mock.
  private class GlGenericDrawerForTest extends GlGenericDrawer {
    public GlGenericDrawerForTest(String genericFragmentSource, ShaderCallbacks shaderCallbacks) {
      super(genericFragmentSource, shaderCallbacks);
    }

    @Override
    GlShader createShader(ShaderType shaderType) {
      return mockedShader;
    }
  }

  private GlShader mockedShader;
  private GlGenericDrawer glGenericDrawer;
  private GlGenericDrawer.ShaderCallbacks mockedCallbacks;

  @Before
  public void setUp() {
    mockedShader = mock(GlShader.class);
    mockedCallbacks = mock(GlGenericDrawer.ShaderCallbacks.class);
    glGenericDrawer = new GlGenericDrawerForTest(FRAGMENT_SHADER, mockedCallbacks);
  }

  @After
  public void tearDown() {
    verifyNoMoreInteractions(mockedCallbacks);
  }

  @Test
  public void testOesFragmentShader() {
    final String expectedOesFragmentShader = "#extension GL_OES_EGL_image_external : require\n"
        + "precision mediump float;\n"
        + "varying vec2 tc;\n"
        + "uniform samplerExternalOES tex;\n"
        + "void main() {\n"
        + "  gl_FragColor = texture2D(tex, tc);\n"
        + "}\n";
    final String oesFragmentShader =
        GlGenericDrawer.createFragmentShaderString(FRAGMENT_SHADER, GlGenericDrawer.ShaderType.OES);
    assertEquals(expectedOesFragmentShader, oesFragmentShader);
  }

  @Test
  public void testRgbFragmentShader() {
    final String expectedRgbFragmentShader = "precision mediump float;\n"
        + "varying vec2 tc;\n"
        + "uniform sampler2D tex;\n"
        + "void main() {\n"
        + "  gl_FragColor = texture2D(tex, tc);\n"
        + "}\n";
    final String rgbFragmentShader =
        GlGenericDrawer.createFragmentShaderString(FRAGMENT_SHADER, GlGenericDrawer.ShaderType.RGB);
    assertEquals(expectedRgbFragmentShader, rgbFragmentShader);
  }

  @Test
  public void testYuvFragmentShader() {
    final String expectedYuvFragmentShader = "precision mediump float;\n"
        + "varying vec2 tc;\n"
        + "uniform sampler2D y_tex;\n"
        + "uniform sampler2D u_tex;\n"
        + "uniform sampler2D v_tex;\n"
        + "vec4 sample(vec2 p) {\n"
        + "  float y = texture2D(y_tex, p).r;\n"
        + "  float u = texture2D(u_tex, p).r - 0.5;\n"
        + "  float v = texture2D(v_tex, p).r - 0.5;\n"
        + "  return vec4(y + 1.403 * v, y - 0.344 * u - 0.714 * v, y + 1.77 * u, 1);\n"
        + "}\n"
        + "void main() {\n"
        + "  gl_FragColor = sample(tc);\n"
        + "}\n";
    final String yuvFragmentShader =
        GlGenericDrawer.createFragmentShaderString(FRAGMENT_SHADER, GlGenericDrawer.ShaderType.YUV);
    assertEquals(expectedYuvFragmentShader, yuvFragmentShader);
  }

  @Test
  public void testShaderCallbacksOneRgbFrame() {
    glGenericDrawer.drawRgb(TEXTURE_ID, TEX_MATRIX, FRAME_WIDTH, FRAME_HEIGHT, VIEWPORT_X,
        VIEWPORT_Y, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);

    verify(mockedCallbacks).onNewShader(mockedShader);
    verify(mockedCallbacks)
        .onPrepareShader(
            mockedShader, TEX_MATRIX, FRAME_WIDTH, FRAME_HEIGHT, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
  }

  @Test
  public void testShaderCallbacksTwoRgbFrames() {
    glGenericDrawer.drawRgb(TEXTURE_ID, TEX_MATRIX, FRAME_WIDTH, FRAME_HEIGHT, VIEWPORT_X,
        VIEWPORT_Y, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
    glGenericDrawer.drawRgb(TEXTURE_ID, TEX_MATRIX, FRAME_WIDTH, FRAME_HEIGHT, VIEWPORT_X,
        VIEWPORT_Y, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);

    // Expect only one shader to be created, but two frames to be drawn.
    verify(mockedCallbacks, times(1)).onNewShader(mockedShader);
    verify(mockedCallbacks, times(2))
        .onPrepareShader(
            mockedShader, TEX_MATRIX, FRAME_WIDTH, FRAME_HEIGHT, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
  }

  @Test
  public void testShaderCallbacksChangingShaderType() {
    glGenericDrawer.drawRgb(TEXTURE_ID, TEX_MATRIX, FRAME_WIDTH, FRAME_HEIGHT, VIEWPORT_X,
        VIEWPORT_Y, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
    glGenericDrawer.drawOes(TEXTURE_ID, TEX_MATRIX, FRAME_WIDTH, FRAME_HEIGHT, VIEWPORT_X,
        VIEWPORT_Y, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);

    // Expect two shaders to be created, and two frames to be drawn.
    verify(mockedCallbacks, times(2)).onNewShader(mockedShader);
    verify(mockedCallbacks, times(2))
        .onPrepareShader(
            mockedShader, TEX_MATRIX, FRAME_WIDTH, FRAME_HEIGHT, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
  }
}
