package com.abbyy.mobile.sample;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.Region;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.View;

import com.abbyy.mobile.rtr.IImageCaptureService;

public class DrawView extends View {
	private Paint paint;
	private Paint backgroundPaint;
	private Paint boundariesPaint;
	private Paint outsideBoundariesPaint;
	private Paint textPaint;
	private Paint reservedPaint;
	private Path path;
	private boolean cornersIsSet = false;
	private float[] corners = new float[8];
	private Bitmap bitmap;
	RectF src = new RectF();
	RectF dst = new RectF();
	private Matrix bitmapToViewMatrix = new Matrix();
	private Matrix imageToViewMatrix;

	class Block {
		RectF Rect;
		Paint Paint;
		int Alpha;

		Block( RectF rect, Paint paint, int alpha )
		{
			this.Rect = rect;
			this.Paint = paint;
			this.Alpha = alpha;
		}
	}

	private Block[] blocks;

	public DrawView( final Context context, final AttributeSet attrs )
	{
		super( context, attrs );

		paint = new Paint();
		paint.setColor( Color.GREEN );
		paint.setStrokeWidth( 5 );
		paint.setStyle( Paint.Style.STROKE );

		boundariesPaint = new Paint();
		boundariesPaint.setStyle( Paint.Style.STROKE );
		boundariesPaint.setStrokeWidth( 3 );
		boundariesPaint.setARGB( 255, 0, 129, 0 );

		outsideBoundariesPaint = new Paint();
		outsideBoundariesPaint.setARGB( 150, 0, 0, 0 );
		outsideBoundariesPaint.setStyle( Paint.Style.FILL );

		backgroundPaint = new Paint();
		backgroundPaint.setStyle( Paint.Style.FILL );
		backgroundPaint.setARGB( 150, 0, 0, 0 );

		textPaint = new Paint();
		textPaint.setStyle( Paint.Style.FILL );
		textPaint.setARGB( 50, 0, 0, 0 );

		reservedPaint = new Paint();
		reservedPaint.setStyle( Paint.Style.STROKE );
		reservedPaint.setARGB( 255, 129, 129, 129 );

		path = new Path();
	}

	public void setImageToViewTransform( @NonNull Matrix matrix )
	{
		imageToViewMatrix = matrix;
	}

	public void setDocumentBoundary( Point[] corners )
	{
		if( corners != null ) {
			int i = 0;
			for( Point corner : corners ) {
				this.corners[i++] = corner.x;
				this.corners[i++] = corner.y;
			}
			imageToViewMatrix.mapPoints( this.corners );
			cornersIsSet = true;
		} else {
			cornersIsSet = false;
		}
		invalidate();
	}

	public void setBitmap( Bitmap bitmap )
	{
		this.bitmap = bitmap;
		if( bitmap != null ) {
			int bitmapWidth = bitmap.getWidth();
			int bitmapHeight = bitmap.getHeight();
			bitmapToViewMatrix.reset();
			if( bitmapWidth < getWidth() && bitmapHeight < getHeight() ) {
				int dx = ( getWidth() - bitmapWidth ) / 2;
				int dy = ( getHeight() - bitmapHeight ) / 2;
				bitmapToViewMatrix.setTranslate( dx, dy );
				src.set( 0, 0, bitmapWidth, bitmapHeight );
			} else {
				src.set( 0, 0, bitmapWidth, bitmapHeight );
				dst.set( 0, 0, getWidth(), getHeight() );
				bitmapToViewMatrix.setRectToRect( src, dst, Matrix.ScaleToFit.CENTER );
			}
			bitmapToViewMatrix.mapRect( src );
		}
		invalidate();
	}

	public void setQualityAssessmentBlocks( IImageCaptureService.QualityAssessmentForOcrBlock[] qualityAssesmentBlocks )
	{
		if( qualityAssesmentBlocks != null ) {
			this.blocks = new Block[qualityAssesmentBlocks.length];
			for( int i = 0; i < qualityAssesmentBlocks.length; i++ ) {
				IImageCaptureService.QualityAssessmentForOcrBlock block = qualityAssesmentBlocks[i];
				RectF rect = new RectF( block.Rect );
				imageToViewMatrix.mapRect( rect );
				switch( block.Type ) {
					case Text:
						this.blocks[i] = new Block( rect, textPaint, block.Quality / 2 );
						break;
					default:
						this.blocks[i] = new Block( rect, reservedPaint, 100 );
				}
			}
		} else {
			this.blocks = null;
		}
		invalidate();
	}

	@Override
	public void onDraw( final Canvas canvas )
	{
		super.onDraw( canvas );

		if( bitmap != null ) {
			canvas.drawRect( 0, 0, getWidth(), getHeight(), backgroundPaint );
			canvas.drawBitmap( bitmap, bitmapToViewMatrix, null );
			canvas.drawRect( src, boundariesPaint );
		}

		if( cornersIsSet ) {
			path.reset();
			path.moveTo( corners[0], corners[1] );
			path.lineTo( corners[2], corners[3] );
			path.lineTo( corners[4], corners[5] );
			path.lineTo( corners[6], corners[7] );
			path.close();

			canvas.save();
			canvas.clipPath( path, Region.Op.DIFFERENCE );
			canvas.drawRect( 0, 0, getWidth(), getHeight(), outsideBoundariesPaint );
			canvas.restore();

			canvas.drawPath( path, boundariesPaint );
			canvas.clipPath( path );
		}

		if( bitmap == null && blocks != null ) {
			for( Block block : blocks ) {
				if( block != null ) {
					block.Paint.setAlpha( block.Alpha );
					if( block.Alpha != 100 ) {
						block.Paint.setARGB( 50, 255 * ( 50 - block.Alpha ) / 50, 255 * block.Alpha / 50, 0 );
						canvas.drawRect( block.Rect, block.Paint );
					}
					canvas.drawRect( block.Rect, reservedPaint );
				}
			}
		}
	}
}
