/*
 *  Copyright 2014 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

package org.appspot.apprtc;

import org.appspot.apprtc.util.AppRTCUtils;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.preference.PreferenceManager;
import android.util.Log;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * AppRTCAudioManager manages all audio related parts of the AppRTC demo.
 */
public class AppRTCAudioManager {
  private static final String TAG = "AppRTCAudioManager";
  private static final String SPEAKERPHONE_AUTO = "auto";
  private static final String SPEAKERPHONE_TRUE = "true";
  private static final String SPEAKERPHONE_FALSE = "false";

  /**
   * AudioDevice is the names of possible audio devices that we currently
   * support.
   */
  // TODO(henrika): add support for BLUETOOTH as well.
  public enum AudioDevice {
    SPEAKER_PHONE,
    WIRED_HEADSET,
    EARPIECE,
  }

  private final Context apprtcContext;
  private final Runnable onStateChangeListener;
  private boolean initialized = false;
  private AudioManager audioManager;
  private int savedAudioMode = AudioManager.MODE_INVALID;
  private boolean savedIsSpeakerPhoneOn = false;
  private boolean savedIsMicrophoneMute = false;

  private final AudioDevice defaultAudioDevice;

  // Contains speakerphone setting: auto, true or false
  private final String useSpeakerphone;

  // Proximity sensor object. It measures the proximity of an object in cm
  // relative to the view screen of a device and can therefore be used to
  // assist device switching (close to ear <=> use headset earpiece if
  // available, far from ear <=> use speaker phone).
  private AppRTCProximitySensor proximitySensor = null;

  // Contains the currently selected audio device.
  private AudioDevice selectedAudioDevice;

  // Contains a list of available audio devices. A Set collection is used to
  // avoid duplicate elements.
  private final Set<AudioDevice> audioDevices = new HashSet<AudioDevice>();

  // Broadcast receiver for wired headset intent broadcasts.
  private BroadcastReceiver wiredHeadsetReceiver;

  // This method is called when the proximity sensor reports a state change,
  // e.g. from "NEAR to FAR" or from "FAR to NEAR".
  private void onProximitySensorChangedState() {
    if (!useSpeakerphone.equals(SPEAKERPHONE_AUTO)) {
      return;
    }

    // The proximity sensor should only be activated when there are exactly two
    // available audio devices.
    if (audioDevices.size() == 2 && audioDevices.contains(AppRTCAudioManager.AudioDevice.EARPIECE)
        && audioDevices.contains(AppRTCAudioManager.AudioDevice.SPEAKER_PHONE)) {
      if (proximitySensor.sensorReportsNearState()) {
        // Sensor reports that a "handset is being held up to a person's ear",
        // or "something is covering the light sensor".
        setAudioDevice(AppRTCAudioManager.AudioDevice.EARPIECE);
      } else {
        // Sensor reports that a "handset is removed from a person's ear", or
        // "the light sensor is no longer covered".
        setAudioDevice(AppRTCAudioManager.AudioDevice.SPEAKER_PHONE);
      }
    }
  }

  /** Construction */
  static AppRTCAudioManager create(Context context, Runnable deviceStateChangeListener) {
    return new AppRTCAudioManager(context, deviceStateChangeListener);
  }

  private AppRTCAudioManager(Context context, Runnable deviceStateChangeListener) {
    apprtcContext = context;
    onStateChangeListener = deviceStateChangeListener;
    audioManager = ((AudioManager) context.getSystemService(Context.AUDIO_SERVICE));

    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
    useSpeakerphone = sharedPreferences.getString(context.getString(R.string.pref_speakerphone_key),
        context.getString(R.string.pref_speakerphone_default));

    if (useSpeakerphone.equals(SPEAKERPHONE_FALSE)) {
      defaultAudioDevice = AudioDevice.EARPIECE;
    } else {
      defaultAudioDevice = AudioDevice.SPEAKER_PHONE;
    }

    // Create and initialize the proximity sensor.
    // Tablet devices (e.g. Nexus 7) does not support proximity sensors.
    // Note that, the sensor will not be active until start() has been called.
    proximitySensor = AppRTCProximitySensor.create(context, new Runnable() {
      // This method will be called each time a state change is detected.
      // Example: user holds his hand over the device (closer than ~5 cm),
      // or removes his hand from the device.
      public void run() {
        onProximitySensorChangedState();
      }
    });
    AppRTCUtils.logDeviceInfo(TAG);
  }

