package com.cwp.chart;

import java.util.ArrayList;

import com.cwp.cmoneycharge.PayChart;
import com.cwp.cmoneycharge.R;

import android.content.Context;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;

import android.graphics.Point;
import android.graphics.RectF;

import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;

import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;

import android.view.View;
import android.view.View.MeasureSpec;

public class PieView extends View implements View.OnTouchListener, Runnable {

	private float m_x = 0;
	private float m_y = 0;

	private static ArrayList<ChartProp> mChartProps;
	private float screenHight, screenWidth;// �Ļ�Ŀ�͸�

	private float radius;// ����Բ�İ뾶
	private float startAngle;// ��?�Ƕ�
	private float sweepAngle = 0.0f; // ɨ���Ľǎ�
	private int itemCount;// ѡ���
	private float startSpeed = 0;

	private boolean firstEnter = true; // �����Ƿ��Ѿ��T?
	private boolean rotateEnabled = false;
	private boolean tounched = false;
	private boolean done = false;
	private Paint mPaint;

	private Paint textPaint;
	private Canvas mCanvas;

	private ChartPropChangeListener listener;
	private static ChartProp mChartProp = null;
	private static ChartProp tChartProp = null;
	private static float[] percents;

	private Point centerPoint;
	private Bitmap myBg;
	private String amount;

	private Thread myThread;

	public void setBackgroundPaintColor(int color) {

		invalidate();
	}

	private void writeLog(String string) {
		Log.e("caizh", string);
	}

	public void destory() {
		// myBg.recycle();
		done = true;
	}

	@Override
	public void draw(Canvas canvas) {
		// TODO Auto-generated method stub

		super.draw(canvas);

		if (firstEnter) {
			firstInit();
		} else {

			if (!tounched) {

				float middleAngle = ((mChartProp.getEndAngle() + mChartProp
						.getStartAngle()) / 2);
				float distance = (middleAngle - getBorderAngle());

				startAngle -= (distance / 2);

				// startAngle=()
			}

		}

		mCanvas = canvas;

		float f1 = centerPoint.x;
		float f2 = centerPoint.y;
		// ��䱳��ܵ
		/*
		 * mCanvas.drawColor(0xff639EC3); mCanvas.save();
		 */

		// *********************************ȷ�����D?��*************************************
		float f3 = f1 - radius;// X��- ��
		float f4 = f2 - radius; // Y��- د
		float f5 = f1 + radius; // X��- ��
		float f6 = f2 + radius; // Y��- د
		RectF rectF = new RectF(f3, f4, f5, f6);

		// *********************************��ÿ��������ɫ�}********************************
		drawItem(rectF);
		// *********************************�����Ͻ����Բ������*******************************

		drawableCenterCircle(f1, f2);
		// ���Canvas������Ⱦ��ǰͼ��

		if (!(mChartProp == tChartProp)) {
			listener.getChartProp(mChartProp);
			tChartProp = mChartProp;
		}

	}

	public PieView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	public PieView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public PieView(Context context) {
		super(context);
		init();
	}

	private void init() {

		myThread = new Thread(this);
		// ����د?�µ�SurfaceHolder�߲����������Ϊ��Ļص�(callback)

		mChartProps = new ArrayList<ChartProp>();

		// ͼ�񻭱�
		mPaint = new Paint();

		mPaint.setAntiAlias(true);
		// ���ֻ���
		textPaint = new Paint();
		textPaint.setTextSize(22);
		textPaint.setColor(Color.WHITE);
		textPaint.setAntiAlias(true);

		// �뾶

		startAngle = 90f;

		myBg = BitmapFactory.decodeResource(getResources(),
				R.drawable.mask_piechartformymoney);

		this.setOnTouchListener(this);

	}

	public void start() {
		myThread.start();
	}

	@Override
	public void run() {

		while (!done) {

			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			if (rotateEnabled) {

				postInvalidate();
			}
		}

	}

	private Bitmap createBitmap(Bitmap b, float x, float y) {
		int w = b.getWidth();
		int h = b.getHeight();

		float sx = (float) x / w;
		float sy = (float) y / h;
		Matrix matrix = new Matrix();
		matrix.postScale(sx, sy);
		Bitmap resizeBmp = Bitmap.createBitmap(b, 0, 0, w, h, matrix, true);
		return resizeBmp;
	}

