/*
 * Copyright (C) 2012 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.camera;

import android.annotation.TargetApi;
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaActionSound;
import android.media.SoundPool;
import android.os.Build;

import com.android.camera.debug.Log;
import com.android.camera.util.ApiHelper;
import com.android.camera2.R;

/*
 * This class controls the sound playback according to the API level.
 */
public class SoundClips {
    // Sound actions.
    public static final int FOCUS_COMPLETE = 0;
    public static final int START_VIDEO_RECORDING = 1;
    public static final int STOP_VIDEO_RECORDING = 2;
    public static final int SHUTTER_CLICK = 3;

    public interface Player {
        public void release();
        public void play(int action);
    }

    public static Player getPlayer(Context context) {
        if (ApiHelper.HAS_MEDIA_ACTION_SOUND) {
            return new MediaActionSoundPlayer();
        } else {
            return new SoundPoolPlayer(context);
        }
    }

    public static int getAudioTypeForSoundPool() {
        // STREAM_SYSTEM_ENFORCED is hidden API.
        return ApiHelper.getIntFieldIfExists(AudioManager.class,
                "STREAM_SYSTEM_ENFORCED", null, AudioManager.STREAM_RING);
    }

    /**
     * This class implements SoundClips.Player using MediaActionSound,
     * which exists since API level 16.
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    private static class MediaActionSoundPlayer implements Player {
        private static final Log.Tag TAG = new Log.Tag("MediaActSndPlayer");
        private MediaActionSound mSound;

        @Override
        public void release() {
            if (mSound != null) {
                mSound.release();
                mSound = null;
            }
        }

        public MediaActionSoundPlayer() {
            mSound = new MediaActionSound();
            mSound.load(MediaActionSound.START_VIDEO_RECORDING);
            mSound.load(MediaActionSound.STOP_VIDEO_RECORDING);
            mSound.load(MediaActionSound.FOCUS_COMPLETE);
            mSound.load(MediaActionSound.SHUTTER_CLICK);
        }

        @Override
        public synchronized void play(int action) {
            switch(action) {
                case FOCUS_COMPLETE:
                    mSound.play(MediaActionSound.FOCUS_COMPLETE);
                    break;
                case START_VIDEO_RECORDING:
                    mSound.play(MediaActionSound.START_VIDEO_RECORDING);
                    break;
                case STOP_VIDEO_RECORDING:
                    mSound.play(MediaActionSound.STOP_VIDEO_RECORDING);
                    break;
                case SHUTTER_CLICK:
                    mSound.play(MediaActionSound.SHUTTER_CLICK);
                    break;
                default:
                    Log.w(TAG, "Unrecognized action:" + action);
            }
        }
    }

    /**
     * This class implements SoundClips.Player using SoundPool, which
     * exists since API level 1.
     */
    private static class SoundPoolPlayer implements
            Player, SoundPool.OnLoadCompleteListener {

        private static final Log.Tag TAG = new Log.Tag("SoundPoolPlayer");
        private static final int NUM_SOUND_STREAMS = 1;
        private static final int[] SOUND_RES = { // Soundtrack res IDs.
                R.raw.focus_complete,
                R.raw.video_record,
        };

        // ID returned by load() should be non-zero.
        private static final int ID_NOT_LOADED = 0;

        // Maps a sound action to the id;
        private final int[] mSoundRes = {0, 1, 1, 1};
        // Store the context for lazy loading.
        private Context mContext;
        // mSoundPool is created every time load() is called and cleared every
        // time release() is called.
        private SoundPool mSoundPool;
        // Sound ID of each sound resources. Given when the sound is loaded.
        private final int[] mSoundIDs;
        private final boolean[] mSoundIDReady;
        private int mSoundIDToPlay;

        public SoundPoolPlayer(Context context) {
            mContext = context;

            mSoundIDToPlay = ID_NOT_LOADED;

            mSoundPool = new SoundPool(NUM_SOUND_STREAMS, getAudioTypeForSoundPool(), 0);
            mSoundPool.setOnLoadCompleteListener(this);

            mSoundIDs = new int[SOUND_RES.length];
            mSoundIDReady = new boolean[SOUND_RES.length];
            for (int i = 0; i < SOUND_RES.length; i++) {
                mSoundIDs[i] = mSoundPool.load(mContext, SOUND_RES[i], 1);
                mSoundIDReady[i] = false;
            }
        }

        @Override
        public synchronized void release() {
            if (mSoundPool != null) {
                mSoundPool.release();
                mSoundPool = null;
            }
        }

        @Override
        public synchronized void play(int action) {
            if (action < 0 || action >= mSoundRes.length) {
                Log.e(TAG, "Resource ID not found for action:" + action + " in play().");
                return;
            }

            int index = mSoundRes[action];
            if (mSoundIDs[index] == ID_NOT_LOADED) {
                // Not loaded yet, load first and then play when the loading is complete.
                mSoundIDs[index] = mSoundPool.load(mContext, SOUND_RES[index], 1);
                mSoundIDToPlay = mSoundIDs[index];
            } else if (!mSoundIDReady[index]) {
                // Loading and not ready yet.
                mSoundIDToPlay = mSoundIDs[index];
            } else {
                mSoundPool.play(mSoundIDs[index], 1f, 1f, 0, 0, 1f);
            }
        }

        @Override
        public void onLoadComplete(SoundPool pool, int soundID, int status) {
            if (status != 0) {
                Log.e(TAG, "loading sound tracks failed (status=" + status + ")");
                for (int i = 0; i < mSoundIDs.length; i++ ) {
                    if (mSoundIDs[i] == soundID) {
                        mSoundIDs[i] = ID_NOT_LOADED;
                        break;
                    }
                }
                return;
            }

            for (int i = 0; i < mSoundIDs.length; i++ ) {
                if (mSoundIDs[i] == soundID) {
                    mSoundIDReady[i] = true;
                    break;
                }
            }

            if (soundID == mSoundIDToPlay) {
                mSoundIDToPlay = ID_NOT_LOADED;
                mSoundPool.play(soundID, 1f, 1f, 0, 0, 1f);
            }
        }
    }
}
