// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.plugins.camerax;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.view.Display;
import android.view.Surface;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import io.flutter.embedding.engine.systemchannels.PlatformChannel;
import io.flutter.embedding.engine.systemchannels.PlatformChannel.DeviceOrientation;

/**
 * Support class to help to determine the media orientation based on the orientation of the device.
 */
public class DeviceOrientationManager {

  interface DeviceOrientationChangeCallback {
    void onChange(DeviceOrientation newOrientation);
  }

  private static final IntentFilter orientationIntentFilter =
      new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED);

  private final Activity activity;
  private final boolean isFrontFacing;
  private final int sensorOrientation;
  private final DeviceOrientationChangeCallback deviceOrientationChangeCallback;
  private PlatformChannel.DeviceOrientation lastOrientation;
  private BroadcastReceiver broadcastReceiver;

  DeviceOrientationManager(
      @NonNull Activity activity,
      boolean isFrontFacing,
      int sensorOrientation,
      DeviceOrientationChangeCallback callback) {
    this.activity = activity;
    this.isFrontFacing = isFrontFacing;
    this.sensorOrientation = sensorOrientation;
    this.deviceOrientationChangeCallback = callback;
  }

  /**
   * Starts listening to the device's sensors or UI for orientation updates.
   *
   * <p>When orientation information is updated, the callback method of the {@link
   * DeviceOrientationChangeCallback} is called with the new orientation. This latest value can also
   * be retrieved through the {@link #getVideoOrientation()} accessor.
   *
   * <p>If the device's ACCELEROMETER_ROTATION setting is enabled the {@link
   * DeviceOrientationManager} will report orientation updates based on the sensor information. If
   * the ACCELEROMETER_ROTATION is disabled the {@link DeviceOrientationManager} will fallback to
   * the deliver orientation updates based on the UI orientation.
   */
  public void start() {
    if (broadcastReceiver != null) {
      return;
    }
    broadcastReceiver =
        new BroadcastReceiver() {
          @Override
          public void onReceive(Context context, Intent intent) {
            handleUIOrientationChange();
          }
        };
    activity.registerReceiver(broadcastReceiver, orientationIntentFilter);
    broadcastReceiver.onReceive(activity, null);
  }

  /** Stops listening for orientation updates. */
  public void stop() {
    if (broadcastReceiver == null) {
      return;
    }
    activity.unregisterReceiver(broadcastReceiver);
    broadcastReceiver = null;
  }

  /**
   * Returns the device's photo orientation in degrees based on the sensor orientation and the last
   * known UI orientation.
   *
   * <p>Returns one of 0, 90, 180 or 270.
   *
   * @return The device's photo orientation in degrees.
   */
  public int getPhotoOrientation() {
    return this.getPhotoOrientation(this.lastOrientation);
  }

  /**
   * Returns the device's photo orientation in degrees based on the sensor orientation and the
   * supplied {@link PlatformChannel.DeviceOrientation} value.
   *
   * <p>Returns one of 0, 90, 180 or 270.
   *
   * @param orientation The {@link PlatformChannel.DeviceOrientation} value that is to be converted
   *     into degrees.
   * @return The device's photo orientation in degrees.
   */
  public int getPhotoOrientation(PlatformChannel.DeviceOrientation orientation) {
    int angle = 0;
    // Fallback to device orientation when the orientation value is null.
    if (orientation == null) {
      orientation = getUIOrientation();
    }

    switch (orientation) {
      case PORTRAIT_UP:
        angle = 90;
        break;
      case PORTRAIT_DOWN:
        angle = 270;
        break;
      case LANDSCAPE_LEFT:
        angle = isFrontFacing ? 180 : 0;
        break;
      case LANDSCAPE_RIGHT:
        angle = isFrontFacing ? 0 : 180;
        break;
    }

    // Sensor orientation is 90 for most devices, or 270 for some devices (eg. Nexus 5X).
    // This has to be taken into account so the JPEG is rotated properly.
    // For devices with orientation of 90, this simply returns the mapping from ORIENTATIONS.
    // For devices with orientation of 270, the JPEG is rotated 180 degrees instead.
    return (angle + sensorOrientation + 270) % 360;
  }

  /**
   * Returns the device's video orientation in clockwise degrees based on the sensor orientation and
   * the last known UI orientation.
   *
   * <p>Returns one of 0, 90, 180 or 270.
   *
   * @return The device's video orientation in clockwise degrees.
   */
  public int getVideoOrientation() {
    return this.getVideoOrientation(this.lastOrientation);
  }

  /**
   * Returns the device's video orientation in clockwise degrees based on the sensor orientation and
   * the supplied {@link PlatformChannel.DeviceOrientation} value.
   *
   * <p>Returns one of 0, 90, 180 or 270.
   *
   * <p>More details can be found in the official Android documentation:
   * https://developer.android.com/reference/android/media/MediaRecorder#setOrientationHint(int)
   *
   * <p>See also:
   * https://developer.android.com/training/camera2/camera-preview-large-screens#orientation_calculation
   *
   * @param orientation The {@link PlatformChannel.DeviceOrientation} value that is to be converted
   *     into degrees.
   * @return The device's video orientation in clockwise degrees.
   */
  public int getVideoOrientation(PlatformChannel.DeviceOrientation orientation) {
    int angle = 0;

    // Fallback to device orientation when the orientation value is null.
    if (orientation == null) {
      orientation = getUIOrientation();
    }

    switch (orientation) {
      case PORTRAIT_UP:
        angle = 0;
        break;
      case PORTRAIT_DOWN:
        angle = 180;
        break;
      case LANDSCAPE_LEFT:
        angle = 270;
        break;
      case LANDSCAPE_RIGHT:
        angle = 90;
        break;
    }

    if (isFrontFacing) {
      angle *= -1;
    }

    return (angle + sensorOrientation + 360) % 360;
  }

  /** @return the last received UI orientation. */
  public PlatformChannel.DeviceOrientation getLastUIOrientation() {
    return this.lastOrientation;
  }

  /**
   * Handles orientation changes based on change events triggered by the OrientationIntentFilter.
   *
   * <p>This method is visible for testing purposes only and should never be used outside this
   * class.
   */
  @VisibleForTesting
  void handleUIOrientationChange() {
    PlatformChannel.DeviceOrientation orientation = getUIOrientation();
    handleOrientationChange(orientation, lastOrientation, deviceOrientationChangeCallback);
    lastOrientation = orientation;
  }

  /**
   * Handles orientation changes coming from either the device's sensors or the
   * OrientationIntentFilter.
   *
   * <p>This method is visible for testing purposes only and should never be used outside this
   * class.
   */
  @VisibleForTesting
  static void handleOrientationChange(
      DeviceOrientation newOrientation,
      DeviceOrientation previousOrientation,
      DeviceOrientationChangeCallback callback) {
    if (!newOrientation.equals(previousOrientation)) {
      callback.onChange(newOrientation);
    }
  }

  /**
   * Gets the current user interface orientation.
   *
   * <p>This method is visible for testing purposes only and should never be used outside this
   * class.
   *
   * @return The current user interface orientation.
   */
  @VisibleForTesting
  PlatformChannel.DeviceOrientation getUIOrientation() {
    final int rotation = getDisplay().getRotation();
    final int orientation = activity.getResources().getConfiguration().orientation;

    switch (orientation) {
      case Configuration.ORIENTATION_PORTRAIT:
        if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90) {
          return PlatformChannel.DeviceOrientation.PORTRAIT_UP;
        } else {
          return PlatformChannel.DeviceOrientation.PORTRAIT_DOWN;
        }
      case Configuration.ORIENTATION_LANDSCAPE:
        if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90) {
          return PlatformChannel.DeviceOrientation.LANDSCAPE_LEFT;
        } else {
          return PlatformChannel.DeviceOrientation.LANDSCAPE_RIGHT;
        }
      default:
        return PlatformChannel.DeviceOrientation.PORTRAIT_UP;
    }
  }

  /**
   * Calculates the sensor orientation based on the supplied angle.
   *
   * <p>This method is visible for testing purposes only and should never be used outside this
   * class.
   *
   * @param angle Orientation angle.
   * @return The sensor orientation based on the supplied angle.
   */
  @VisibleForTesting
  PlatformChannel.DeviceOrientation calculateSensorOrientation(int angle) {
    final int tolerance = 45;
    angle += tolerance;

    // Orientation is 0 in the default orientation mode. This is portrait-mode for phones
    // and landscape for tablets. We have to compensate for this by calculating the default
    // orientation, and apply an offset accordingly.
    int defaultDeviceOrientation = getDeviceDefaultOrientation();
    if (defaultDeviceOrientation == Configuration.ORIENTATION_LANDSCAPE) {
      angle += 90;
    }
    // Determine the orientation
    angle = angle % 360;
    return new PlatformChannel.DeviceOrientation[] {
          PlatformChannel.DeviceOrientation.PORTRAIT_UP,
          PlatformChannel.DeviceOrientation.LANDSCAPE_LEFT,
          PlatformChannel.DeviceOrientation.PORTRAIT_DOWN,
          PlatformChannel.DeviceOrientation.LANDSCAPE_RIGHT,
        }
        [angle / 90];
  }

  /**
   * Gets the default orientation of the device.
   *
   * <p>This method is visible for testing purposes only and should never be used outside this
   * class.
   *
   * @return The default orientation of the device.
   */
  @VisibleForTesting
  int getDeviceDefaultOrientation() {
    Configuration config = activity.getResources().getConfiguration();
    int rotation = getDisplay().getRotation();
    if (((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180)
            && config.orientation == Configuration.ORIENTATION_LANDSCAPE)
        || ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270)
            && config.orientation == Configuration.ORIENTATION_PORTRAIT)) {
      return Configuration.ORIENTATION_LANDSCAPE;
    } else {
      return Configuration.ORIENTATION_PORTRAIT;
    }
  }

  /**
   * Gets an instance of the Android {@link android.view.Display}.
   *
   * <p>This method is visible for testing purposes only and should never be used outside this
   * class.
   *
   * @return An instance of the Android {@link android.view.Display}.
   */
  @SuppressWarnings("deprecation")
  @VisibleForTesting
  Display getDisplay() {
    return ((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
  }
}
