
package com.reactlibrary;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.os.Environment;
import android.util.Base64;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import  java.lang.Object;

public class RNMergeImageModule extends ReactContextBaseJavaModule {

  private final ReactApplicationContext reactContext;
  public static Bitmap RotateBitmap(Bitmap source, float angle,boolean flipX,boolean flipY)
  {
    Matrix matrix = new Matrix();
    matrix.postRotate(angle);
    matrix.postScale(flipX?-1:1, flipY?-1:1, source.getWidth()/2, source.getHeight()/2);
    return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
  }
  public RNMergeImageModule(ReactApplicationContext reactContext) {
    super(reactContext);
    this.reactContext = reactContext;
  }

  public  String MergeImageBase64(String base64bg, String pathFrame, float fgLeftPos, float fgTopPos,String name,boolean flipX,boolean flipY,boolean rotate) {
    String pathOut="";
    Log("Bat dau:"+pathFrame);
    byte[] decodedString = Base64.decode(base64bg, Base64.DEFAULT);
    Bitmap bitmapBg = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);

    int widthBG = bitmapBg.getWidth();
    int heightBG = bitmapBg.getHeight();
    Bitmap bitmapFg = BitmapFactory.decodeFile(pathFrame);
    if(rotate){
      if(bitmapFg.getWidth()<bitmapFg.getHeight()){
        bitmapBg = RotateBitmap(bitmapBg,90,flipX,flipY);//xoay anh khi chup dung
      }
      else
        bitmapBg = RotateBitmap(bitmapBg,180,flipX,flipY);//xoay anh khi chup dung
    }
      // Calculate the size of the merged Bitmap
    float ratioFrame = (float) bitmapFg.getWidth()/bitmapFg.getHeight();
    float ratioBG = (float)bitmapBg.getWidth()/bitmapBg.getHeight();
      int mergedImageWidth = 0;
      int mergedImageHeight =0;
      Log(ratioBG+"|"+ratioFrame);
      int left=0,top=0;
    if(ratioBG > ratioFrame){
        mergedImageHeight = bitmapBg.getHeight();
        mergedImageWidth = (int)(mergedImageHeight*ratioFrame);
    }
    else {
        mergedImageWidth = bitmapBg.getWidth();
        mergedImageHeight = (int)(mergedImageWidth/ratioFrame);
        Log("TH2:"+mergedImageWidth+"|"+mergedImageHeight);
    }
      if(bitmapFg == null)
          Log("FR null:");
      else
          Log("FR ko null"+bitmapFg.getWidth()+"|"+bitmapFg.getHeight());
      Bitmap resize;
      if (bitmapFg.getWidth() == mergedImageWidth && bitmapFg.getHeight() == mergedImageHeight)
          resize = bitmapFg;
      else
          resize = GetResizedBitmap(bitmapFg,mergedImageWidth,mergedImageHeight);





    // Create the return Bitmap (and Canvas to draw on)
    Bitmap mergedBitmap = Bitmap.createBitmap(mergedImageWidth, mergedImageHeight, resize.getConfig());
    Canvas mergedBitmapCanvas = new Canvas(mergedBitmap);

    // Draw the background image
    mergedBitmapCanvas.drawBitmap(bitmapBg, (mergedImageWidth-bitmapBg.getWidth())/2f, (mergedImageHeight-bitmapBg.getHeight())/2, null);

