package jp.mkuriki.sheep2015;

import java.util.ArrayList;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;



public class CustomSurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    // 画像読み込み
    private Resources res = this.getContext().getResources();
    private Bitmap wool = BitmapFactory.decodeResource(res, R.drawable.wool);
    private Bitmap back01 = BitmapFactory.decodeResource(res, R.drawable.back01);
    private Bitmap finish01 = BitmapFactory.decodeResource(res, R.drawable.finish01);
    private Bitmap finish02 = BitmapFactory.decodeResource(res, R.drawable.finish02);
    private Bitmap nakedSheep = BitmapFactory.decodeResource(res, R.drawable.naked);
    private Bitmap happySheep = BitmapFactory.decodeResource(res, R.drawable.wear);
    
    // 画面サイズ
    private int canvasWidth = 0;
    private int canvasHeight = 0;
    // ヒツジサイズ
    private int sheepWidth = nakedSheep.getWidth();
    private int sheepHeight = nakedSheep.getHeight();
    // ヒツジ座標
    private int sheepX = 0;
    private int sheepY = 0;
    
	// 画像を保持するリスト
	private ArrayList<float[]> imgList; 
	
	// ヒツジ画像スケーリング用変数
	private float resizeRate = 1.0f;

	private boolean finishImg = false;
	
	// 毛判定用
	private static int checkWidth = 3;
	private static int checkHeight = 2;
	private static int checkCount = checkWidth * checkHeight;
	private int woolRect[][][] = new int[checkWidth+1][checkHeight+1][2];
	private int checkRect[][] = new int[(checkWidth+1)*(checkHeight+1)][4];
	private boolean wearList[] = new boolean[checkCount];
	private boolean weared = false;

	public CustomSurfaceView(Context context) {
		super(context);

		setFocusable(true);
		getHolder().addCallback(this);
		
		// 画像位置配列の初期化
		imgList = new ArrayList<float[]>();
		
		for(int i = 0; i < wearList.length; i++){
			wearList[i] = false;
		}
		
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		// SurfaceViewが変化（画面の大きさ，ピクセルフォーマット）した時のイベントの処理を記述
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		// SurfaceViewが作成された時の処理（初期画面の描画等）を記述
		doDraw(holder);
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		// SurfaceViewが廃棄されたる時の処理を記述
	}

	@Override
	protected void onDraw(Canvas canvas) {
		canvas.drawColor(Color.WHITE);

	}

	// 描画処理
	private void doDraw(SurfaceHolder holder) {
		// 変数初期化
		Canvas canvas = holder.lockCanvas();
		Paint paint = new Paint();

		// 毛むくじゃら判定処理
		weared = checkWool();
		
		Bitmap sheep;
		Bitmap back;
		// 毛を来ていれば Happy で finish
		if(weared){
			sheep = happySheep;
			if(finishImg){
				back = finish01;
				finishImg = false;
			}else{
				back = finish02;
				finishImg = true;
			}
		// まだ裸なら naked
		}else{
			sheep = nakedSheep;
			back = back01;
		}
		
		// キャンバスのサイズ
        canvasWidth = canvas.getWidth();
        canvasHeight = canvas.getHeight();
 
        // ビットマップのサイズ
        int bmpWidth = this.back01.getWidth();
        int bmpHeight = this.back01.getHeight();
        
		// 画面サイズに合う様に縦横スケール値を求める（最大限画面に収まる様に努力する）
        float toCanvasScale = this.calcBitmapScale(canvasWidth, canvasHeight, bmpWidth, bmpHeight);
 
        // キャンバスの大きさに画像を合わせたときにサイズのずれがどれくらいあるか
        float diffX = (bmpWidth * toCanvasScale - canvasWidth);
        float diffY = (bmpHeight * toCanvasScale - canvasHeight);
         
        // すみを残して中心から取り出す様にする
        float addX = (diffX / toCanvasScale) / 2;
        float addY = (diffY / toCanvasScale) / 2;
        
        // 画像の切り取り位置を調整して画像の中心がキャンバスの中心に来る様にする
        Rect rSrc = new Rect((int)addX, (int)addY,
                (int)((canvasWidth / toCanvasScale) + addX), (int)((canvasHeight / toCanvasScale) + addY));
        RectF rDest = new RectF(0, 0, canvasWidth, canvasHeight);
		// 背景画像の描画
        canvas.drawBitmap(back, rSrc, rDest, paint);
        // ヒツジの描画
        // もしヒツジの絵がキャンバスサイズの 80% よりも大きかったらリサイズ
        if(sheep.getWidth() > canvasWidth){
        	resizeRate = sheep.getWidth() / canvasWidth * 0.80f;
        	sheep = Bitmap.createScaledBitmap(sheep, 
        			(int)(sheep.getWidth() * resizeRate), 
        			(int)(sheep.getHeight() * resizeRate), 
        			false);
        	// resized = true;
        	sheepWidth = sheep.getWidth();
        	sheepHeight = sheep.getHeight();
        }
        // 画面からちょい上の位置にヒツジを描画
        sheepX = canvasWidth - sheep.getWidth();
        sheepY = (int)(canvasHeight * 0.90f - sheep.getHeight());
        canvas.drawBitmap(sheep, 
        		canvasWidth - sheep.getWidth(), 
        		canvasHeight * 0.90f - sheep.getHeight(), 
        		paint);
		
		// 毛の描画処理
		// imgList の中に入ってるだけ画像を描画
		for(int i = 0; i < imgList.size(); i++){
			// 毛の画像を描画
			canvas.drawBitmap(wool, 
					imgList.get(i)[0] - wool.getWidth()/2, 
					imgList.get(i)[1] - wool.getHeight()/2, 
					paint);
		}

		holder.unlockCanvasAndPost(canvas);
	}
	
	// Bitmapの拡大率を出す
    private float calcBitmapScale(int canvasWidth, int canvasHeight, int bmpWidth, int bmpHeight) {
 
        // 最初は幅で調べる
        float scale = (float)canvasWidth / (float)bmpWidth;
        float tmp = bmpHeight * scale;
 
        // 画像の高さがキャンバスの高さより小さい（余白ができてしまう場合）高さの方で横幅をスケールする
        if (tmp < canvasHeight) {
            scale = (float)canvasHeight / (float)bmpHeight;
            return scale;
        }
         
        return scale;
    }

	// 画面がタップされたときの処理
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		float x = event.getX();
		float y = event.getY();

		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			// タップされた位置を取得して画像リストに保存
			float[] pos = {x, y};
			imgList.add(pos);
			// 振動するぜ！
			MainActivity.vib.vibrate(30);
			// もし画面下部をタップすればリセットする
			if(y > canvasHeight * 0.88f){
				this.reset();
			}
			break;
		default:
			return true;
		}
		// 描画処理
		doDraw(getHolder());
		return true;
	}
	
	// 十分に毛があるか判定する処理
	private boolean checkWool(){
		// ヒツジ裸部分初期位置
		int nakedX = sheepX + (int)(sheepWidth * 0.28f);
		int nakedY = sheepY + (int)(sheepHeight * 0.15f);
		// 裸部分の大きさ
		int nakedWidth = (int)(sheepWidth * 0.70f);
		int nakedHeight = (int)(sheepHeight * 0.56f);
		
		// 判定用矩形を用意
		for(int i = 0; i <= checkWidth; i++){
			for(int j = 0; j <= checkHeight; j++){
				woolRect[i][j][0] = nakedX + nakedWidth/checkWidth * i;
				woolRect[i][j][1] = nakedY + nakedHeight/checkHeight * j;
			}
		}
		for(int i = 0; i < checkWidth; i++){
			for(int j = 0; j < checkHeight; j++){
				// i 番目の矩形の左上, 右下をそれぞれ代入
				int rectIndex;
				if(j == 0){
					rectIndex = (i+1)*(j+1) - 1;
				}else{
					rectIndex = (i+1)*(j+1) - ((i+1)-2);
				}
				checkRect[rectIndex][0] = woolRect[i][j][0];
				checkRect[rectIndex][1] = woolRect[i][j][1];
				checkRect[rectIndex][2] = woolRect[i+1][j+1][0];
				checkRect[rectIndex][3] = woolRect[i+1][j+1][1];
			}
		}
		
		rectCount : for(int i = 0; i < checkCount; i++){
			// チェック用の毛カウンタ
			int count = 0;
			int[] rectTop = {checkRect[i][0], checkRect[i][1]};
			int[] rectBottom = {checkRect[i][2], checkRect[i][3]};
			for(int index = 0; index < imgList.size(); index++){
				float imgX = imgList.get(index)[0];
				float imgY = imgList.get(index)[1];
				// もし画像の位置が矩形内ならば
				if(imgX > rectTop[0] && imgX < rectBottom[0]){
					if(imgY > rectTop[1] && imgY < rectBottom[1]){
						count++;
						if(count >= 6){
							wearList[i] = true;
							// true になればループを抜ける
							Log.d("true", ""+i);
							count = 0;
							continue rectCount;
						}
					}
				}
			}
		}
		
		// wearList に false があればまだヒツジは裸である. 
		for(int i = 0; i < checkCount; i++){
			if(!wearList[i]){
				return false;
			}
		}

		// ヒツジが毛をちゃんとまとえば長く振動させて Happy 表示にする
		MainActivity.vib.vibrate(200);
		return true;
	}
	
	// 状態をリセットする
	private void reset(){
		imgList = new ArrayList<float[]>();
		weared = false;
		// wearList も全て false に
		for(int i = 0; i < checkCount; i++){
			wearList[i] = false;
		}
	}
	
}

