package com.cicada.player.utils;

import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.view.Choreographer;

@NativeUsed
public class VsyncTimer {

    private static final String TAG = VsyncTimer.class.getSimpleName();

    private static int WHAT_INIT = 10000;
    private static int WHAT_START = 10001;
    private static int WHAT_PAUSE = 10002;
    private static int WHAT_DESTROY = 10003;

    private long mNativePtr;
    private HandlerThread mTimerThread;
    private Handler mTimerHandler;

    private final Object lockObj = new Object();

    private Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
        @Override
        public void doFrame(long frameTimeNanos) {
            onVsync(mNativePtr, frameTimeNanos);
            Choreographer.getInstance().postFrameCallback(this);
        }
    };

    public VsyncTimer(long nativePtr) {
        mNativePtr = nativePtr;
        mTimerThread = new HandlerThread(TAG);
        mTimerThread.start();
        mTimerHandler = new Handler(mTimerThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                if (msg.what == WHAT_INIT) {
                    onInit(mNativePtr);
                } else if (msg.what == WHAT_START) {
                    Choreographer.getInstance().postFrameCallback(mFrameCallback);
                } else if (msg.what == WHAT_PAUSE) {
                    Choreographer.getInstance().removeFrameCallback(mFrameCallback);
                } else if (msg.what == WHAT_DESTROY) {
                    Choreographer.getInstance().removeFrameCallback(mFrameCallback);
                    onDestroy(mNativePtr);
                    mTimerThread.quit();
                    mNativePtr = 0;

                    synchronized (lockObj) {
                        lockObj.notifyAll();
                    }
                }
            }
        };


        mTimerHandler.sendEmptyMessage(WHAT_INIT);
    }

    public void start() {
        mTimerHandler.sendEmptyMessage(WHAT_START);
    }

    public void pause() {
        mTimerHandler.sendEmptyMessage(WHAT_PAUSE);
    }

    public void destroy() {
        synchronized (lockObj) {
            mTimerHandler.sendEmptyMessage(WHAT_DESTROY);
            try {
                lockObj.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private native int onInit(long nativePtr);

    private native int onVsync(long nativePtr, long frameTimeNanos);

    private native void onDestroy(long nativePtr);
}
