package com.roxiga.aquamotion3d;

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 java.util.ArrayList;

import javax.microedition.khronos.opengles.GL10;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.opengl.Matrix;
import android.graphics.Bitmap.Config;
import android.graphics.Color;
import android.graphics.Canvas;
import android.graphics.Paint;

public class Sprite2D
{
    public static final int FLOAT_SIZE_BYTES = 4;
    public static final int SHORT_SIZE_BYTES = 2;
    protected static final int VERTICES_DATA_STRIDE_BYTES = 3 * FLOAT_SIZE_BYTES;
    protected static final int UV_DATA_STRIDE_BYTES = 2 * FLOAT_SIZE_BYTES;
   	protected FloatBuffer _vertexBuffer = null;
	protected FloatBuffer _textureBuffer = null;
    protected ShortBuffer _indexBuffer = null;
    protected ArrayList<Vector3D> _vertices = new ArrayList<Vector3D>();
    protected ArrayList<Float>    _uv       = new ArrayList<Float>();
    protected ArrayList<Short>    _indices  = new ArrayList<Short>();
    public int _textureID;
	public boolean _visible = true;
	public Vector3D _pos = new Vector3D(0,0,0);
	public Vector3D _rotate = new Vector3D(0,0,0);
	public Vector3D _scale = new Vector3D(1,1,1);
    protected float[] _mvpMatrix = new float[16];
    protected float[] _mMatrix = new float[16];

    public Sprite2D()
    {
    }
    
    public Sprite2D(float x,float y,float width,float height,float u,float v,float uWidth,float vHeight)
    {
    	addV(x      ,y       ,0);
    	addV(x+width,y       ,0);
    	addV(x+width,y+height,0);
    	addV(x      ,y+height,0);
    	addI(2,1,0);
    	addI(0,3,2);
    	addUV(u+uWidth,v+vHeight);
    	addUV(u+uWidth,v);
    	addUV(u,v);
    	addUV(u,v);
    	addUV(u,v+vHeight);
    	addUV(u+uWidth,v+vHeight);
    	init();
    }
    
    protected void init()
    {
    	short i;
        ByteBuffer vbb = ByteBuffer.allocateDirect(
        		_indices.size()*3*FLOAT_SIZE_BYTES);
        vbb.order(ByteOrder.nativeOrder());
        _vertexBuffer = vbb.asFloatBuffer();
        for ( i = 0; i < _indices.size(); i++)
        {
        	Vector3D v = _vertices.get(_indices.get(i));
 			_vertexBuffer.put(v._x);
			_vertexBuffer.put(v._y);
			_vertexBuffer.put(v._z);
		}
        _vertexBuffer.position(0);

        ByteBuffer ibb = ByteBuffer.allocateDirect(
        		_indices.size()*SHORT_SIZE_BYTES);
        ibb.order(ByteOrder.nativeOrder());
        _indexBuffer = ibb.asShortBuffer();
        for ( i = 0; i < _indices.size(); i++)
        {
			_indexBuffer.put(i);
		}
		_indexBuffer.position(0);

		ByteBuffer uvbb = ByteBuffer.allocateDirect(
				_uv.size()*FLOAT_SIZE_BYTES);
		uvbb.order(ByteOrder.nativeOrder());
		_textureBuffer = uvbb.asFloatBuffer();
		for ( int j = 0; j < _uv.size(); j++ )
        {
			_textureBuffer.put(_uv.get(j));
        }
        _textureBuffer.position(0);
    }

    protected void addV(double x,double y,double z)
    {
    	_vertices.add(new Vector3D((float)x,(float)y,(float)z));
    }

    protected void addI(int i,int i2,int i3)
    {
    	_indices.add((short)i);
    	_indices.add((short)i2);
    	_indices.add((short)i3);
    }
    
    protected void addUV(double u,double v)
    {
    	_uv.add((float)u);
    	_uv.add((float)v);
    }

    public void setTexture(Resources res,int id)
    {
        int[] textures = new int[1];
        InputStream is = res.openRawResource(id);

        Bitmap bitmap;
        try
        {
            bitmap = BitmapFactory.decodeStream(is);
        }
        finally
        {
            try
            {
                is.close();
            }
            catch(IOException e)
            {
            }
        }
        GLES20.glGenTextures(1, textures, 0);

        _textureID = textures[0];
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, _textureID);

        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
                GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_NEAREST);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
                GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_NEAREST);

        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
                GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
                GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_REPEAT);

        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
    }

    public void setFontTexture(Resources res,String str)
    {
        int[] textures = new int[1];
        GLES20.glGenTextures(1, textures, 0);

        _textureID = textures[0];
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, _textureID);

        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
                GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_NEAREST);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
                GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_NEAREST);

        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
                GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
                GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_REPEAT);

        Bitmap bitmap = Bitmap.createBitmap(256, 256, Config.ARGB_8888);;
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        paint.setColor(Color.BLACK);
        paint.setAntiAlias(true);
        paint.setTextSize(15);
//        paint.setStyle(Style.FILL);
        canvas.drawColor(0);
        canvas.drawText(str, 0, 100, paint);
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
        bitmap.recycle();
    }

    public void draw(Scene3D scene)
    {        
    	if ( !_visible )
    	{
    		return;
    	}
    	GLES20.glEnable(GLES20.GL_ALPHA);
    	GLES20.glEnable(GLES20.GL_BLEND);
    	GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);

    	GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, _textureID);

        GLES20.glUniform1i(scene._uUseBoneHandle, 0);
        GLES20.glDisableVertexAttribArray(scene._aBoneHandle);

        setTransform();
        Matrix.multiplyMM(_mvpMatrix, 0, scene._orthoMatrix, 0, _mMatrix, 0);
        GLES20.glUniformMatrix4fv(scene._uMVPMatrixHandle, 1, false, _mvpMatrix, 0);

        GLES20.glEnableVertexAttribArray(scene._aPositionHandle);
        _vertexBuffer.position(0);
        GLES20.glVertexAttribPointer(scene._aPositionHandle, 3, GLES20.GL_FLOAT,
        		false,VERTICES_DATA_STRIDE_BYTES, _vertexBuffer);

        GLES20.glEnableVertexAttribArray(scene._aTextureHandle);
        _textureBuffer.position(0);
        GLES20.glVertexAttribPointer(scene._aTextureHandle, 2, GLES20.GL_FLOAT, false,
               UV_DATA_STRIDE_BYTES, _textureBuffer);

        GLES20.glDrawElements(GL10.GL_TRIANGLES, _indices.size(),
        		GLES20.GL_UNSIGNED_SHORT, _indexBuffer);

        GLES20.glDisable(GLES20.GL_ALPHA);
    	GLES20.glDisable(GLES20.GL_BLEND);
   }
   
    protected void setTransform()
    {
    	Matrix.setIdentityM(_mMatrix, 0);
    	Matrix.translateM(_mMatrix, 0,_pos._x,_pos._y,_pos._z);
        Matrix.rotateM(_mMatrix, 0, _rotate._x, 1, 0, 0);
        Matrix.rotateM(_mMatrix, 0, _rotate._y, 0, 1, 0);
        Matrix.rotateM(_mMatrix, 0, _rotate._z, 0, 0, 1);
        Matrix.scaleM(_mMatrix, 0, _scale._x, _scale._y, _scale._z);
    }
}
