
package jp.sourceforge.nicoro;

import static jp.sourceforge.nicoro.Log.LOG_TAG;

import android.app.Activity;
import android.os.AsyncTask;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;

public interface FFmpegVideoDecoderInterface extends FFmpegInfoCallback {

    public abstract static class PrepareFFmpegTask extends AsyncTask<Boolean, Void, Boolean> {
        private Exception mException;
        private FFmpegVideoDecoderInterface mDecoder;

        protected PrepareFFmpegTask(FFmpegVideoDecoderInterface decoder) {
            mDecoder = decoder;
        }

        @Override
        protected Boolean doInBackground(Boolean... params) {
            assert params.length == 1;
            boolean isOpened = params[0];
            try {
                return mDecoder.prepareFFmpeg(isOpened);
            } catch (IllegalArgumentException e) {
                Log.e(LOG_TAG, e.toString(), e);
                mException = e;
                return false;
            } catch (NullPointerException e) {
                if (mDecoder.isFinish()) {
                    // XXX 動画再生準備と並行してnative instanceが解放された可能性
                    Log.w(LOG_TAG, e.toString(), e);
                    return false;
                } else {
                    throw e;
                }
            }
        }

        public void executeWrapper(boolean isOpened) {
            execute(isOpened);
        }
        public Exception getException() {
            return mException;
        }
    }

    public interface CreateDrawBufferListener {
        void onCreateDrawBuffer(FFmpegVideoDecoderInterface decoder);
    }

    boolean isNull();

    void quit();

    void quitAsync(ExecutorService executorService, final CountDownLatch latch);

    void seekBySecond(int second);

    void pause();

    void restart();

    boolean prepareFFmpeg(boolean isOpened);

    void prepareDecode();

    void destroyNativeInstance();

    void getCurrentPositionVideoDecode(Rational rational);

    void getCurrentPositionAudioDecode(Rational rational);

    void updateSurfaceSize();

    int getVideoOriginalWidth();

    int getVideoOriginalHeight();

    void setCacheDecodeFirst(boolean use);

    void updateDisplayMetrics(Activity activity);

    void updateDisplaySize(int width, int height);

    void setOrientation(int orientation);

    void setIsVisible(boolean isVisible);

    void start();

    boolean isFinish();

    void setCreateDrawBufferListener(CreateDrawBufferListener listener);

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

        private NullObject() {
        }

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

        @Override
        public void createDrawBufferFromNativeCallback(int width, int height) {
        }

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

        @Override
        public void quit() {
        }

        @Override
        public void quitAsync(ExecutorService executorService, CountDownLatch latch) {
            latch.countDown();
        }

        @Override
        public void seekBySecond(int second) {
        }

        @Override
        public void pause() {
        }

        @Override
        public void restart() {
        }

        @Override
        public boolean prepareFFmpeg(boolean isOpened) {
            return false;
        }

        @Override
        public void prepareDecode() {
        }

        @Override
        public void destroyNativeInstance() {
        }

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

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

        @Override
        public void updateSurfaceSize() {
        }

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

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

        @Override
        public void setCacheDecodeFirst(boolean use) {
        }

        @Override
        public void updateDisplayMetrics(Activity activity) {
        }

        @Override
        public void updateDisplaySize(int width, int height) {
        }

        @Override
        public void setOrientation(int orientation) {
        }

        @Override
        public void setIsVisible(boolean isVisible) {
        }

        @Override
        public void start() {
        }

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

        @Override
        public void setCreateDrawBufferListener(CreateDrawBufferListener listener) {
        }
    }
}
