/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * 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 com.android.services.telephony;

import static android.media.AudioManager.RINGER_MODE_NORMAL;
import static android.media.AudioManager.RINGER_MODE_SILENT;

import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.os.Vibrator;
import android.provider.Settings;

/**
 * Plays an emergency tone when placing emergency calls on CDMA devices.
 */
class EmergencyTonePlayer {

    private static final int EMERGENCY_TONE_OFF = 0;
    private static final int EMERGENCY_TONE_ALERT = 1;
    private static final int EMERGENCY_TONE_VIBRATE = 2;

    private static final int ALERT_RELATIVE_VOLUME_PERCENT = 100;

    private static final int VIBRATE_LENGTH_MILLIS = 1000;
    private static final int VIBRATE_PAUSE_MILLIS = 1000;
    private static final long[] VIBRATE_PATTERN =
            new long[] { VIBRATE_LENGTH_MILLIS, VIBRATE_PAUSE_MILLIS};

    private static final AudioAttributes VIBRATION_ATTRIBUTES =
            new AudioAttributes.Builder()
                .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
                .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
                .build();

    private final Context mContext;
    private final AudioManager mAudioManager;
    private final Vibrator mVibrator;

    private ToneGenerator mToneGenerator;
    private int mSavedInCallVolume;
    private boolean mIsVibrating = false;

    EmergencyTonePlayer(Context context) {
        mContext = context;
        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
    }

    public void start() {
        switch (getToneSetting()) {
            case EMERGENCY_TONE_VIBRATE:
                startVibrate();
                break;
            case EMERGENCY_TONE_ALERT:
                startAlert();
                break;
            case EMERGENCY_TONE_OFF:
                // nothing;
                break;
        }
    }

    public void stop() {
        stopVibrate();
        stopAlert();
    }

    private void startVibrate() {
        int ringerMode = mAudioManager.getRingerMode();
        if (ringerMode == RINGER_MODE_SILENT) {
            Log.i(this, "startVibrate: skipping vibrate tone due to ringer mode %d", ringerMode);
            return;
        }

        if (!mIsVibrating) {
            mVibrator.vibrate(VIBRATE_PATTERN, 0, VIBRATION_ATTRIBUTES);
            mIsVibrating = true;
        }
    }

    private void stopVibrate() {
        if (mIsVibrating) {
            mVibrator.cancel();
            mIsVibrating = false;
        }
    }

    private void startAlert() {
        int ringerMode = mAudioManager.getRingerMode();
        if (ringerMode != RINGER_MODE_NORMAL) {
            Log.i(this, "startAlert: skipping emergency tone due to ringer mode %d", ringerMode);
            return;
        }

        if (mToneGenerator == null) {
            mToneGenerator = new ToneGenerator(
                    AudioManager.STREAM_VOICE_CALL, ALERT_RELATIVE_VOLUME_PERCENT);

            // Set the volume to max and save the old volume setting.
            mSavedInCallVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
            mAudioManager.setStreamVolume(
                    AudioManager.STREAM_VOICE_CALL,
                    mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL),
                    0);
            mToneGenerator.startTone(ToneGenerator.TONE_CDMA_EMERGENCY_RINGBACK);
        }
    }

    private void stopAlert() {
        if (mToneGenerator != null) {
            mToneGenerator.stopTone();
            mToneGenerator.release();
            mToneGenerator = null;

            mAudioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, mSavedInCallVolume, 0);
            mSavedInCallVolume = 0;
        }
    }

    private int getToneSetting() {
       return Settings.Global.getInt(
               mContext.getContentResolver(), Settings.Global.EMERGENCY_TONE, EMERGENCY_TONE_OFF);
    }
}