	/**
	 * create charts' property ������״ͼ�����
	 * 
	 * @param chartsNum
	 *            charts' number ��״ͼ�ĸ��
	 * @return charts' property's list ��״ͼ���Ե�list
	 */
	public ArrayList<ChartProp> createCharts(int itemCount) {
		this.itemCount = itemCount;
		percents = new float[itemCount];
		mChartProps.clear();
		createChartProp(itemCount);

		return mChartProps;
	}

	// ���³�ʼ��
	public void reInit() {
		startAngle = 90f;
		firstEnter = true; // �����Ƿ��Ѿ��T?
	}

	// ��һ�β�����иı��ij�ʼ������
	public void initPercents() {

		for (int i = 0; i < itemCount; i++) {

			percents[i] = mChartProps.get(i).getPercent();
			mChartProps.get(i).setPercent(0.01f);

		}

	}

	public void setChartPropChangeListener(ChartPropChangeListener listener) {
		this.listener = listener;
	}

	/**
	 * actually create chartProp objects. �������������{?����
	 * 
	 * @param chartsNum
	 *            charts' number ��״ͼ�ĸ��
	 */
	private void createChartProp(int chartsNum) {
		for (int i = 0; i < chartsNum; i++) {
			ChartProp chartProp = new ChartProp(this);
			chartProp.setId(i);
			mChartProps.add(chartProp);
		}
	}

	public ChartProp createNullChartProp() {
		mChartProps.clear();
		ChartProp chartProp = new ChartProp(this);
		mChartProps.add(chartProp);
		return chartProp;
	}

	private void initResoure() {
		float y = myBg.getHeight();
		float x = myBg.getWidth();
		float r;

		if (screenHight > screenWidth) {
			r = screenWidth;
			myBg = createBitmap(myBg, screenWidth, (screenWidth * y) / x);
		} else {
			r = screenHight;
			myBg = createBitmap(myBg, screenHight, (screenHight * y) / x);
		}

		centerPoint = new Point();

		centerPoint.x = (int) (r / 2);
		centerPoint.y = (int) ((r * 19) / 32);

		radius = (centerPoint.x * 0.8843f);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

		// �߶�
		screenHight = (float) PiewController.measureWidth(heightMeasureSpec);

		screenWidth = (float) PiewController.measureHeight(widthMeasureSpec);
		Log.e("caizh", "screenWidth01=" + screenWidth);
		initResoure();
		setMeasuredDimension((int) screenWidth, (int) screenHight);
	}

	private int measureWidth(int pWidthMeasureSpec) {
		int result = 0;
		int widthMode = MeasureSpec.getMode(pWidthMeasureSpec);// �õ�ģʽ
		int widthSize = MeasureSpec.getSize(pWidthMeasureSpec);// �õ��ߴ�

		switch (widthMode) {
		/**
		 * mode�����������ȡֵ�ֱ�ΪMeasureSpec.UNSPECIFIED, MeasureSpec.EXACTLY,
		 * MeasureSpec.AT_MOST?
		 * 
		 * 
		 * MeasureSpec.EXACTLY�Ǿ�ȷ�ߴ磬
		 * �����ǽ��ؼ���layout_width��layout_heightָ��Ϊ�����ֵʱ��andorid
		 * :layout_width="50dip"������ΪFILL_PARENT�ǣ����ǿؼ���С�Ѿ�ȷ�����������Ǿ�ȷ�ߴ�?
		 * 
		 * 
		 * MeasureSpec.AT_MOST�����ߴ磬
		 * ���ؼ���layout_width��layout_heightָ��ΪWRAP_CONTENT�J
		 * ���ؼ���Сһ����������ӿռ�����ݽ��б仯����ʱ�ؼ��ߴ�ֻҪ���������ؼ�����Ėc?�ߴ缴��
		 * ����ˣ���ʱ��mode��AT_MOST��size�����˸��ؼ���������ߴ�?
		 * 
		 * 
		 * MeasureSpec.UNSPECIFIED��δָ���ߴ磬���������࣬د?���Ǹ��ؼ���AdapterView��
		 * ͨ��measure���������ģʽ?
		 */
		case MeasureSpec.AT_MOST:
		case MeasureSpec.EXACTLY:
			result = widthSize;
			break;
		}
		return result;
	}

