package com.wasu.cs.widget;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader.TileMode;
import android.util.AttributeSet;
import android.widget.ImageView;

public class ReflectImageViewEx extends ImageView {
	private boolean mbEnableTurn		= false;
	private boolean mbEnableReflect 	= false;
	
	private int mTurnAngleX = 0;
	private int mTurnAngleY = 0;
	private int mTurnAngleZ = 0;
	
	// The height the reflection image have
	private int mReflectHeight 	= 0;
	// The gap we want between the reflection and the original image
	private int mReflectGap 	= 0;
	
	private int mParentViewHeight = 0;
	
	public ReflectImageViewEx(Context context){
		super(context);
	}
	
	public ReflectImageViewEx(Context context, AttributeSet attrs) {
		super(context, attrs);
	}
	
	public void setEnableReflect(int gap, int height){
		mbEnableReflect = true;
		mReflectHeight 	= height;
		mReflectGap		= gap;
	}
	
	/**
	 * 旋转角度， 45表示旋转45度
	 * @param turnX: x轴的旋转角度
	 * @param turnY: y轴的旋转角度
	 * @param turnZ: z轴的旋转角度
	 */
	public void setEnableTurn(int turnX, int turnY, int turnZ){
		mbEnableTurn = true;
		mTurnAngleX = turnX;
		mTurnAngleY = turnY;
		mTurnAngleZ = turnZ;
	}

	@Override
	public void setImageBitmap(Bitmap bm) {
		if (mbEnableReflect || mbEnableTurn){
			bm = createImage(bm);
		}
		
		super.setImageBitmap(bm);
	}
	
	private Bitmap createReflectImage(Bitmap originalImage, Matrix matrixTurn){
		Bitmap originalImageRotate = Bitmap.createBitmap(originalImage, 0, 0, originalImage.getWidth(), originalImage.getHeight(), matrixTurn, true);
        int width = originalImageRotate.getWidth();
        int height = originalImageRotate.getHeight();
  
        // This will not scale but will flip on the Y axis
        Matrix matrix = new Matrix();
        matrix.preScale(1, -1);
        // Create a Bitmap with the flip matrix applied to it.
        // We only want the bottom half of the image
        Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, height - mReflectHeight, originalImage.getWidth(),
        		mReflectHeight, matrix, true);

        // Create a new bitmap with same width but taller to fit reflection  
        Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + mReflectHeight + mReflectGap),  
                Config.ARGB_8888);  
  
        // Create a new Canvas with the bitmap that's big enough for  
        // the image plus gap plus reflection  
        Canvas canvas = new Canvas(bitmapWithReflection);
        matrixTurn.postSkew(0, 0.06f);
        canvas.setMatrix(matrixTurn);
        canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
        // Draw in the original image
        canvas.drawBitmap(originalImage, 0, 0, null);
        // Draw in the gap
        Paint defaultPaint = new Paint();
        defaultPaint.setAntiAlias(true);
        canvas.drawRect(0, height, width, height + mReflectGap, defaultPaint);
        // Draw in the reflection  
        canvas.drawBitmap(reflectionImage, 0, height + mReflectGap, null);
  
        // Create a shader that is a linear gradient that covers the reflection
        Paint paint = new Paint();
        LinearGradient shader = new LinearGradient(0, originalImage.getHeight(), 0,
                bitmapWithReflection.getHeight() + mReflectGap, 0x70ffffff, 0x00ffffff,
                TileMode.CLAMP);
        // Set the paint to use this shader (linear gradient)  
        paint.setShader(shader);
        // Set the Transfer mode to be porter duff and destination in  
        paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));  
        // Draw a rectangle using the paint with our linear gradient
        canvas.drawRect(0, height, originalImage.getWidth() + 1, bitmapWithReflection.getHeight() + mReflectGap + 1, paint);
        
        this.setTag(Float.valueOf((float) width / Float.valueOf(bitmapWithReflection.getHeight() + mReflectGap + 1)));
  
        if (originalImageRotate != null){
        	originalImageRotate.recycle();
        }
        if (reflectionImage != null){
        	reflectionImage.recycle();
        }
        
        return bitmapWithReflection;
	}
	
	public Bitmap createImage(Bitmap originalImage) {
        Matrix matrix = new Matrix();
        if (mbEnableTurn){
        	Camera camera = new Camera(); 
        	camera.save(); 
        	if (mTurnAngleX > 0){
        		camera.rotateX(mTurnAngleX); 
        	}
        	if (mTurnAngleY > 0){
        		camera.rotateY(mTurnAngleY); 
        	}
        	if (mTurnAngleZ > 0){
        		camera.rotateZ(mTurnAngleZ); 
        	}
        	camera.getMatrix(matrix); 
        	camera.restore(); 
        }
        
        if (mbEnableReflect){
        	return createReflectImage(originalImage, matrix);
        }else if(mbEnableTurn){
        	return Bitmap.createBitmap(originalImage, 0, 0, originalImage.getWidth(), 
        			originalImage.getHeight(), matrix, true); 
        }else{
        	return null;
        }
    }

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// TODO Auto-generated method stub
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		mParentViewHeight = MeasureSpec.getSize(heightMeasureSpec);
	}
}
