package com.mybigday.rnmediameta;

import android.content.Context;
import android.graphics.Bitmap;
import wseemann.media.FFmpegMediaMetadataRetriever;
import android.util.Base64;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.WritableMap;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;

public class RNMediaMeta extends ReactContextBaseJavaModule {
  private Context context;

  public RNMediaMeta(ReactApplicationContext reactContext) {
    super(reactContext);

    this.context = (Context) reactContext;
  }

  @Override
  public String getName() {
    return "RNMediaMeta";
  }

  // Related to https://github.com/wseemann/FFmpegMediaMetadataRetriever/blob/master/gradle/fmmr-library/library/src/main/java/wseemann/media/FFmpegMediaMetadataRetriever.java#L632
  private final String[] metadatas = {
    "album",
    "album_artist",
    "comment",
    "copyright",
    "creation_time",
    "disc",
    "encoder",
    "encoded_by",
    "genre",
    "language",
    "performer",
    "publisher",
    "service_name",
    "service_provider",
    "track",
    "variant_bitrate",
    "icy_metadata",
    "framerate",
    "chapter_start_time",
    "chapter_end_time",
    "artist",
    "composer",
    "title",
    "date",
    "duration",
    "rotation"
  };

  private String convertToBase64(byte[] bytes) {
    return Base64.encodeToString(bytes, Base64.NO_WRAP);
  }

  private byte[] convertToBytes(Bitmap bmp) {
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    bmp.compress(Bitmap.CompressFormat.PNG, 75, stream);
    return stream.toByteArray();
  }

  private void putString(WritableMap map, String key, String value) {
    if (value != null) map.putString(key, value);
  }

  private void getMetadata(String path, Promise promise) {
    File f = new File(path);
    if (!f.exists() || f.isDirectory()) {
      promise.reject("-15", "file not found");
      return;
    }

    FFmpegMediaMetadataRetriever mmr = new FFmpegMediaMetadataRetriever();
    WritableMap result = Arguments.createMap();
    try {
      mmr.setDataSource(path);

      // check is media
      String audioCodec = mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_AUDIO_CODEC);
      String videoCodec = mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_VIDEO_CODEC);
      if (audioCodec == null && videoCodec == null) {
        promise.resolve(result);
        mmr.release();
        return;
      }

      // get all metadata
      for (String meta: metadatas) {
        putString(result, meta, mmr.extractMetadata(meta));
      }

      // get thumb
      Bitmap bmp = mmr.getFrameAtTime();
      if (bmp != null) {
        // Bitmap bmp2 = mmr.getFrameAtTime((long) 4E6, FFmpegMediaMetadataRetriever.OPTION_CLOSEST);
        // if (bmp2 != null) bmp = bmp2;
        byte[] bytes = convertToBytes(bmp);
        result.putInt("width", bmp.getWidth());
        result.putInt("height", bmp.getHeight());
        result.putString("thumb", convertToBase64(bytes));
      }
    } catch(Exception e) {
      e.printStackTrace();
    } finally {
      promise.resolve(result);
      mmr.release();
    }
  }

  @ReactMethod
  public void get(final String path, final Promise promise) {
    new Thread() {
      @Override
      public void run() {
        getMetadata(path, promise);
      }
    }.start();
  }
}
@@ -171,16 +171,48 @@
 .Base64;
+%0Aimport android.graphics.Matrix;
 %0A%0Aimport
@@ -3241,344 +3241,1476 @@
 p2;%0A
-        byte%5B%5D bytes = convertToBytes(bmp);%0A        result.putInt(%22width%22, bmp.getWidth());%0A        result.putInt(%22height%22, bmp.getHeight());%0A        result.putString(%22thumb%22, convertToBase64(bytes));%0A      %7D%0A    %7D catch(Exception e) %7B%0A      e.printStackTrace();%0A    %7D finally %7B%0A      promise.resolve(result);%0A      mmr.release();%0A    %7D
+%0A        // the image returned seems to be always in landscape mode and does not follow%0A        // the rotation of the video.%0A        // get the rotation from the metadata and apply the correction so the image is straight.%0A%0A        String rotation =  mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);%0A        String createTime =  mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_CREATION_TIME);%0A        String duration =  mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_DURATION);%0A%0A        if( rotation != null )  %7B%0A            Bitmap rotatedBmp = RotateBitmap(bmp, Float.parseFloat(rotation));%0A            if(rotatedBmp != null ) %7B%0A                bmp = rotatedBmp;%0A            %7D%0A        %7D%0A%0A        byte%5B%5D bytes = convertToBytes(bmp);%0A        result.putInt(%22width%22, bmp.getWidth());%0A        result.putInt(%22height%22, bmp.getHeight());%0A        result.putString(%22thumb%22, convertToBase64(bytes));%0A        result.putString(%22rotation%22, rotation);%0A        result.putString(%22createTime%22, createTime);%0A        result.putString(%22duration%22, duration);%0A      %7D%0A    %7D catch(Exception e) %7B%0A      e.printStackTrace();%0A    %7D finally %7B%0A      promise.resolve(result);%0A      mmr.release();%0A    %7D%0A  %7D%0A%0A  private Bitmap RotateBitmap(Bitmap source, float angle)%0A  %7B%0A      Matrix matrix = new Matrix();%0A      matrix.postRotate(angle);%0A      return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
 %0A  %7D

Fix video thumbnail orientation issue (#4)