
package jp.sourceforge.nicoro;

import java.nio.ByteBuffer;

public interface StreamAudioPlayerInterface {

    boolean isNull();

    /**
     * 再生の前準備
     */
    void prepareStart();

    /**
     * 終了させる
     */
    void finish();

    /**
     * {@link android.media.AudioTrack#release()}のみ行う
     */
    void release();

    /**
     * {@link #release()}プラスAudioTrackやバッファの開放を行う
     */
    void releaseAll();

    /**
     * FFmpegによって開始<br>
     * TODO 動画または音声のどちらかがない動画への対応
     * @param sample_rate
     * @param channels
     * @param sample_fmt
     */
    void startByFFmpeg(int sample_rate, int channels, int sample_fmt);

    /**
     * SWF再生によって開始
     * @param sampleRateInHz
     * @param channels
     */
    void startBySwf(int sampleRateInHz, int channels);

    int writeDummyDataAtSeek();

    /**
     * AudioTrackを活動中にさせるため、ダミーデータを書き込み続ける
     */
    void writeDummyDataAtSeekForAlive();

    /**
     * 冒頭に挿入したダミーデータの再生中か判定
     * @return
     */
    boolean isInDummyDataAtStart();

    boolean isInDummyDataAtSeek();

    /**
     * 再生可能状態か判定
     * @return
     */
    boolean canPlay();

    /**
     * 一時停止
     */
    void pause();

    /**
     * 一時停止を解除
     */
    void restart();

    /**
     * ダミーデータを過ぎて、本当の音声部分が再生開始するまで待つ
     */
    void waitRealStartAtStart();

    /**
     * 再生が終了／完了するまで待つ
     */
    void waitPlayEnd();

    /**
     * 音声バッファのサイズをバイト単位で算出
     * @return
     */
    int getAudioBufferByteSize();

    /**
     * 音声バッファに格納可能な残りサイズをバイト単位で算出
     * @return
     */
    int getRemainBufferByteSize();

    /**
     * 音声データをバッファに書き込む
     * @param buffer 音声データ
     * @param sizeInShorts 音声データのサイズ（short単位）
     */
    void writeBuffer(short[] buffer, int sizeInShorts);

    void writeBuffer(ByteBuffer buffer, int sizeInShorts);

    void writeBufferOnlyPool(short[] buffer, int sizeInShorts);

    /**
     * 音声バッファを{@link android.media.AudioTrack}に転送
     */
    void flushBufferToAudioTrack();

    void flushAudioTrack();

    /**
     * キャッシュ済みの音声サイズをshort単位で取得
     * @return
     */
    int getCachedSize();

    /**
     * 音声バッファに十分なキャッシュがあるか判定
     * @return
     */
    boolean hasEnoughCache();

    int getAudioSampleByteSize();

    int getSampleRate();

    /**
     * 現在の再生位置を{@link Rational}で取得<br>
     * 現状シークすると若干誤差が発生する
     * @param rational
     */
    void getCurrentPosition(Rational rational);

    /**
     * デバイス上に再生待ちで残っている音声データのサイズを取得
     * @return
     */
    int getRemainDataSizeOnDeviceMs();

    void startSeek();

    void endSeek(int currentMilliSecond);

    /**
     * ダミーデータ再生中に一時停止を予約
     */
    void reservePause();

    public static class NullObject implements StreamAudioPlayerInterface {
        private static final NullObject sInstance = new NullObject();
        public static NullObject getInstance() {
            return sInstance;
        }

        private NullObject() {
        }

        @Override
        public boolean isNull() {
            return true;
        }

        @Override
        public void prepareStart() {
        }

        @Override
        public void finish() {
        }

        @Override
        public void release() {
        }

        @Override
        public void releaseAll() {
        }

        @Override
        public void startByFFmpeg(int sample_rate, int channels, int sample_fmt) {
        }

        @Override
        public void startBySwf(int sampleRateInHz, int channels) {
        }

        @Override
        public int writeDummyDataAtSeek() {
            return 0;
        }

        @Override
        public void writeDummyDataAtSeekForAlive() {
        }

        @Override
        public boolean isInDummyDataAtStart() {
            return false;
        }

        @Override
        public boolean isInDummyDataAtSeek() {
            return false;
        }

        @Override
        public boolean canPlay() {
            return false;
        }

        @Override
        public void pause() {
        }

        @Override
        public void restart() {
        }

        @Override
        public void waitRealStartAtStart() {
        }

        @Override
        public void waitPlayEnd() {
        }

        @Override
        public int getAudioBufferByteSize() {
            return 0;
        }

        @Override
        public int getRemainBufferByteSize() {
            return 0;
        }

        @Override
        public void writeBuffer(short[] buffer, int sizeInShorts) {
        }

        @Override
        public void writeBuffer(ByteBuffer buffer, int sizeInShorts) {
        }

        @Override
        public void writeBufferOnlyPool(short[] buffer, int sizeInShorts) {
        }

        @Override
        public void flushBufferToAudioTrack() {
        }

        @Override
        public void flushAudioTrack() {
        }

        @Override
        public int getCachedSize() {
            return 0;
        }

        @Override
        public boolean hasEnoughCache() {
            return false;
        }

        @Override
        public int getAudioSampleByteSize() {
            return 2 * 2;
        }

        @Override
        public int getSampleRate() {
            return 44100;
        }

        @Override
        public void getCurrentPosition(Rational rational) {
            rational.num = 0;
            rational.den = 1;
        }

        @Override
        public int getRemainDataSizeOnDeviceMs() {
            return 0;
        }

        @Override
        public void startSeek() {
        }

        @Override
        public void endSeek(int currentMilliSecond) {
        }

        @Override
        public void reservePause() {
        }

    }
}