    //Draw the foreground image
    if(resize == null)
      Log("null");
    else
      Log("ko null");
    mergedBitmapCanvas.drawBitmap(resize, fgLeftPos, fgTopPos, null);
    Log("Da merge xong");
    try {
      String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
      File file = new File(root + "/SmartCamera/"+name);
      file.mkdirs();
      if(file.exists())
        file.delete();
      pathOut = file.toString();
      Log("1");

      Log("2");
      FileOutputStream out = new FileOutputStream(file);
      Log("3");
      mergedBitmap.compress(Bitmap.CompressFormat.PNG, 100, out); // bmp is your Bitmap instance
      Log("4");
      // PNG is a lossless format, the compression factor (100) is ignored
    Log("Da luu xong");
    } catch (IOException e) {
      Log(e.toString());
    }
    return pathOut;

  }
  public  String MergeBitmaps(String pathBG, String pathFg, float fgLeftPos, float fgTopPos,String pathOut) {
    Log("Bat dau");
    Bitmap bitmapBg = BitmapFactory.decodeFile(pathBG);
    Bitmap bitmapFg = BitmapFactory.decodeFile(pathFg);
    // Calculate the size of the merged Bitmap
    int mergedImageWidth = Math.max(bitmapBg.getWidth(), bitmapFg.getWidth());
    int mergedImageHeight = Math.max(bitmapBg.getHeight(), bitmapFg.getHeight());

    // Create the return Bitmap (and Canvas to draw on)
    Bitmap mergedBitmap = Bitmap.createBitmap(mergedImageWidth, mergedImageHeight, bitmapBg.getConfig());
    Canvas mergedBitmapCanvas = new Canvas(mergedBitmap);

    // Draw the background image
    mergedBitmapCanvas.drawBitmap(bitmapBg, 0f, 0f, null);

    //Draw the foreground image
    mergedBitmapCanvas.drawBitmap(bitmapFg, fgLeftPos, fgTopPos, null);
    Log("Da merge xong");
    try {
      FileOutputStream out = new FileOutputStream(pathOut);
      mergedBitmap.compress(Bitmap.CompressFormat.PNG, 100, out); // bmp is your Bitmap instance
      // PNG is a lossless format, the compression factor (100) is ignored
      WritableMap payload1 = Arguments.createMap();
      // Put data to map
      payload1.putString("log", "da luu xong"+pathOut);
      SendApp("MergeBitmaps",payload1);
    } catch (IOException e) {
      Log(e.toString());
    }
    return pathOut;

  }
  public Bitmap GetResizedBitmap(Bitmap bm, int newWidth, int newHeight) {
    if(bm == null)
      Log("bm:null");
    else
      Log("bm:ko null");
    int width = bm.getWidth();
    int height = bm.getHeight();
    float scaleWidth = ((float) newWidth) / width;
    float scaleHeight = ((float) newHeight) / height;
    // CREATE A MATRIX FOR THE MANIPULATION
    Matrix matrix = new Matrix();
    // RESIZE THE BIT MAP
    matrix.postScale(scaleWidth, scaleHeight);

    Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
    bm.recycle();
    return resizedBitmap;
  }
  public String GetResizedFrame(String pathImg, int newWidth, int newHeight) {

    Bitmap bm = BitmapFactory.decodeFile(pathImg);
    int width = bm.getWidth();
    int height = bm.getHeight();
    float scaleWidth = ((float) newWidth) / width;
    float scaleHeight = ((float) newHeight) / height;
    // CREATE A MATRIX FOR THE MANIPULATION
    Matrix matrix = new Matrix();
    // RESIZE THE BIT MAP
    matrix.postScale(scaleWidth, scaleHeight);

    Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
    bm.recycle();

    return ImageUtil.convert(resizedBitmap);
  }
  public  void SendApp(String functionName,WritableMap payload){

    // Get EventEmitter from context and send event thanks to it
    this.reactContext
            .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
            .emit(functionName, payload);
  }
  public  void Log(String data){

    // Get EventEmitter from context and send event thanks to it
    WritableMap payload1 = Arguments.createMap();
    // Put data to map
    payload1.putString("log", data);
    this.reactContext
            .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
            .emit("MergeBitmaps", payload1);
  }
  @Override
  public String getName() {
    return "RNMergeImageModule";
  }
  @ReactMethod
  public void Merge(String pathBG,String pathLG,int x,int y,String pathOut,Promise promise){
    promise.resolve(MergeBitmaps(pathBG,pathLG,x,y,pathOut));
  }
  @ReactMethod
  public void MergeImageBase64(String base64BG,String pathframe,int x,int y,String name,boolean flipX,boolean flipsY,boolean rotate,Promise promise){
    promise.resolve(MergeImageBase64(base64BG,pathframe,x,y,name,flipX,flipsY,rotate));
  }
  @ReactMethod
  public void ResizeImageBase64(String base64frame,int x,int y,Promise promise){
    promise.resolve(GetResizedFrame(base64frame,x,y));
  }

}
class ImageUtil
{
  public static Bitmap convert(String base64Str) throws IllegalArgumentException
  {
    byte[] decodedBytes = Base64.decode(
            base64Str.substring(base64Str.indexOf(",")  + 1),
            Base64.DEFAULT
    );

    return BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.length);
  }

  public static String convert(Bitmap bitmap)
  {
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);

    return Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT);
  }

}
