content: package com.idlefish.flutterboost.containers;
  
  import android.app.Activity;
  import android.os.Bundle;
  import android.util.Log;
  import android.view.View;
  
  import androidx.annotation.NonNull;
  
  import com.idlefish.flutterboost.FlutterBoost;
  import com.idlefish.flutterboost.FlutterBoostUtils;
  import com.idlefish.flutterboost.Messages;
  
  import java.util.HashMap;
  import java.util.Map;
  import java.util.UUID;
  
  import io.flutter.embedding.android.LifecycleView;
  import io.flutter.embedding.android.RenderMode;
  import io.flutter.embedding.android.TransparencyMode;
  import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener;
  
  import static com.idlefish.flutterboost.containers.FlutterActivityLaunchConfigs.EXTRA_UNIQUE_ID;
  import static com.idlefish.flutterboost.containers.FlutterActivityLaunchConfigs.EXTRA_URL;
  import static com.idlefish.flutterboost.containers.FlutterActivityLaunchConfigs.EXTRA_URL_PARAM;
  
  public class FlutterBoostView extends LifecycleView implements FlutterViewContainer {
      private static final String TAG = "FlutterBoostView";
      private final String who = UUID.randomUUID().toString();
      private Callback callback;
      private boolean hasCreated;
      private boolean hasDestroyed;
  
      private boolean hasDestroyed() {
          if (hasDestroyed) {
              Log.w(TAG, "Application attempted to call on a destroyed View", new Throwable());
          }
          return hasDestroyed;
      }
  
      @NonNull
      public static CachedEngineBuilder withCachedEngine() {
          return new CachedEngineBuilder();
      }
  
      public static class CachedEngineBuilder {
          private RenderMode renderMode = RenderMode.texture;
          private TransparencyMode transparencyMode = TransparencyMode.transparent;
          private boolean shouldAttachEngineToActivity = true;
          private String url;
          private HashMap<String, Object> params;
  
          private CachedEngineBuilder() {
          }
  
          @NonNull
          public CachedEngineBuilder renderMode(@NonNull RenderMode renderMode) {
              this.renderMode = renderMode;
              return this;
          }
  
          @NonNull
          public CachedEngineBuilder transparencyMode(
                  @NonNull TransparencyMode transparencyMode) {
              this.transparencyMode = transparencyMode;
              return this;
          }
  
          @NonNull
          protected Bundle createArgs() {
              Bundle args = new Bundle();
              args.putString(ARG_CACHED_ENGINE_ID, FlutterBoost.ENGINE_ID);
              args.putString(
                      ARG_FLUTTERVIEW_RENDER_MODE,
                      renderMode != null ? renderMode.name() : RenderMode.surface.name());
              args.putString(
                      ARG_FLUTTERVIEW_TRANSPARENCY_MODE,
                      transparencyMode != null ? transparencyMode.name() : TransparencyMode.transparent.name());
              args.putString(EXTRA_URL, url);
              args.putSerializable(EXTRA_URL_PARAM, params);
              args.putString(EXTRA_UNIQUE_ID, FlutterBoostUtils.createUniqueId(url));
              return args;
          }
  
          public FlutterBoostView build(Activity context) {
              return build(context, null);
          }
  
          @NonNull
          public FlutterBoostView build(Activity context, Callback callback) {
              FlutterBoostView view = new FlutterBoostView(context, callback);
              Bundle args = createArgs();
              view.setArguments(args);
              return view;
          }
  
          @NonNull
          public CachedEngineBuilder url(
                  @NonNull String url) {
              this.url = url;
              return this;
          }
  
          @NonNull
          public CachedEngineBuilder urlParams(@NonNull Map<String, Object> params) {
              this.params = (params instanceof HashMap) ? (HashMap)params : new HashMap<String, Object>(params);
              return this;
          }
      }
  
      private FlutterBoostView(Activity context, Callback callback) {
          super(context);
          this.callback = callback;
      }
  
  
      @Override
      public void onCreate() {
          super.onCreate();
          FlutterBoost.instance().getPlugin().onContainerCreated(this);
          onStart();
          hasCreated = true;
      }
  
      @Override
      public void onResume() {
          if(hasDestroyed()) return;
          if (!hasCreated) {
              onCreate();
          }
          super.onResume();
          FlutterBoost.instance().getPlugin().onContainerAppeared(this, () -> {
              flutterView().attachToFlutterEngine(getFlutterEngine());
          });
      }
  
      @Override
      public void onPause() {
          if(hasDestroyed()) return;
          super.onPause();
          flutterView().detachFromFlutterEngine();
      }
  
      @Override
      public void onStop() {
          if(hasDestroyed()) return;
          super.onStop();
          FlutterBoost.instance().getPlugin().onContainerDisappeared(this);
      }
  
      @Override
      public void onDestroy() {
          if(hasDestroyed()) return;
          if (hasCreated) {
              super.onDestroy();
              FlutterBoost.instance().getPlugin().onContainerDestroyed(this);
          }
          hasDestroyed = true;
      }
  
      @Override
      public void setVisibility(int visibility) {
          super.setVisibility(visibility);
          if (!hasCreated) {
              onCreate();
          }
  
          if (getVisibility() == View.VISIBLE) {
              FlutterBoost.instance().getPlugin().onContainerAppeared(this, () -> {
                  flutterView().attachToFlutterEngine(getFlutterEngine());
              });
          } else if (getVisibility() == View.GONE) {
              FlutterBoost.instance().getPlugin().onContainerDisappeared(this);
              flutterView().detachFromFlutterEngine();
          }
      }
  
      public void onBackPressed() {
          FlutterBoost.instance().getPlugin().onBackPressed();
      }
  
      @Override
      public Activity getContextActivity() {
          return getActivity();
      }
  
      @Override
      public void finishContainer(Map<String, Object> result) {
          if (callback != null) {
              callback.finishContainer(result);
          } else {
              getActivity().finish();
          }
      }
  
      @Override
      public String getCachedEngineId() {
        return getArguments().getString(ARG_CACHED_ENGINE_ID, FlutterBoost.ENGINE_ID);
      }
  
      public void onFlutterUiDisplayed() {
          if (callback != null) {
              callback.onFlutterUiDisplayed();
          } else {
              Activity attachedActivity = getActivity();
              if (attachedActivity instanceof FlutterUiDisplayListener) {
                  ((FlutterUiDisplayListener) attachedActivity).onFlutterUiDisplayed();
              }
          }
      }
  
      public void onFlutterUiNoLongerDisplayed() {
          if (callback != null) {
              callback.onFlutterUiNoLongerDisplayed();
          } else {
              Activity attachedActivity = getActivity();
              if (attachedActivity instanceof FlutterUiDisplayListener) {
                  ((FlutterUiDisplayListener) attachedActivity).onFlutterUiNoLongerDisplayed();
              }
          }
      }
  
      public String getUrl() {
          if (!getArguments().containsKey(EXTRA_URL)) {
              throw new RuntimeException("Oops! The view url are *MISSED*! You should "
                      + "override the |getUrl|, or set url via CachedEngineBuilder.");
          }
          return getArguments().getString(EXTRA_URL);
      }
  
      public Map<String, Object> getUrlParams() {
          return (HashMap<String, Object>)getArguments().getSerializable(EXTRA_URL_PARAM);
      }
  
      public String getUniqueId() {
          return getArguments().getString(EXTRA_UNIQUE_ID, this.who);
      }
  
      public interface Callback extends FlutterUiDisplayListener {
          void finishContainer(Map<String, Object> result);
          void onFlutterUiDisplayed();
          void onFlutterUiNoLongerDisplayed();
      }
  }