package com.reactnativecompressor.Utils;

import static com.facebook.react.bridge.UiThreadUtil.runOnUiThread;

import android.media.MediaFormat;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.linkedin.android.litr.MediaTransformer;
import com.linkedin.android.litr.TransformationListener;
import com.linkedin.android.litr.TransformationOptions;
import com.linkedin.android.litr.analytics.TrackTransformationInfo;
import com.reactnativecompressor.Data.MediaTransformationListener;
import com.reactnativecompressor.Data.SourceMedia;
import com.reactnativecompressor.Data.TargetMedia;
import com.reactnativecompressor.Data.TransformationState;


import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class Utils {
  private static final String TAG = "react-native-compessor";

  public static String generateCacheFilePath(String extension, ReactApplicationContext reactContext) {
    File outputDir = reactContext.getCacheDir();

    return String.format("%s/%s." + extension, outputDir.getPath(), UUID.randomUUID().toString());
  }


  public static void compressVideo(String srcPath, String destinationPath, int resultWidth, int resultHeight, int videoBitRate, String uuid, Promise promise, ReactApplicationContext reactContext) {

    MediaTransformer mediaTransformer = new MediaTransformer(reactContext);

    SourceMedia sourceMedia = new SourceMedia();
    sourceMedia.uri = Uri.parse(srcPath);

    TargetMedia targetMedia = new TargetMedia();

    targetMedia.setTargetFile(new File(destinationPath));

    TransformationState transformationState = new TransformationState();
    transformationState.requestId = uuid;
    try {

      TransformationOptions transformationOptions = new TransformationOptions.Builder()
        .setGranularity(MediaTransformer.GRANULARITY_DEFAULT)
        .build();

      MediaFormat targetVideoFormat = MediaFormat.createVideoFormat(
        MediaFormat.MIMETYPE_VIDEO_AVC,
        resultWidth,
        resultHeight);
      targetVideoFormat.setInteger(MediaFormat.KEY_BIT_RATE, videoBitRate);
      targetVideoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
      targetVideoFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);

      mediaTransformer.transform(
        transformationState.requestId,
        sourceMedia.uri,
        targetMedia.targetFile.getPath(),
        targetVideoFormat,
        null,
        new TransformationListener() {
          @Override
          public void onStarted(@NonNull String id) {

          }

          @Override
          public void onProgress(@NonNull String id, float progress) {
            Log.d(TAG, "onProgress: "+progress);
              WritableMap params = Arguments.createMap();
              WritableMap data = Arguments.createMap();
              params.putString("uuid", uuid);
              data.putDouble("progress", progress);
              params.putMap("data", data);
              sendEvent(reactContext, "videoCompressProgress", params);
          }

          @Override
          public void onCompleted(@NonNull String id, @Nullable List<TrackTransformationInfo> trackTransformationInfos) {
            promise.resolve("file://"+destinationPath);
          }

          @Override
          public void onCancelled(@NonNull String id, @Nullable List<TrackTransformationInfo> trackTransformationInfos) {

          }

          @Override
          public void onError(@NonNull String id, @Nullable Throwable cause, @Nullable List<TrackTransformationInfo> trackTransformationInfos) {

          }
        },
        transformationOptions);

    } catch (Exception ex) {
      promise.reject(ex);
    }
  }

  public static void cancelCompressionHelper(ReactApplicationContext reactContext, String uuid) {
    try {

    } catch (Exception ignored) {
    }
  }

  private static void sendEvent(ReactContext reactContext,
                                String eventName,
                                @Nullable WritableMap params) {
    reactContext
      .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
      .emit(eventName, params);
  }

  public static String getRealPath(String fileUrl, ReactApplicationContext reactContext) {
    if (fileUrl.startsWith("content://")) {
      try {
        Uri uri = Uri.parse(fileUrl);
        fileUrl = RealPathUtil.getRealPath(reactContext, uri);
      } catch (Exception ex) {
        Log.d(TAG, " Please see this issue: https://github.com/Shobbak/react-native-compressor/issues/25");
      }
    }
    return fileUrl;
  }
}
