/*
 * 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.nfc.beam;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.SurfaceTexture;
import android.opengl.GLUtils;
import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

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;

public class FireflyRenderer {
    private static final String LOG_TAG = "NfcFireflyThread";

    static final int NUM_FIREFLIES = 200;

    static final float NEAR_CLIPPING_PLANE = 50f;
    static final float FAR_CLIPPING_PLANE = 100f;

    // All final variables below only need to be allocated once
    // and can be reused between subsequent Beams
    static final int[] sEglConfig = {
        EGL10.EGL_RED_SIZE, 8,
        EGL10.EGL_GREEN_SIZE, 8,
        EGL10.EGL_BLUE_SIZE, 8,
        EGL10.EGL_ALPHA_SIZE, 0,
        EGL10.EGL_DEPTH_SIZE, 0,
        EGL10.EGL_STENCIL_SIZE, 0,
        EGL10.EGL_NONE
    };

    // Vertices for drawing a 32x32 rect
    static final float mVertices[] = {
        0.0f,  0.0f, 0.0f,  // 0, Top Left
        0.0f,  32.0f, 0.0f, // 1, Bottom Left
        32.0f, 32.0f, 0.0f, // 2, Bottom Right
        32.0f, 0.0f, 0.0f,  // 3, Top Right
    };

    // Mapping coordinates for the texture
    static final float mTextCoords[] = {
        0.0f, 0.0f,
        1.0f, 0.0f,
        1.0f, 1.0f,
        0.0f, 1.0f
    };

    // Connecting order (draws a square)
    static final short[] mIndices = { 0, 1, 2, 0, 2, 3 };

    final Context mContext;

    // Buffer holding the vertices
    final FloatBuffer mVertexBuffer;

    // Buffer holding the indices
    final ShortBuffer mIndexBuffer;

    // Buffer holding the texture mapping coordinates
    final FloatBuffer mTextureBuffer;

    final Firefly[] mFireflies;

    FireflyRenderThread mFireflyRenderThread;

    // The surface to render the flies on, including width and height
    SurfaceTexture mSurface;
    int mDisplayWidth;
    int mDisplayHeight;

    public FireflyRenderer(Context context) {
        mContext = context;

        // First, build the vertex, texture and index buffers
        ByteBuffer vbb = ByteBuffer.allocateDirect(mVertices.length * 4); // Float => 4 bytes
        vbb.order(ByteOrder.nativeOrder());
        mVertexBuffer = vbb.asFloatBuffer();
        mVertexBuffer.put(mVertices);
        mVertexBuffer.position(0);

        ByteBuffer ibb = ByteBuffer.allocateDirect(mIndices.length * 2); // Short => 2 bytes
        ibb.order(ByteOrder.nativeOrder());
        mIndexBuffer = ibb.asShortBuffer();
        mIndexBuffer.put(mIndices);
        mIndexBuffer.position(0);

        ByteBuffer tbb = ByteBuffer.allocateDirect(mTextCoords.length * 4);
        tbb.order(ByteOrder.nativeOrder());
        mTextureBuffer = tbb.asFloatBuffer();
        mTextureBuffer.put(mTextCoords);
        mTextureBuffer.position(0);

        mFireflies = new Firefly[NUM_FIREFLIES];
        for (int i = 0; i < NUM_FIREFLIES; i++) {
            mFireflies[i] = new Firefly();
        }
    }

    /**
     * Starts rendering fireflies on the given surface.
     * Must be called from the UI-thread.
     */
    public void start(SurfaceTexture surface, int width, int height) {
        mSurface = surface;
        mDisplayWidth = width;
        mDisplayHeight = height;

        mFireflyRenderThread = new FireflyRenderThread();
        mFireflyRenderThread.start();
    }

    /**
     * Stops rendering fireflies.
     * Must be called from the UI-thread.
     */
    public void stop() {
        if (mFireflyRenderThread != null) {
            mFireflyRenderThread.finish();
            try {
                mFireflyRenderThread.join();
            } catch (InterruptedException e) {
                Log.e(LOG_TAG, "Couldn't wait for FireflyRenderThread.");
            }
            mFireflyRenderThread = null;
        }
    }

    private class FireflyRenderThread extends Thread {
        EGL10 mEgl;
        EGLDisplay mEglDisplay;
        EGLConfig mEglConfig;
        EGLContext mEglContext;
        EGLSurface mEglSurface;
        GL10 mGL;

        // Holding the handle to the texture
        int mTextureId;

        // Read/written by multiple threads
        volatile boolean mFinished;

        @Override
        public void run() {
            if (!initGL()) {
                Log.e(LOG_TAG, "Failed to initialize OpenGL.");
                return;
            }
            loadStarTexture();

            mGL.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

            mGL.glViewport(0, 0, mDisplayWidth, mDisplayHeight);

            // make adjustments for screen ratio
            mGL.glMatrixMode(GL10.GL_PROJECTION);
            mGL.glLoadIdentity();
            mGL.glFrustumf(-mDisplayWidth, mDisplayWidth, mDisplayHeight, -mDisplayHeight, NEAR_CLIPPING_PLANE, FAR_CLIPPING_PLANE);

            // Switch back to modelview
            mGL.glMatrixMode(GL10.GL_MODELVIEW);
            mGL.glLoadIdentity();

            mGL.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
            mGL.glDepthMask(true);


            for (Firefly firefly : mFireflies) {
                firefly.reset();
            }

            for (int i = 0; i < 3; i++) {
                // Call eglSwapBuffers 3 times - this will allocate the necessary
                // buffers, and make sure the animation looks smooth from the start.
                mGL.glClear(GL10.GL_COLOR_BUFFER_BIT);
                if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
                    Log.e(LOG_TAG, "Could not swap buffers");
                    mFinished = true;
                }
            }

            long startTime = System.currentTimeMillis();

            while (!mFinished) {
                long timeElapsedMs = System.currentTimeMillis() - startTime;
                startTime = System.currentTimeMillis();

                checkCurrent();

                mGL.glClear(GL10.GL_COLOR_BUFFER_BIT);
                mGL.glLoadIdentity();

                mGL.glEnable(GL10.GL_TEXTURE_2D);
                mGL.glEnable(GL10.GL_BLEND);
                mGL.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE);

                for (Firefly firefly : mFireflies) {
                    firefly.updatePositionAndScale(timeElapsedMs);
                    firefly.draw(mGL);
                }

                if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
                    Log.e(LOG_TAG, "Could not swap buffers");
                    mFinished = true;
                }

                long elapsed = System.currentTimeMillis() - startTime;
                try {
                    Thread.sleep(Math.max(30 - elapsed, 0));
                } catch (InterruptedException e) {

                }
            }
            finishGL();
        }

        public void finish() {
            mFinished = true;
        }

        void loadStarTexture() {
            int[] textureIds = new int[1];
            mGL.glGenTextures(1, textureIds, 0);
            mTextureId = textureIds[0];

            InputStream in = null;
            try {
                // Remember that both texture dimensions must be a power of 2!
                in = mContext.getAssets().open("star.png");

                Bitmap bitmap = BitmapFactory.decodeStream(in);
                mGL.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);

                mGL.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
                mGL.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

                GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

                bitmap.recycle();

            } catch (IOException e) {
                Log.e(LOG_TAG, "IOException opening assets.");
            } finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) { }
                }
            }
        }

        private void checkCurrent() {
            if (!mEglContext.equals(mEgl.eglGetCurrentContext()) ||
                    !mEglSurface.equals(mEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) {
                if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
                    throw new RuntimeException("eglMakeCurrent failed "
                            + GLUtils.getEGLErrorString(mEgl.eglGetError()));
                }
            }
        }

        boolean initGL() {
            // Initialize openGL engine
            mEgl = (EGL10) EGLContext.getEGL();

            mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
            if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
                Log.e(LOG_TAG, "eglGetDisplay failed " +
                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
                return false;
            }

            int[] version = new int[2];
            if (!mEgl.eglInitialize(mEglDisplay, version)) {
                Log.e(LOG_TAG, "eglInitialize failed " +
                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
                return false;
            }

            mEglConfig = chooseEglConfig();
            if (mEglConfig == null) {
                Log.e(LOG_TAG, "eglConfig not initialized.");
                return false;
            }

            mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig, EGL10.EGL_NO_CONTEXT, null);

            mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, mSurface, null);

            if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
                int error = mEgl.eglGetError();
                Log.e(LOG_TAG,"createWindowSurface returned error " + Integer.toString(error));
                return false;
            }

            if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
                Log.e(LOG_TAG, "eglMakeCurrent failed " +
                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
                return false;
            }

            mGL = (GL10) mEglContext.getGL();

            return true;
        }

        private void finishGL() {
            if (mEgl == null || mEglDisplay == null) {
                // Nothing to free
                return;
            }
            // Unbind the current surface and context from the display
            mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE,
                    EGL10.EGL_NO_CONTEXT);

            if (mEglSurface != null) {
                mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
            }

            if (mEglContext != null) {
                mEgl.eglDestroyContext(mEglDisplay, mEglContext);
            }
        }

        private EGLConfig chooseEglConfig() {
            int[] configsCount = new int[1];
            EGLConfig[] configs = new EGLConfig[1];
            if (!mEgl.eglChooseConfig(mEglDisplay, sEglConfig, configs, 1, configsCount)) {
                throw new IllegalArgumentException("eglChooseConfig failed " +
                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
            } else if (configsCount[0] > 0) {
                return configs[0];
            }
            return null;
        }
    }

    private class Firefly {
        static final float TEXTURE_HEIGHT = 30f; // TODO use measurement of texture size
        static final float SPEED = .5f;

        float mX; // between -mDisplayHeight and mDisplayHeight
        float mY; // between -mDisplayWidth and mDisplayWidth
        float mZ; // between 0.0 (near) and 1.0 (far)
        float mZ0;
        float mT;
        float mScale;
        float mAlpha;

        public Firefly() {
        }

        void reset() {
            mX = (float) (Math.random() * mDisplayWidth) * 4 - 2 * mDisplayWidth;
            mY = (float) (Math.random() * mDisplayHeight) * 4 - 2 * mDisplayHeight;
            mZ0 = mZ = (float) (Math.random()) * 2 - 1;
            mT = 0f;
            mScale = 1.5f;
            mAlpha = 0f;
        }

        public void updatePositionAndScale(long timeElapsedMs) {
               mT += timeElapsedMs;
               mZ = mZ0 + mT/1000f * SPEED;
               mAlpha = 1f-mZ;
               if(mZ > 1.0) reset();
        }

        public void draw(GL10 gl) {
            gl.glLoadIdentity();

            // Counter clockwise winding
            gl.glFrontFace(GL10.GL_CCW);

            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
            gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

            gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
            gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer);

            gl.glTranslatef(mX, mY, -NEAR_CLIPPING_PLANE-mZ*(FAR_CLIPPING_PLANE-NEAR_CLIPPING_PLANE));
            gl.glColor4f(1, 1, 1, mAlpha);

            // scale around center
            gl.glTranslatef(TEXTURE_HEIGHT/2, TEXTURE_HEIGHT/2, 0);
            gl.glScalef(mScale, mScale, 0);
            gl.glTranslatef(-TEXTURE_HEIGHT/2, -TEXTURE_HEIGHT/2, 0);

            gl.glDrawElements(GL10.GL_TRIANGLES, mIndices.length, GL10.GL_UNSIGNED_SHORT,
                    mIndexBuffer);

            gl.glColor4f(1, 1, 1, 1);
            gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        }
    }
}