	private int measureHeight(int pHeightMeasureSpec) {
		int result = 0;

		int heightMode = MeasureSpec.getMode(pHeightMeasureSpec);
		int heightSize = MeasureSpec.getSize(pHeightMeasureSpec);

		switch (heightMode) {
		case MeasureSpec.AT_MOST:
		case MeasureSpec.EXACTLY:
			result = heightSize;
			break;
		}
		return result;
	}

	private void firstInit() {
		startSpeed += 0.05f;
		if (startSpeed >= 1) {
			startSpeed = 0.9f;
		}
		float total = 0f;
		if (!mChartProps.isEmpty()) {
			for (int i = 0; i < itemCount; i++) {
				if (i < mChartProps.size()) {
					float percent = mChartProps.get(i).getPercent();
					// writeLog("percent="+percent);
					float distancePercent = (percents[i] - percent);

					if (distancePercent < 0.0001) {
						mChartProps.get(i).setPercent(percents[i]);

					} else {

						mChartProps.get(i).setPercent(
								percent + (distancePercent * startSpeed));
					}

					total = total + mChartProps.get(i).getPercent();
				}
			}
		}

		if (total >= 1) {
			firstEnter = false;
		}

	}

	public void getCurrentChartProp(ChartProp chartProp, float f) {

		if ((chartProp.getStartAngle() <= f) && (chartProp.getEndAngle() > f)) {

			mChartProp = chartProp;

		}
	}

	public void drawableCenterCircle(float x, float y) {
		/*
		 * Paint centerCirclePaint = new Paint();
		 * centerCirclePaint.setColor(Color.BLACK);
		 * 
		 * centerCirclePaint.setAlpha(150); mCanvas.drawCircle(x, y, radius / 3,
		 * centerCirclePaint);
		 */

		// Paint localPaint = new Paint();
		// ����ȡ����Ч��
		// localPaint.setAntiAlias(true);
		// ���ΪԲ�x
		/*
		 * localPaint.setStyle(Paint.Style.STROKE); // Բ�����
		 * localPaint.setStrokeWidth(circleRadius);
		 */
		// Բ������

		mCanvas.drawBitmap(myBg, 0, 0, null);
		mCanvas.save();

		textPaint.setColor(Color.WHITE);
		textPaint.setTextAlign(Paint.Align.CENTER);
		textPaint.setTextSize(x / 10);

		mCanvas.drawText("�ܼ�", x, y - x / 12, textPaint);
		mCanvas.drawText(PayChart.getamount(), x, y + x / 10, textPaint); // �ܼ�
		mCanvas.save();
	}

	private float getBorderAngle() {
		float borderAngle;
		int circleCount = 0;
		if (startAngle >= 0) {
			circleCount = (int) (startAngle / 360);
			if ((startAngle % 360) > (90)) {
				borderAngle = (float) (90 + 360 * (circleCount + 1));
			} else {
				borderAngle = (float) (90 + 360 * circleCount);
			}

		} else {
			circleCount = (int) (startAngle / 360);
			if ((startAngle % 360) < (-270)) {
				borderAngle = (float) (90 + 360 * (circleCount - 1));
			} else {
				borderAngle = (float) (90 + 360 * circleCount);
			}

		}

		return borderAngle;

	}

	public ChartProp getCurrentChartProp() {
		if (mChartProp != null) {
			return mChartProp;
		}
		float temp = startAngle;
		float borderAngle = getBorderAngle();

		for (int i = 0; i < itemCount; i++) {

			sweepAngle = mChartProps.get(i).getSweepAngle();
			mChartProps.get(i).setStartAngle(temp);

			temp += sweepAngle;
			mChartProps.get(i).setEndAngle(temp);

			getCurrentChartProp(mChartProps.get(i), borderAngle);
		}

		return mChartProp;
	}

