// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package dev.flutter.scenarios;

import android.content.res.AssetFileDescriptor;
import android.graphics.Canvas;
import android.graphics.ImageFormat;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Shader.TileMode;
import android.graphics.SurfaceTexture;
import android.hardware.HardwareBuffer;
import android.media.Image;
import android.media.ImageReader;
import android.media.ImageWriter;
import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.view.Gravity;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.FrameLayout.LayoutParams;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.util.Supplier;
import io.flutter.view.TextureRegistry.SurfaceTextureEntry;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

public class ExternalTextureFlutterActivity extends TestActivity {
  static final String TAG = "Scenarios";
  private static final int SURFACE_WIDTH = 192;
  private static final int SURFACE_HEIGHT = 256;

  private SurfaceRenderer surfaceViewRenderer, flutterRenderer;

  // Latch used to ensure both SurfaceRenderers produce a frame before taking a screenshot.
  private final CountDownLatch firstFrameLatch = new CountDownLatch(2);

  private long textureId = 0;
  private SurfaceTextureEntry surfaceTextureEntry;

  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    String surfaceRenderer = getIntent().getStringExtra("surface_renderer");
    surfaceViewRenderer = selectSurfaceRenderer(surfaceRenderer, getIntent().getExtras());
    flutterRenderer = selectSurfaceRenderer(surfaceRenderer, getIntent().getExtras());

    // Create and place a SurfaceView above the Flutter content.
    SurfaceView surfaceView = new SurfaceView(getContext());
    surfaceView.setZOrderMediaOverlay(true);
    surfaceView.setMinimumWidth(SURFACE_WIDTH);
    surfaceView.setMinimumHeight(SURFACE_HEIGHT);

    FrameLayout frameLayout = new FrameLayout(getContext());
    frameLayout.addView(
        surfaceView,
        new LayoutParams(
            ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT,
            Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL));

    addContentView(
        frameLayout,
        new ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

    SurfaceHolder surfaceHolder = surfaceView.getHolder();
    surfaceHolder.setFixedSize(SURFACE_WIDTH, SURFACE_HEIGHT);
    surfaceHolder.addCallback(new SurfaceRendererCallback(surfaceViewRenderer, firstFrameLatch));
  }

  @Override
  public void waitUntilFlutterRendered() {
    super.waitUntilFlutterRendered();

    try {
      firstFrameLatch.await(10, java.util.concurrent.TimeUnit.SECONDS);
    } catch (InterruptedException e) {
      throw new RuntimeException(e);
    }
  }