  public void init() {
    Log.d(TAG, "init");
    if (initialized) {
      return;
    }

    // Store current audio state so we can restore it when close() is called.
    savedAudioMode = audioManager.getMode();
    savedIsSpeakerPhoneOn = audioManager.isSpeakerphoneOn();
    savedIsMicrophoneMute = audioManager.isMicrophoneMute();

    // Request audio focus before making any device switch.
    audioManager.requestAudioFocus(
        null, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);

    // Start by setting MODE_IN_COMMUNICATION as default audio mode. It is
    // required to be in this mode when playout and/or recording starts for
    // best possible VoIP performance.
    // TODO(henrika): we migh want to start with RINGTONE mode here instead.
    audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);

    // Always disable microphone mute during a WebRTC call.
    setMicrophoneMute(false);

    // Do initial selection of audio device. This setting can later be changed
    // either by adding/removing a wired headset or by covering/uncovering the
    // proximity sensor.
    updateAudioDeviceState(hasWiredHeadset());

    // Register receiver for broadcast intents related to adding/removing a
    // wired headset (Intent.ACTION_HEADSET_PLUG).
    registerForWiredHeadsetIntentBroadcast();

    initialized = true;
  }

  public void close() {
    Log.d(TAG, "close");
    if (!initialized) {
      return;
    }

    unregisterForWiredHeadsetIntentBroadcast();

    // Restore previously stored audio states.
    setSpeakerphoneOn(savedIsSpeakerPhoneOn);
    setMicrophoneMute(savedIsMicrophoneMute);
    audioManager.setMode(savedAudioMode);
    audioManager.abandonAudioFocus(null);

    if (proximitySensor != null) {
      proximitySensor.stop();
      proximitySensor = null;
    }

    initialized = false;
  }

  /** Changes selection of the currently active audio device. */
  public void setAudioDevice(AudioDevice device) {
    Log.d(TAG, "setAudioDevice(device=" + device + ")");
    AppRTCUtils.assertIsTrue(audioDevices.contains(device));

    switch (device) {
      case SPEAKER_PHONE:
        setSpeakerphoneOn(true);
        selectedAudioDevice = AudioDevice.SPEAKER_PHONE;
        break;
      case EARPIECE:
        setSpeakerphoneOn(false);
        selectedAudioDevice = AudioDevice.EARPIECE;
        break;
      case WIRED_HEADSET:
        setSpeakerphoneOn(false);
        selectedAudioDevice = AudioDevice.WIRED_HEADSET;
        break;
      default:
        Log.e(TAG, "Invalid audio device selection");
        break;
    }
    onAudioManagerChangedState();
  }

  /** Returns current set of available/selectable audio devices. */
  public Set<AudioDevice> getAudioDevices() {
    return Collections.unmodifiableSet(new HashSet<AudioDevice>(audioDevices));
  }

  /** Returns the currently selected audio device. */
  public AudioDevice getSelectedAudioDevice() {
    return selectedAudioDevice;
  }

  /**
   * Registers receiver for the broadcasted intent when a wired headset is
   * plugged in or unplugged. The received intent will have an extra
   * 'state' value where 0 means unplugged, and 1 means plugged.
   */
  private void registerForWiredHeadsetIntentBroadcast() {
    IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);

    /** Receiver which handles changes in wired headset availability. */
    wiredHeadsetReceiver = new BroadcastReceiver() {
      private static final int STATE_UNPLUGGED = 0;
      private static final int STATE_PLUGGED = 1;
      private static final int HAS_NO_MIC = 0;
      private static final int HAS_MIC = 1;

      @Override
      public void onReceive(Context context, Intent intent) {
        int state = intent.getIntExtra("state", STATE_UNPLUGGED);
        int microphone = intent.getIntExtra("microphone", HAS_NO_MIC);
        String name = intent.getStringExtra("name");
        Log.d(TAG, "BroadcastReceiver.onReceive" + AppRTCUtils.getThreadInfo() + ": "
                + "a=" + intent.getAction() + ", s="
                + (state == STATE_UNPLUGGED ? "unplugged" : "plugged") + ", m="
                + (microphone == HAS_MIC ? "mic" : "no mic") + ", n=" + name + ", sb="
                + isInitialStickyBroadcast());

        boolean hasWiredHeadset = (state == STATE_PLUGGED);
        switch (state) {
          case STATE_UNPLUGGED:
            updateAudioDeviceState(hasWiredHeadset);
            break;
          case STATE_PLUGGED:
            if (selectedAudioDevice != AudioDevice.WIRED_HEADSET) {
              updateAudioDeviceState(hasWiredHeadset);
            }
            break;
          default:
            Log.e(TAG, "Invalid state");
            break;
        }
      }
    };

    apprtcContext.registerReceiver(wiredHeadsetReceiver, filter);
  }

  /** Unregister receiver for broadcasted ACTION_HEADSET_PLUG intent. */
  private void unregisterForWiredHeadsetIntentBroadcast() {
    apprtcContext.unregisterReceiver(wiredHeadsetReceiver);
    wiredHeadsetReceiver = null;
  }

  /** Sets the speaker phone mode. */
  private void setSpeakerphoneOn(boolean on) {
    boolean wasOn = audioManager.isSpeakerphoneOn();
    if (wasOn == on) {
      return;
    }
    audioManager.setSpeakerphoneOn(on);
  }

  /** Sets the microphone mute state. */
  private void setMicrophoneMute(boolean on) {
    boolean wasMuted = audioManager.isMicrophoneMute();
    if (wasMuted == on) {
      return;
    }
    audioManager.setMicrophoneMute(on);
  }

  /** Gets the current earpiece state. */
  private boolean hasEarpiece() {
    return apprtcContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
  }

  /**
   * Checks whether a wired headset is connected or not.
   * This is not a valid indication that audio playback is actually over
   * the wired headset as audio routing depends on other conditions. We
   * only use it as an early indicator (during initialization) of an attached
   * wired headset.
   */
  @Deprecated
  private boolean hasWiredHeadset() {
    return audioManager.isWiredHeadsetOn();
  }

  /** Update list of possible audio devices and make new device selection. */
  private void updateAudioDeviceState(boolean hasWiredHeadset) {
    // Update the list of available audio devices.
    audioDevices.clear();
    if (hasWiredHeadset) {
      // If a wired headset is connected, then it is the only possible option.
      audioDevices.add(AudioDevice.WIRED_HEADSET);
    } else {
      // No wired headset, hence the audio-device list can contain speaker
      // phone (on a tablet), or speaker phone and earpiece (on mobile phone).
      audioDevices.add(AudioDevice.SPEAKER_PHONE);
      if (hasEarpiece()) {
        audioDevices.add(AudioDevice.EARPIECE);
      }
    }
    Log.d(TAG, "audioDevices: " + audioDevices);

    // Switch to correct audio device given the list of available audio devices.
    if (hasWiredHeadset) {
      setAudioDevice(AudioDevice.WIRED_HEADSET);
    } else {
      setAudioDevice(defaultAudioDevice);
    }
  }

  /** Called each time a new audio device has been added or removed. */
  private void onAudioManagerChangedState() {
    Log.d(TAG, "onAudioManagerChangedState: devices=" + audioDevices + ", selected="
            + selectedAudioDevice);

    // Enable the proximity sensor if there are two available audio devices
    // in the list. Given the current implementation, we know that the choice
    // will then be between EARPIECE and SPEAKER_PHONE.
    if (audioDevices.size() == 2) {
      AppRTCUtils.assertIsTrue(audioDevices.contains(AudioDevice.EARPIECE)
          && audioDevices.contains(AudioDevice.SPEAKER_PHONE));
      // Start the proximity sensor.
      proximitySensor.start();
    } else if (audioDevices.size() == 1) {
      // Stop the proximity sensor since it is no longer needed.
      proximitySensor.stop();
    } else {
      Log.e(TAG, "Invalid device list");
    }

    if (onStateChangeListener != null) {
      // Run callback to notify a listening client. The client can then
      // use public getters to query the new state.
      onStateChangeListener.run();
    }
  }
}
