// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package dev.cobalt.media;

import static dev.cobalt.media.Log.TAG;

import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioDeviceCallback;
import android.media.AudioDeviceInfo;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Build;
import androidx.annotation.RequiresApi;
import dev.cobalt.util.Log;
import dev.cobalt.util.UsedByNative;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/** Creates and destroys AudioTrackBridge and handles the volume change. */
public class AudioOutputManager implements CobaltMediaSession.UpdateVolumeListener {
  private List<AudioTrackBridge> audioTrackBridgeList;
  private Context context;

  AtomicBoolean hasAudioDeviceChanged = new AtomicBoolean(false);
  boolean hasRegisteredAudioDeviceCallback = false;

  public AudioOutputManager(Context context) {
    this.context = context;
    audioTrackBridgeList = new ArrayList<AudioTrackBridge>();
  }

  @Override
  public void onUpdateVolume(float gain) {
    for (AudioTrackBridge audioTrackBridge : audioTrackBridgeList) {
      audioTrackBridge.setVolume(gain);
    }
  }

  @SuppressWarnings("unused")
  @UsedByNative
  AudioTrackBridge createAudioTrackBridge(
      int sampleType,
      int sampleRate,
      int channelCount,
      int preferredBufferSizeInBytes,
      boolean enableAudioDeviceCallback,
      boolean enablePcmContentTypeMovie,
      int tunnelModeAudioSessionId,
      boolean isWebAudio) {
    AudioTrackBridge audioTrackBridge =
        new AudioTrackBridge(
            sampleType,
            sampleRate,
            channelCount,
            preferredBufferSizeInBytes,
            enablePcmContentTypeMovie,
            tunnelModeAudioSessionId,
            isWebAudio);
    if (!audioTrackBridge.isAudioTrackValid()) {
      Log.e(TAG, "AudioTrackBridge has invalid audio track");
      return null;
    }
    audioTrackBridgeList.add(audioTrackBridge);
    hasAudioDeviceChanged.set(false);

    if (Build.VERSION.SDK_INT < 23
        || hasRegisteredAudioDeviceCallback
        || !enableAudioDeviceCallback) {
      return audioTrackBridge;
    }

    AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
    audioManager.registerAudioDeviceCallback(
        new AudioDeviceCallback() {
          // Since registering a callback triggers an immediate call to onAudioDevicesAdded() with
          // current devices, don't set |hasAudioDeviceChanged| for this initial call.
          private boolean initialDevicesAdded = false;

          private void handleConnectedDeviceChange(AudioDeviceInfo[] devices) {
            for (AudioDeviceInfo info : devices) {
              // TODO: Determine if AudioDeviceInfo.TYPE_HDMI_EARC should be checked in API 31.
              if (info.isSink()
                  && (info.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_A2DP
                      || info.getType() == AudioDeviceInfo.TYPE_HDMI_ARC
                      || info.getType() == AudioDeviceInfo.TYPE_HDMI)) {
                // TODO: Avoid destroying the AudioTrack if the new devices can support the current
                // AudioFormat.
                Log.v(
                    TAG,
                    String.format(
                        "Setting |hasAudioDeviceChanged| to true for audio device %s, %s.",
                        info.getProductName(), getDeviceTypeNameV23(info.getType())));
                hasAudioDeviceChanged.set(true);
                break;
              }
            }
          }

          @Override
          public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
            Log.v(
                TAG,
                String.format(
                    "onAudioDevicesAdded() called, |initialDevicesAdded| is: %b.",
                    initialDevicesAdded));
            if (initialDevicesAdded) {
              handleConnectedDeviceChange(addedDevices);
              return;
            }
            initialDevicesAdded = true;
          }

          @Override
          public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
            Log.v(TAG, "onAudioDevicesRemoved() called.");
            handleConnectedDeviceChange(removedDevices);
          }
        },
        null);
    hasRegisteredAudioDeviceCallback = true;
    return audioTrackBridge;
  }

  @SuppressWarnings("unused")
  @UsedByNative
  void destroyAudioTrackBridge(AudioTrackBridge audioTrackBridge) {
    audioTrackBridge.release();
    audioTrackBridgeList.remove(audioTrackBridge);
  }

  /** Returns the maximum number of HDMI channels. */
  @SuppressWarnings("unused")
  @UsedByNative
  int getMaxChannels() {
    // The aac audio decoder on this platform will switch its output from 5.1
    // to stereo right before providing the first output buffer when
    // attempting to decode 5.1 input.  Since this heavily violates invariants
    // of the shared starboard player framework, disable 5.1 on this platform.
    // It is expected that we will be able to resolve this issue with Xiaomi
    // by Android P, so only do this workaround for SDK versions < 27.
    if (android.os.Build.MODEL.equals("MIBOX3") && android.os.Build.VERSION.SDK_INT < 27) {
      return 2;
    }

    if (Build.VERSION.SDK_INT >= 23) {
      return getMaxChannelsV23();
    }
    return 2;
  }

  /** Returns the maximum number of HDMI channels for API 23 and above. */
  @RequiresApi(23)
  private int getMaxChannelsV23() {
    AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
    AudioDeviceInfo[] deviceInfos = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
    int maxChannels = 2;
    for (AudioDeviceInfo info : deviceInfos) {
      int type = info.getType();
      if (type == AudioDeviceInfo.TYPE_HDMI || type == AudioDeviceInfo.TYPE_HDMI_ARC) {
        int[] channelCounts = info.getChannelCounts();
        if (channelCounts.length == 0) {
          // An empty array indicates that the device supports arbitrary channel masks.
          return 8;
        }
        for (int count : channelCounts) {
          maxChannels = Math.max(maxChannels, count);
        }
      }
    }
    return maxChannels;
  }

  /** Convert AudioDeviceInfo.TYPE_* to name in String */
  @RequiresApi(23)
  private static String getDeviceTypeNameV23(int device_type) {
    switch (device_type) {
      case AudioDeviceInfo.TYPE_AUX_LINE:
        return "TYPE_AUX_LINE";
      case AudioDeviceInfo.TYPE_BLUETOOTH_A2DP:
        return "TYPE_BLUETOOTH_A2DP";
      case AudioDeviceInfo.TYPE_BLUETOOTH_SCO:
        return "TYPE_BLUETOOTH_SCO";
      case AudioDeviceInfo.TYPE_BUILTIN_EARPIECE:
        return "TYPE_BUILTIN_EARPIECE";
      case AudioDeviceInfo.TYPE_BUILTIN_MIC:
        return "TYPE_BUILTIN_MIC";
      case AudioDeviceInfo.TYPE_BUILTIN_SPEAKER:
        return "TYPE_BUILTIN_SPEAKER";
      case AudioDeviceInfo.TYPE_BUS:
        return "TYPE_BUS";
      case AudioDeviceInfo.TYPE_DOCK:
        return "TYPE_DOCK";
      case AudioDeviceInfo.TYPE_FM:
        return "TYPE_FM";
      case AudioDeviceInfo.TYPE_FM_TUNER:
        return "TYPE_FM_TUNER";
      case AudioDeviceInfo.TYPE_HDMI:
        return "TYPE_HDMI";
      case AudioDeviceInfo.TYPE_HDMI_ARC:
        return "TYPE_HDMI_ARC";
      case AudioDeviceInfo.TYPE_IP:
        return "TYPE_IP";
      case AudioDeviceInfo.TYPE_LINE_ANALOG:
        return "TYPE_LINE_ANALOG";
      case AudioDeviceInfo.TYPE_LINE_DIGITAL:
        return "TYPE_LINE_DIGITAL";
      case AudioDeviceInfo.TYPE_TELEPHONY:
        return "TYPE_TELEPHONY";
      case AudioDeviceInfo.TYPE_TV_TUNER:
        return "TYPE_TV_TUNER";
      case AudioDeviceInfo.TYPE_UNKNOWN:
        return "TYPE_UNKNOWN";
      case AudioDeviceInfo.TYPE_USB_ACCESSORY:
        return "TYPE_USB_ACCESSORY";
      case AudioDeviceInfo.TYPE_USB_DEVICE:
        return "TYPE_USB_DEVICE";
      case AudioDeviceInfo.TYPE_WIRED_HEADPHONES:
        return "TYPE_WIRED_HEADPHONES";
      case AudioDeviceInfo.TYPE_WIRED_HEADSET:
        return "TYPE_WIRED_HEADSET";
      default:
        // This may include constants introduced after API 23.
        return String.format("TYPE_UNKNOWN (%d)", device_type);
    }
  }

  /** Convert audio encodings in int[] to common separated values in String */
  @RequiresApi(23)
  private static String getEncodingNames(final int[] encodings) {
    StringBuffer encodings_in_string = new StringBuffer("[");
    for (int i = 0; i < encodings.length; ++i) {
      switch (encodings[i]) {
        case AudioFormat.ENCODING_DEFAULT:
          encodings_in_string.append("DEFAULT");
          break;
        case AudioFormat.ENCODING_PCM_8BIT:
          encodings_in_string.append("PCM_8BIT");
          break;
        case AudioFormat.ENCODING_PCM_16BIT:
          encodings_in_string.append("PCM_16BIT");
          break;
        case AudioFormat.ENCODING_PCM_FLOAT:
          encodings_in_string.append("PCM_FLOAT");
          break;
        case AudioFormat.ENCODING_DTS:
          encodings_in_string.append("DTS");
          break;
        case AudioFormat.ENCODING_DTS_HD:
          encodings_in_string.append("DTS_HD");
          break;
        case AudioFormat.ENCODING_AC3:
          encodings_in_string.append("AC3");
          break;
        case AudioFormat.ENCODING_E_AC3:
          encodings_in_string.append("E_AC3");
          break;
        case AudioFormat.ENCODING_IEC61937:
          encodings_in_string.append("IEC61937");
          break;
        case AudioFormat.ENCODING_INVALID:
          encodings_in_string.append("INVALID");
          break;
        default:
          // This may include constants introduced after API 23.
          encodings_in_string.append(String.format("UNKNOWN (%d)", encodings[i]));
          break;
      }
      if (i != encodings.length - 1) {
        encodings_in_string.append(", ");
      }
    }
    encodings_in_string.append(']');
    return encodings_in_string.toString();
  }

  /** Dump all audio output devices. */
  public void dumpAllOutputDevices() {
    if (Build.VERSION.SDK_INT < 23) {
      Log.i(TAG, "dumpAllOutputDevices() is only supported in API level 23 or above.");
      return;
    }

    Log.i(TAG, "Dumping all audio output devices:");

    AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
    AudioDeviceInfo[] deviceInfos = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);

    for (AudioDeviceInfo info : deviceInfos) {
      Log.i(
          TAG,
          String.format(
              "  Audio Device: %s, channels: %s, sample rates: %s, encodings: %s",
              getDeviceTypeNameV23(info.getType()),
              Arrays.toString(info.getChannelCounts()),
              Arrays.toString(info.getSampleRates()),
              getEncodingNames(info.getEncodings())));
    }
  }

  /** Returns the minimum buffer size of AudioTrack. */
  @SuppressWarnings("unused")
  @UsedByNative
  int getMinBufferSize(int sampleType, int sampleRate, int channelCount) {
    int channelConfig;
    switch (channelCount) {
      case 1:
        channelConfig = AudioFormat.CHANNEL_OUT_MONO;
        break;
      case 2:
        channelConfig = AudioFormat.CHANNEL_OUT_STEREO;
        break;
      case 6:
        channelConfig = AudioFormat.CHANNEL_OUT_5POINT1;
        break;
      default:
        throw new RuntimeException("Unsupported channel count: " + channelCount);
    }
    return AudioTrack.getMinBufferSize(sampleRate, channelConfig, sampleType);
  }

  /** Generate audio session id used by tunneled playback. */
  @SuppressWarnings("unused")
  @UsedByNative
  int generateTunnelModeAudioSessionId(int numberOfChannels) {
    // Android 9.0 (Build.VERSION.SDK_INT >= 28) support v2 sync header that
    // aligns sync header with audio frame size. V1 sync header has alignment
    // issues for multi-channel audio.
    if (Build.VERSION.SDK_INT < 28) {
      // Currently we only support int16 under tunnel mode.
      final int sampleSizeInBytes = 2;
      final int frameSizeInBytes = sampleSizeInBytes * numberOfChannels;
      if (AudioTrackBridge.AV_SYNC_HEADER_V1_SIZE % frameSizeInBytes != 0) {
        Log.w(
            TAG,
            String.format(
                "Disable tunnel mode due to sampleSizeInBytes (%d) * numberOfChannels (%d) isn't"
                    + " aligned to AV_SYNC_HEADER_V1_SIZE (%d).",
                sampleSizeInBytes, numberOfChannels, AudioTrackBridge.AV_SYNC_HEADER_V1_SIZE));
        return -1;
      }
    }
    AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
    return audioManager.generateAudioSessionId();
  }

  /** Returns whether passthrough on `encoding` is supported. */
  @SuppressWarnings("unused")
  @UsedByNative
  boolean hasPassthroughSupportFor(int encoding) {
    if (Build.VERSION.SDK_INT < 23) {
      Log.i(
          TAG,
          String.format(
              "Passthrough on encoding %d is rejected on api %d, as passthrough is only"
                  + " supported on api 23 or later.",
              encoding, Build.VERSION.SDK_INT));
      return false;
    }

    AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
    AudioDeviceInfo[] deviceInfos = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);

    // Some devices have issues on reporting playback capability and managing routing when Bluetooth
    // output is connected.  So e/ac3 support is disabled when Bluetooth output device is connected.
    for (AudioDeviceInfo info : deviceInfos) {
      if (info.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_A2DP) {
        Log.i(
            TAG,
            String.format(
                "Passthrough on encoding %d is disabled because Bluetooth output device is"
                    + " connected.",
                encoding));
        return false;
      }
    }

    // Sample rate is not provided when the function is called, assume it is 48000.
    final int DEFAULT_SURROUND_SAMPLE_RATE = 48000;

    if (hasPassthroughSupportForV23(deviceInfos, encoding)) {
      Log.i(
          TAG,
          String.format(
              "Passthrough on encoding %d is supported, as hasPassthroughSupportForV23() returns"
                  + " true.",
              encoding));
    } else {
      if (Build.VERSION.SDK_INT < 29) {
        Log.i(
            TAG,
            String.format(
                "Passthrough on encoding %d is rejected, as"
                    + " hasDirectSurroundPlaybackSupportForV29() is not called for api %d.",
                encoding, Build.VERSION.SDK_INT));
        return false;
      }
      if (hasDirectSurroundPlaybackSupportForV29(encoding, DEFAULT_SURROUND_SAMPLE_RATE)) {
        Log.i(
            TAG,
            String.format(
                "Passthrough on encoding %d is supported, as"
                    + " hasDirectSurroundPlaybackSupportForV29() returns true.",
                encoding));
      } else {
        Log.i(
            TAG,
            String.format(
                "Passthrough on encoding %d is not supported, as"
                    + " hasDirectSurroundPlaybackSupportForV29() returns false.",
                encoding));
        return false;
      }
    }

    Log.i(TAG, "Verify passthrough support by creating an AudioTrack.");

    try {
      AudioTrack audioTrack =
          new AudioTrack(
              getDefaultAudioAttributes(),
              getPassthroughAudioFormatFor(encoding, DEFAULT_SURROUND_SAMPLE_RATE),
              AudioTrack.getMinBufferSize(48000, AudioFormat.CHANNEL_OUT_5POINT1, encoding),
              AudioTrack.MODE_STREAM,
              AudioManager.AUDIO_SESSION_ID_GENERATE);
      audioTrack.release();
    } catch (Exception e) {
      // AudioTrack creation can fail if the audio is routed to an unexpected device. For example,
      // when the user has Bluetooth headphones connected, or when the encoding is EAC3 and both
      // HDMI and SPDIF are connected, where the output should fallback to AC3.
      Log.w(
          TAG,
          String.format(
              "Passthrough on encoding %d is disabled because creating AudioTrack raises"
                  + " exception: ",
              encoding),
          e);
      return false;
    }

    Log.i(TAG, "AudioTrack creation succeeded, passthrough support verified.");

    return true;
  }

  /** Returns whether passthrough on `encoding` is supported for API 23 and above. */
  @RequiresApi(23)
  private boolean hasPassthroughSupportForV23(final AudioDeviceInfo[] deviceInfos, int encoding) {
    for (AudioDeviceInfo info : deviceInfos) {
      final int type = info.getType();
      if (type != AudioDeviceInfo.TYPE_HDMI && type != AudioDeviceInfo.TYPE_HDMI_ARC) {
        continue;
      }
      // TODO: ExoPlayer uses ACTION_HDMI_AUDIO_PLUG to detect the encodings supported via
      //       passthrough, we should consider using it, and maybe other actions like
      //       ACTION_HEADSET_PLUG for general audio device switch/encoding detection.
      final int[] encodings = info.getEncodings();
      if (encodings.length == 0) {
        // Per https://developer.android.com/reference/android/media/AudioDeviceInfo#getEncodings()
        // an empty array indicates that the device supports arbitrary encodings.
        Log.i(
            TAG,
            String.format(
                "Passthrough on encoding %d is supported on %s, because getEncodings() returns"
                    + " an empty array.",
                encoding, getDeviceTypeNameV23(type)));
        return true;
      }
      for (int i = 0; i < encodings.length; ++i) {
        if (encodings[i] == encoding) {
          Log.i(
              TAG,
              String.format(
                  "Passthrough on encoding %d is supported on %s.",
                  encoding, getDeviceTypeNameV23(type)));
          return true;
        }
      }
      Log.i(
          TAG,
          String.format(
              "Passthrough on encoding %d is not supported on %s.",
              encoding, getDeviceTypeNameV23(type)));
    }
    Log.i(
        TAG,
        String.format("Passthrough on encoding %d is not supported on any devices.", encoding));
    return false;
  }

  @RequiresApi(29)
  /** Returns whether direct playback on surround `encoding` is supported for API 29 and above. */
  private boolean hasDirectSurroundPlaybackSupportForV29(int encoding, int sampleRate) {
    if (encoding != AudioFormat.ENCODING_AC3
        && encoding != AudioFormat.ENCODING_E_AC3
        && encoding != AudioFormat.ENCODING_E_AC3_JOC) {
      Log.w(
          TAG,
          String.format(
              "hasDirectSurroundPlaybackSupportForV29() encountered unsupported encoding %d.",
              encoding));
      return false;
    }

    boolean supported =
        AudioTrack.isDirectPlaybackSupported(
            getPassthroughAudioFormatFor(encoding, sampleRate), getDefaultAudioAttributes());
    Log.i(
        TAG,
        String.format(
            "isDirectPlaybackSupported() for encoding %d returned %b.", encoding, supported));
    return supported;
  }

  // TODO: Move utility functions into a separate class.
  /** Returns AudioFormat for surround `encoding` and `sampleRate`. */
  static AudioFormat getPassthroughAudioFormatFor(int encoding, int sampleRate) {
    return new AudioFormat.Builder()
        .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1)
        .setEncoding(encoding)
        .setSampleRate(sampleRate)
        .build();
  }

  /** Returns default AudioAttributes for surround playbacks. */
  static AudioAttributes getDefaultAudioAttributes() {
    // TODO: Turn this into a static variable after it is moved into a separate class.
    return new AudioAttributes.Builder()
        .setUsage(AudioAttributes.USAGE_MEDIA)
        .setContentType(AudioAttributes.CONTENT_TYPE_MOVIE)
        .build();
  }

  @UsedByNative
  private boolean getAndResetHasAudioDeviceChanged() {
    return hasAudioDeviceChanged.getAndSet(false);
  }
}