	// *********************************��ÿ���ȏ�********************************
	public void drawItem(RectF localRectf) {
		float temp = startAngle;
		float borderAngle = getBorderAngle();
		// System.out.println("itemCount" + itemCount);
		if (!mChartProps.isEmpty()) {
			if (itemCount > 0) {
				for (int i = 0; i < itemCount; i++) {
					if (i < mChartProps.size()) {
						mPaint.setColor(mChartProps.get(i).getColor());
						// startAngleΪÿ���ƶ��ĽǶȴ�С
						sweepAngle = mChartProps.get(i).getSweepAngle();
						mChartProps.get(i).setStartAngle(temp);

						/*
						 * oval��Բ����ڵ���Բ����?startAngle��Բ������ʼ�Ƕȡ�sweepAngle��Բ���ĽǶ�?
						 * useCenter��
						 * �Ƿ���ʾ�뾶���ߣ�true��ʾ��ʾԲ����Բ�ĵİ뾶���ߣ�false��ʾ����ʾ?paint
						 * ������ʱ��?�õĻ���
						 */
						mCanvas.drawArc(localRectf, temp, sweepAngle, true,
								mPaint);
						// mCanvas.drawText(localRectf, temp, sweepAngle,
						// mChartProps.get(i).getName());
						mCanvas.save();

						temp += sweepAngle;
						mChartProps.get(i).setEndAngle(temp);

						getCurrentChartProp(mChartProps.get(i), borderAngle);
					}

				}
			}
		}

	}

	public boolean isRotateEnabled() {
		return rotateEnabled;
	}

	public void setRotateEnabled(boolean rotateEnabled) {
		this.rotateEnabled = rotateEnabled;
	}

	public void rotateEnable() {
		rotateEnabled = true;
	}

	public void rotateDisable() {
		rotateEnabled = false;
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {

		boolean enable = true;
		float x = centerPoint.x;
		float y = centerPoint.y;
		float y1 = event.getY();
		float x1 = event.getX();

		float x2 = v.getLeft();
		float y2 = v.getTop();

		float x3 = x1 - x2;
		float y3 = y1 - y2;

		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			m_x = x3;
			m_y = y3;
			tounched = true;

		}

		if (event.getAction() == MotionEvent.ACTION_UP) {
			m_x = 0;
			m_y = 0;
			tounched = false;

		}

		float d = (float) Math.sqrt((Math.pow(Math.abs((x - x3)), 2) + Math
				.pow(Math.abs((y - y3)), 2)));
		if (d > radius) {
			m_x = 0;
			m_y = 0;
			enable = false;

		}

		if (event.getAction() == MotionEvent.ACTION_MOVE) {

			if ((m_x == 0) && (m_y == 0)) {

				enable = false;
			}
			if (enable) {
				float c = (float) Math
						.sqrt((Math.pow(Math.abs((m_x - x3)), 2) + Math.pow(
								Math.abs((m_y - y3)), 2)));
				float a = (float) Math
						.sqrt((Math.pow(Math.abs(m_x - x), 2) + Math.pow(
								Math.abs((m_y - y)), 2)));
				float b = (float) Math
						.sqrt((Math.pow(Math.abs(x3 - x), 2) + Math.pow(
								Math.abs((y3 - y)), 2)));

				float cosc = (float) (Math.pow(a, 2) + Math.pow(b, 2) - Math
						.pow(c, 2)) / (2 * a * b);

				float m_angle = getAngle((m_x - x), (m_y - y));

				float angle3 = getAngle((x3 - x), (y3 - y));
				if ((90 > m_angle) && (angle3 > 270)) {
					m_angle = m_angle + (float) 360;
				}
				if ((90 > angle3) && (m_angle > 270)) {
					angle3 = angle3 + (float) 360;
				}
				if (angle3 - m_angle > 0) {
					startAngle = (float) (startAngle + Math.acos(cosc) * 180
							/ Math.PI);
				} else {
					startAngle = (float) (startAngle - Math.acos(cosc) * 180
							/ Math.PI);
				}
				m_x = x3;
				m_y = y3;
			}

		}

		return true;
	}

	private float getAngle(float x, float y) {

		if ((x == 0) && (y == 0)) {
			return 0;
		}

		float angle = (float) (Math.atan(y / x) * 180 / Math.PI);

		if (x == 0) {
			if (y > 0) {
				return 90;
			} else {
				return 270;
			}
		}

		if (x > 0) {
			if (y < 0) {
				return (float) 360 + angle;
			}
		}
		if (x < 0) {
			if (y > 0) {
				return (float) 180 + angle;
			} else if (y == 0) {
				return 180;
			} else if (y < 0) {
				return (float) 180 + angle;
			}

		}

		return angle;

	}
}