/*
 * Copyright (C) 2011 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.graphics.SurfaceTexture;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import com.android.gallery3d.common.ApiHelper;

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;
import javax.microedition.khronos.opengles.GL10;

@TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) // uses SurfaceTexture
public class MosaicPreviewRenderer {
    private static final String TAG = "MosaicPreviewRenderer";
    private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
    private static final boolean DEBUG = false;

    private int mWidth; // width of the view in UI
    private int mHeight; // height of the view in UI

    private boolean mIsLandscape = true;
    private final float[] mTransformMatrix = new float[16];

    private ConditionVariable mEglThreadBlockVar = new ConditionVariable();
    private HandlerThread mEglThread;
    private EGLHandler mEglHandler;

    private EGLConfig mEglConfig;
    private EGLDisplay mEglDisplay;
    private EGLContext mEglContext;
    private EGLSurface mEglSurface;
    private SurfaceTexture mMosaicOutputSurfaceTexture;
    private SurfaceTexture mInputSurfaceTexture;
    private EGL10 mEgl;
    private GL10 mGl;

    private class EGLHandler extends Handler {
        public static final int MSG_INIT_EGL_SYNC = 0;
        public static final int MSG_SHOW_PREVIEW_FRAME_SYNC = 1;
        public static final int MSG_SHOW_PREVIEW_FRAME = 2;
        public static final int MSG_ALIGN_FRAME_SYNC = 3;
        public static final int MSG_RELEASE = 4;

        public EGLHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_INIT_EGL_SYNC:
                    doInitGL();
                    mEglThreadBlockVar.open();
                    break;
                case MSG_SHOW_PREVIEW_FRAME_SYNC:
                    doShowPreviewFrame();
                    mEglThreadBlockVar.open();
                    break;
                case MSG_SHOW_PREVIEW_FRAME:
                    doShowPreviewFrame();
                    break;
                case MSG_ALIGN_FRAME_SYNC:
                    doAlignFrame();
                    mEglThreadBlockVar.open();
                    break;
                case MSG_RELEASE:
                    doRelease();
                    break;
            }
        }

        private void doAlignFrame() {
            mInputSurfaceTexture.updateTexImage();
            mInputSurfaceTexture.getTransformMatrix(mTransformMatrix);

            MosaicRenderer.setWarping(true);
            // Call preprocess to render it to low-res and high-res RGB textures.
            MosaicRenderer.preprocess(mTransformMatrix);
            // Now, transfer the textures from GPU to CPU memory for processing
            MosaicRenderer.transferGPUtoCPU();
            MosaicRenderer.updateMatrix();
            draw();
            mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
        }

        private void doShowPreviewFrame() {
            mInputSurfaceTexture.updateTexImage();
            mInputSurfaceTexture.getTransformMatrix(mTransformMatrix);

            MosaicRenderer.setWarping(false);
            // Call preprocess to render it to low-res and high-res RGB textures.
            MosaicRenderer.preprocess(mTransformMatrix);
            MosaicRenderer.updateMatrix();
            draw();
            mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
        }

        private void doInitGL() {
            // These are copied from GLSurfaceView
            mEgl = (EGL10) EGLContext.getEGL();
            mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
            if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
                throw new RuntimeException("eglGetDisplay failed");
            }
            int[] version = new int[2];
            if (!mEgl.eglInitialize(mEglDisplay, version)) {
                throw new RuntimeException("eglInitialize failed");
            } else {
                Log.v(TAG, "EGL version: " + version[0] + '.' + version[1]);
            }
            int[] attribList = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
            mEglConfig = chooseConfig(mEgl, mEglDisplay);
            mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig, EGL10.EGL_NO_CONTEXT,
                                                attribList);

            if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) {
                throw new RuntimeException("failed to createContext");
            }
            mEglSurface = mEgl.eglCreateWindowSurface(
                    mEglDisplay, mEglConfig, mMosaicOutputSurfaceTexture, null);
            if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
                throw new RuntimeException("failed to createWindowSurface");
            }

            if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
                throw new RuntimeException("failed to eglMakeCurrent");
            }

            mGl = (GL10) mEglContext.getGL();

            mInputSurfaceTexture = new SurfaceTexture(MosaicRenderer.init());
            MosaicRenderer.reset(mWidth, mHeight, mIsLandscape);
        }

        private void doRelease() {
            mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
            mEgl.eglDestroyContext(mEglDisplay, mEglContext);
            mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE,
                    EGL10.EGL_NO_CONTEXT);
            mEgl.eglTerminate(mEglDisplay);
            mEglSurface = null;
            mEglContext = null;
            mEglDisplay = null;
            releaseSurfaceTexture(mInputSurfaceTexture);
            mEglThread.quit();
        }

        @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
        private void releaseSurfaceTexture(SurfaceTexture st) {
            if (ApiHelper.HAS_RELEASE_SURFACE_TEXTURE) {
                st.release();
            }
        }

        // Should be called from other thread.
        public void sendMessageSync(int msg) {
            mEglThreadBlockVar.close();
            sendEmptyMessage(msg);
            mEglThreadBlockVar.block();
        }

    }

    public MosaicPreviewRenderer(SurfaceTexture tex, int w, int h, boolean isLandscape) {
        mMosaicOutputSurfaceTexture = tex;
        mWidth = w;
        mHeight = h;
        mIsLandscape = isLandscape;

        mEglThread = new HandlerThread("PanoramaRealtimeRenderer");
        mEglThread.start();
        mEglHandler = new EGLHandler(mEglThread.getLooper());

        // We need to sync this because the generation of surface texture for input is
        // done here and the client will continue with the assumption that the
        // generation is completed.
        mEglHandler.sendMessageSync(EGLHandler.MSG_INIT_EGL_SYNC);
    }

    public void release() {
        mEglHandler.sendEmptyMessage(EGLHandler.MSG_RELEASE);
    }

    public void showPreviewFrameSync() {
        mEglHandler.sendMessageSync(EGLHandler.MSG_SHOW_PREVIEW_FRAME_SYNC);
    }

    public void showPreviewFrame() {
        mEglHandler.sendEmptyMessage(EGLHandler.MSG_SHOW_PREVIEW_FRAME);
    }

    public void alignFrameSync() {
        mEglHandler.sendMessageSync(EGLHandler.MSG_ALIGN_FRAME_SYNC);
    }

    public SurfaceTexture getInputSurfaceTexture() {
        return mInputSurfaceTexture;
    }

    private void draw() {
        MosaicRenderer.step();
    }

    private static void checkEglError(String prompt, EGL10 egl) {
        int error;
        while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) {
            Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error));
        }
    }

    private static final int EGL_OPENGL_ES2_BIT = 4;
    private static final int[] CONFIG_SPEC = new int[] {
            EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
            EGL10.EGL_RED_SIZE, 8,
            EGL10.EGL_GREEN_SIZE, 8,
            EGL10.EGL_BLUE_SIZE, 8,
            EGL10.EGL_NONE
    };

    private static EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
        int[] numConfig = new int[1];
        if (!egl.eglChooseConfig(display, CONFIG_SPEC, null, 0, numConfig)) {
            throw new IllegalArgumentException("eglChooseConfig failed");
        }

        int numConfigs = numConfig[0];
        if (numConfigs <= 0) {
            throw new IllegalArgumentException("No configs match configSpec");
        }

        EGLConfig[] configs = new EGLConfig[numConfigs];
        if (!egl.eglChooseConfig(
                display, CONFIG_SPEC, configs, numConfigs, numConfig)) {
            throw new IllegalArgumentException("eglChooseConfig#2 failed");
        }

        return configs[0];
    }
}
