package com.azesmway.rnunity;

import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Process;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.widget.FrameLayout;

import com.facebook.react.ReactActivity;
import com.unity3d.player.IUnityPlayerLifecycleEvents;
import com.unity3d.player.UnityPlayer;

public class UnityReactActivity extends ReactActivity implements IUnityPlayerLifecycleEvents {
   private static UnityReactActivity instance = null;

   public static UnityReactActivity getInstance() {
       return instance;
   }

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       requestWindowFeature(Window.FEATURE_NO_TITLE);

       getWindow().setFormat(android.graphics.PixelFormat.RGBA_8888);

       super.onCreate(savedInstanceState);

       instance = this;

       hideSystemUI();

       FrameLayout rootLayout = (FrameLayout) findViewById(android.R.id.content);

       String cmdLine = updateUnityCommandLineArguments(getIntent().getStringExtra("unity"));
       getIntent().putExtra("unity", cmdLine);

       mUnityPlayer = new UnityPlayer(this, this);
       // turn off hardwareAccelerated for unity view
       mUnityPlayer.getView().setLayerType(View.LAYER_TYPE_NONE, null);
       rootLayout.addView(mUnityPlayer, 0);
       mUnityPlayer.requestFocus();
   }

   private void hideSystemUI() {
       // Enables regular immersive mode.
       // For "lean back" mode, remove SYSTEM_UI_FLAG_IMMERSIVE.
       // Or for "sticky immersive," replace it with SYSTEM_UI_FLAG_IMMERSIVE_STICKY
       View decorView = getWindow().getDecorView();
       decorView.setSystemUiVisibility(
               View.SYSTEM_UI_FLAG_IMMERSIVE
                       // Set the content to appear under the system bars so that the
                       // content doesn't resize when the system bars hide and show.
                       | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                       | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                       | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                       // Hide the nav bar and status bar
                       | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                       | View.SYSTEM_UI_FLAG_FULLSCREEN);
   }

   public interface IUnityReceiver {
       void receiveHandshake();
       void receiveCommand(String message);
   }

   public IUnityReceiver unityReceiver;

   protected void setReceiver(IUnityReceiver receiver) {
       unityReceiver = receiver;
   }

   protected void sendMessage(String message) {}

   public void unitySendHandshake() {
       if (unityReceiver != null) {
           runOnUiThread(new Runnable() {
               @Override
               public void run() {
                   unityReceiver.receiveHandshake();
               }
           });
       }
   }

   public void unitySendCommand(String arg) {
       if (unityReceiver != null) {
           final String finalArg = arg;
           runOnUiThread(new Runnable() {
               @Override
               public void run() {
                   unityReceiver.receiveCommand(finalArg);
               }
           });
       }
   }

   protected FrameLayout getUnityFrameLayout() {
       return mUnityPlayer;
   }

   // Unity 2020.1

   public static UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code

   // Override this in your custom UnityPlayerActivity to tweak the command line arguments passed to the Unity Android Player
   // The command line arguments are passed as a string, separated by spaces
   // UnityPlayerActivity calls this from 'onCreate'
   // Supported: -force-gles20, -force-gles30, -force-gles31, -force-gles31aep, -force-gles32, -force-gles, -force-vulkan
   // See https://docs.unity3d.com/Manual/CommandLineArguments.html
   // @param cmdLine the current command line arguments, may be null
   // @return the modified command line string or null
   protected String updateUnityCommandLineArguments(String cmdLine) {
       return cmdLine;
   }

   // When Unity player unloaded move task to background
   @Override public void onUnityPlayerUnloaded() {
       moveTaskToBack(true);
   }

   // Callback before Unity player process is killed
   @Override public void onUnityPlayerQuitted() {
   }

   @Override public void onNewIntent(Intent intent)
   {
       // To support deep linking, we need to make sure that the client can get access to
       // the last sent intent. The clients access this through a JNI api that allows them
       // to get the intent set on launch. To update that after launch we have to manually
       // replace the intent with the one caught here.
       setIntent(intent);
       mUnityPlayer.newIntent(intent);
   }

   // Quit Unity
   @Override protected void onDestroy ()
   {
       mUnityPlayer.destroy();
       super.onDestroy();
   }

   // Pause Unity
   @Override protected void onPause()
   {
       super.onPause();
       mUnityPlayer.pause();
   }

   // Resume Unity
   @Override protected void onResume()
   {
       super.onResume();
       mUnityPlayer.resume();
   }

   // Low Memory Unity
   @Override public void onLowMemory()
   {
       super.onLowMemory();
       mUnityPlayer.lowMemory();
   }

   // Trim Memory Unity
   @Override public void onTrimMemory(int level)
   {
       super.onTrimMemory(level);
       if (level == TRIM_MEMORY_RUNNING_CRITICAL)
       {
           mUnityPlayer.lowMemory();
       }
   }

   // This ensures the layout will be correct.
   @Override public void onConfigurationChanged(Configuration newConfig)
   {
       super.onConfigurationChanged(newConfig);
       mUnityPlayer.configurationChanged(newConfig);
   }

   // Notify Unity of the focus change.
   @Override public void onWindowFocusChanged(boolean hasFocus)
   {
       super.onWindowFocusChanged(hasFocus);
       mUnityPlayer.windowFocusChanged(hasFocus);
   }

   // For some reason the multiple keyevent type is not supported by the ndk.
   // Force event injection by overriding dispatchKeyEvent().
   @Override public boolean dispatchKeyEvent(KeyEvent event)
   {
       if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
           return mUnityPlayer.injectEvent(event);
       return super.dispatchKeyEvent(event);
   }

   // Pass any events not handled by (unfocused) views straight to UnityPlayer
   @Override public boolean onKeyUp(int keyCode, KeyEvent event)     { return mUnityPlayer.injectEvent(event); }
   @Override public boolean onKeyDown(int keyCode, KeyEvent event)   { return mUnityPlayer.injectEvent(event); }
   @Override public boolean onTouchEvent(MotionEvent event)          { return mUnityPlayer.injectEvent(event); }
   /*API12*/ public boolean onGenericMotionEvent(MotionEvent event)  { return mUnityPlayer.injectEvent(event); }
}
