package com.airbnb.android.react.navigation;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityOptionsCompat;
import android.view.ViewGroup;

import com.airbnb.android.R;
import com.facebook.react.ReactRootView;
import com.facebook.react.bridge.ReadableMap;

public final class ReactNativeIntents {
  static final String EXTRA_MODULE_NAME = "REACT_MODULE_NAME";
  static final String EXTRA_PROPS = "REACT_PROPS";
  static final String EXTRA_CODE = "code";
  static final String EXTRA_IS_DISMISS = "isDismiss";
  static final String INSTANCE_ID_PROP = "nativeNavigationInstanceId";
  static final String INITIAL_BAR_HEIGHT_PROP = "nativeNavigationInitialBarHeight";
  private static final String SHARED_ELEMENT_TRANSITION_GROUP_OPTION = "transitionGroup";
  private static ReactNavigationCoordinator coordinator = ReactNavigationCoordinator.sharedInstance;

  private ReactNativeIntents() {
  }

  @SuppressWarnings({"WeakerAccess", "unused"})
  public static void pushScreen(Activity activity, String moduleName) {
    pushScreen(activity, moduleName, null);
  }

  @SuppressWarnings("WeakerAccess")
  public static void pushScreen(Activity activity, String moduleName, @Nullable Bundle props) {
    // TODO: right now this is the same as presentScreen but eventually it should just do
    // a fragment transaction
    Intent intent = pushIntent(activity, moduleName, props);
    //noinspection unchecked
    Bundle options = ActivityOptionsCompat
            .makeSceneTransitionAnimation(activity)
            .toBundle();
    activity.startActivity(intent, options);
  }

  @SuppressWarnings("WeakerAccess")
  public static void presentScreen(Activity context, String moduleName) {
    presentScreen(context, moduleName, null);
  }


  @SuppressWarnings("WeakerAccess")
  public static void presentScreen(Activity activity, String moduleName, @Nullable Bundle props) {
    Intent intent = presentIntent(activity, moduleName, props);
    //noinspection unchecked
    Bundle options = ActivityOptionsCompat
            .makeSceneTransitionAnimation(activity)
            .toBundle();
    activity.startActivity(intent, options);
  }

  static Bundle getSharedElementOptionsBundle(
          Activity activity, Intent intent, @Nullable ReadableMap options) {
    ViewGroup transitionGroup = null;
    if (activity instanceof ReactInterface && options != null &&
            options.hasKey(SHARED_ELEMENT_TRANSITION_GROUP_OPTION)) {
      ReactRootView reactRootView = ((ReactInterface) activity).getReactRootView();
      transitionGroup = ViewUtils.findViewGroupWithTag(
              reactRootView,
              R.id.react_shared_element_group_id,
              options.getString(SHARED_ELEMENT_TRANSITION_GROUP_OPTION));
    }

    if (transitionGroup == null) {
      // Even though there is no transition group, we want the activity options to include a scene
      // transition so that we can postpone the enter transition.
      //noinspection unchecked
      return ActivityOptionsCompat.makeSceneTransitionAnimation(activity).toBundle();
    } else {
      ReactNativeUtils.setIsSharedElementTransition(intent);
      return AutoSharedElementCallback.getActivityOptionsBundle(activity, transitionGroup);
    }
  }

  static Intent pushIntent(Context context, String moduleName, @Nullable Bundle props) {
    Class destClass = coordinator.getOrDefault(moduleName).mode.getPushActivityClass();
    return new Intent(context, destClass)
            .putExtras(intentExtras(moduleName, props));
  }

  static Intent presentIntent(
          Context context, String moduleName, @Nullable Bundle props) {
    Class destClass = coordinator.getOrDefault(moduleName).mode.getPresentActivityClass();
    return new Intent(context, destClass)
            .putExtras(intentExtras(moduleName, props));
  }

  private static Bundle intentExtras(String moduleName, @Nullable Bundle props) {
    return new BundleBuilder()
            .putString(EXTRA_MODULE_NAME, moduleName)
            .putBundle(EXTRA_PROPS, props)
            .toBundle();
  }
}