  private SurfaceRenderer selectSurfaceRenderer(String surfaceRenderer, Bundle extras) {
    switch (surfaceRenderer) {
      case "image":
        if (VERSION.SDK_INT >= VERSION_CODES.M) {
          // CanvasSurfaceRenderer doesn't work correctly when used with ImageSurfaceRenderer.
          // Use MediaSurfaceRenderer for now.
          return new ImageSurfaceRenderer(
              selectSurfaceRenderer("media", extras), extras.getParcelable("crop"));
        } else {
          throw new RuntimeException("ImageSurfaceRenderer not supported");
        }
      case "media":
        if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
          return new MediaSurfaceRenderer(this::createMediaExtractor, extras.getInt("rotation", 0));
        } else {
          throw new RuntimeException("MediaSurfaceRenderer not supported");
        }
      case "canvas":
      default:
        return new CanvasSurfaceRenderer();
    }
  }

  private MediaExtractor createMediaExtractor() {
    // Sample Video generated with FFMPEG.
    // ffmpeg -loop 1 -i ~/engine/src/flutter/lib/ui/fixtures/DashInNooglerHat.jpg -c:v libx264
    // -profile:v main -level:v 5.2 -t 1 -r 1 -vf scale=192:256 -b:v 1M sample.mp4
    try {
      MediaExtractor extractor = new MediaExtractor();
      AssetFileDescriptor afd = getAssets().openFd("sample.mp4");
      extractor.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
      return extractor;
    } catch (IOException e) {
      e.printStackTrace();
      throw new RuntimeException(e);
    }
  }

  @Override
  public void onPause() {
    surfaceViewRenderer.destroy();
    flutterRenderer.destroy();
    surfaceTextureEntry.release();
    super.onPause();
  }

  @Override
  public void onFlutterUiDisplayed() {
    surfaceTextureEntry = getFlutterEngine().getRenderer().createSurfaceTexture();
    SurfaceTexture surfaceTexture = surfaceTextureEntry.surfaceTexture();
    surfaceTexture.setDefaultBufferSize(SURFACE_WIDTH, SURFACE_HEIGHT);
    flutterRenderer.attach(new Surface(surfaceTexture), firstFrameLatch);
    flutterRenderer.repaint();
    textureId = surfaceTextureEntry.id();

    super.onFlutterUiDisplayed();
  }

  @Override
  protected void getScenarioParams(@NonNull Map<String, Object> args) {
    super.getScenarioParams(args);
    args.put("texture_id", textureId);
    args.put("texture_width", SURFACE_WIDTH);
    args.put("texture_height", SURFACE_HEIGHT);
  }

  private interface SurfaceRenderer {
    void attach(Surface surface, CountDownLatch onFirstFrame);

    void repaint();

    void destroy();
  }

  /** Paints a simple gradient onto the attached Surface. */
  private static class CanvasSurfaceRenderer implements SurfaceRenderer {
    private Surface surface;
    private CountDownLatch onFirstFrame;

    protected CanvasSurfaceRenderer() {}

    @Override
    public void attach(Surface surface, CountDownLatch onFirstFrame) {
      this.surface = surface;
      this.onFirstFrame = onFirstFrame;
    }

    @Override
    public void repaint() {
      Canvas canvas =
          VERSION.SDK_INT >= VERSION_CODES.M
              ? surface.lockHardwareCanvas()
              : surface.lockCanvas(null);
      Paint paint = new Paint();
      paint.setShader(
          new LinearGradient(
              0.0f,
              0.0f,
              canvas.getWidth(),
              canvas.getHeight(),
              new int[] {
                // Cyan (#00FFFF)
                0xFF00FFFF,
                // Magenta (#FF00FF)
                0xFFFF00FF,
                // Yellow (#FFFF00)
                0xFFFFFF00,
              },
              null,
              TileMode.REPEAT));
      canvas.drawPaint(paint);
      surface.unlockCanvasAndPost(canvas);

      if (onFirstFrame != null) {
        onFirstFrame.countDown();
        onFirstFrame = null;
      }
    }

    @Override
    public void destroy() {}
  }

  /** Decodes a sample video into the attached Surface. */
  @RequiresApi(VERSION_CODES.LOLLIPOP)
  private static class MediaSurfaceRenderer implements SurfaceRenderer {
    private final Supplier<MediaExtractor> extractorSupplier;
    private final int rotation;
    private CountDownLatch onFirstFrame;

    private Surface surface;
    private MediaExtractor extractor;
    private MediaFormat format;
    private Thread decodeThread;

    protected MediaSurfaceRenderer(Supplier<MediaExtractor> extractorSupplier, int rotation) {
      this.extractorSupplier = extractorSupplier;
      this.rotation = rotation;
    }

    @Override
    public void attach(Surface surface, CountDownLatch onFirstFrame) {
      this.surface = surface;
      this.onFirstFrame = onFirstFrame;

      extractor = extractorSupplier.get();
      format = extractor.getTrackFormat(0);

      // NOTE: MediaFormat.KEY_ROTATION was not available until 23+, but the key is still handled on
      // API 21+.
      format.setInteger("rotation-degrees", rotation);

      decodeThread = new Thread(this::decodeThreadMain);
      decodeThread.start();
    }

    private void decodeThreadMain() {
      try {
        MediaCodec codec = MediaCodec.createDecoderByType(format.getString(MediaFormat.KEY_MIME));
        codec.configure(format, surface, null, 0);
        codec.start();

        // Track 0 is always the video track, since the sample video doesn't contain audio.
        extractor.selectTrack(0);

        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
        boolean seenEOS = false;
        long startTimeNs = System.nanoTime();
        int frameCount = 0;

        while (true) {
          // Move samples (video frames) from the extractor into the decoder, as long as we haven't
          // consumed all samples.
          if (!seenEOS) {
            int inputBufferIndex = codec.dequeueInputBuffer(-1);
            ByteBuffer inputBuffer = codec.getInputBuffer(inputBufferIndex);
            int sampleSize = extractor.readSampleData(inputBuffer, 0);
            if (sampleSize >= 0) {
              long presentationTimeUs = extractor.getSampleTime();
              codec.queueInputBuffer(inputBufferIndex, 0, sampleSize, presentationTimeUs, 0);
              extractor.advance();
            } else {
              codec.queueInputBuffer(
                  inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
              seenEOS = true;
            }
          }

          // Then consume decoded video frames from the decoder. These frames are automatically
          // pushed to the attached Surface, so this schedules them for present.
          int outputBufferIndex = codec.dequeueOutputBuffer(bufferInfo, 10000);
          boolean lastBuffer = (bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
          if (outputBufferIndex >= 0) {
            if (bufferInfo.size > 0) {
              if (onFirstFrame != null) {
                onFirstFrame.countDown();
                onFirstFrame = null;
              }
              Log.w(TAG, "Presenting frame " + frameCount);
              frameCount++;

              codec.releaseOutputBuffer(
                  outputBufferIndex, startTimeNs + (bufferInfo.presentationTimeUs * 1000));
            }
          }

          // Exit the loop if there are no more frames available.
          if (lastBuffer) {
            break;
          }
        }

        codec.stop();
        codec.release();
        extractor.release();
      } catch (IOException e) {
        e.printStackTrace();
        throw new RuntimeException(e);
      }
    }

    @Override
    public void repaint() {}

    @Override
    public void destroy() {
      try {
        decodeThread.join();
      } catch (InterruptedException e) {
        e.printStackTrace();
        throw new RuntimeException(e);
      }
    }
  }

  /**
   * Takes frames from the inner SurfaceRenderer and feeds it through an ImageReader and ImageWriter
   * pair.
   */
  @RequiresApi(VERSION_CODES.M)
  private static class ImageSurfaceRenderer implements SurfaceRenderer {
    private final SurfaceRenderer inner;
    private final Rect crop;

    private CountDownLatch onFirstFrame;
    private ImageReader reader;
    private ImageWriter writer;

    private Handler handler;
    private HandlerThread handlerThread;

    private boolean canReadImage = true;
    private boolean canWriteImage = true;

    protected ImageSurfaceRenderer(SurfaceRenderer inner, Rect crop) {
      this.inner = inner;
      this.crop = crop;
    }

    @Override
    public void attach(Surface surface, CountDownLatch onFirstFrame) {
      this.onFirstFrame = onFirstFrame;
      if (VERSION.SDK_INT >= VERSION_CODES.Q) {
        // On Android Q+, use PRIVATE image format.
        // Also let the frame producer know the images will
        // be sampled from by the GPU.
        writer = ImageWriter.newInstance(surface, 3, ImageFormat.PRIVATE);
        reader =
            ImageReader.newInstance(
                SURFACE_WIDTH,
                SURFACE_HEIGHT,
                ImageFormat.PRIVATE,
                2,
                HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE);
      } else {
        // Before Android Q, this will change the format of the surface to match the images.
        writer = ImageWriter.newInstance(surface, 3);
        reader = ImageReader.newInstance(SURFACE_WIDTH, SURFACE_HEIGHT, writer.getFormat(), 2);
      }
      inner.attach(reader.getSurface(), null);

      handlerThread = new HandlerThread("image reader/writer thread");
      handlerThread.start();

      handler = new Handler(handlerThread.getLooper());
      reader.setOnImageAvailableListener(this::onImageAvailable, handler);
      writer.setOnImageReleasedListener(this::onImageReleased, handler);
    }

    private void onImageAvailable(ImageReader reader) {
      Log.v(TAG, "Image available");

      if (!canWriteImage) {
        // If the ImageWriter hasn't released the latest image, don't attempt to enqueue another
        // image.
        // Otherwise the reader writer pair locks up if the writer runs behind, as the reader runs
        // out of images and the writer has no more space for images.
        canReadImage = true;
        return;
      }

      canReadImage = false;
      Image image = reader.acquireLatestImage();
      image.setCropRect(crop);
      try {
        canWriteImage = false;
        writer.queueInputImage(image);
      } catch (IllegalStateException e) {
        // If the output surface disconnects, this method will be interrupted with an
        // IllegalStateException.
        // Simply log and return.
        Log.i(TAG, "Surface disconnected from ImageWriter", e);
        image.close();
        return;
      }

      Log.v(TAG, "Output image");

      if (onFirstFrame != null) {
        onFirstFrame.countDown();
        onFirstFrame = null;
      }
    }

    private void tryAcquireImage() {
      if (canReadImage) {
        onImageAvailable(reader);
      }
    }

    private void onImageReleased(ImageWriter imageWriter) {
      Log.v(TAG, "Image released");

      if (!canWriteImage) {
        canWriteImage = true;
        if (canReadImage) {
          // Try acquire the image in a handler message, as we may have another call to
          // onImageAvailable in the thread's message queue.
          handler.post(this::tryAcquireImage);
        }
      }
    }

    @Override
    public void repaint() {
      inner.repaint();
    }

    @Override
    public void destroy() {
      Log.i(TAG, "Destroying ImageSurfaceRenderer");
      inner.destroy();
      handler.post(this::destroyReaderWriter);
    }

    private void destroyReaderWriter() {
      writer.close();
      Log.i(TAG, "ImageWriter destroyed");
      reader.close();
      Log.i(TAG, "ImageReader destroyed");
      handlerThread.quitSafely();
    }
  }

  private static class SurfaceRendererCallback implements SurfaceHolder.Callback {
    final SurfaceRenderer surfaceRenderer;
    final CountDownLatch onFirstFrame;

    public SurfaceRendererCallback(SurfaceRenderer surfaceRenderer, CountDownLatch onFirstFrame) {
      this.surfaceRenderer = surfaceRenderer;
      this.onFirstFrame = onFirstFrame;
    }

    @Override
    public void surfaceCreated(@NonNull SurfaceHolder holder) {
      surfaceRenderer.attach(holder.getSurface(), onFirstFrame);
    }

    @Override
    public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
      surfaceRenderer.repaint();
    }

    @Override
    public void surfaceDestroyed(@NonNull SurfaceHolder holder) {}
  }
}
