package com.backfire.room.manager;

import java.util.ArrayList;

import net.yeeyo.doudizhu.feiyu.R;
import android.graphics.Point;
import android.graphics.Rect;
import android.view.MotionEvent;

import com.backfire.arithmetic.Card;
import com.backfire.arithmetic.CardAssist;
import com.backfire.arithmetic.CardAuto;
import com.backfire.arithmetic.CardCompare;
import com.backfire.doudizhu.common.DdzApplication;
import com.backfire.graphics.PCanvas;
import com.backfire.room.MsgDispatcher;
import com.backfire.room.RoomActivity;
import com.backfire.room.Interface.IGetSelectCard;
import com.backfire.room.Interface.IUpdateCard;
import com.backfire.room.data.ConfigCenter;
import com.backfire.room.data.ResCenter;
import com.backfire.room.data.RoomInfo;
import com.backfire.room.data.State.GameState;
import com.backfire.utils.Log;
import com.backfire.widget.CardButton;

public class CardButtonManager implements IUpdateCard, IGetSelectCard {

	RoomActivity mContext;

	private int left = 0; // 整个手里牌绘制的左顶点
	private int right = 0; // 整个手里牌绘制的右顶点
	private int space = 0; // 牌与牌之间的间隙
	private Rect rect = null; // 捕获用户点击事件的点击区域
	private int startX = 0; // 捕获点击事件的开始位置
	private int endX = 0; // 捕获点击事件的结束位置
	private int selectLength = 0; // 滑动屏幕时选择的牌的集合
	private ArrayList<CardButton> drawCards = null; // 需要绘制的牌的集合
	private ArrayList<Integer> selectCardsIdx = null; // 被用户选择了的牌的集合
	private ArrayList<Card> selectCards = null;

	private boolean isTouchDown = false; // 按下事件是否生效

	private int max = 0; // 滑动屏幕时选择的牌的位置的最大值
	private int min = 0; // 滑动屏幕时选择的牌的位置的最小值
	private int size = 0; // 当前的牌的数量

	private byte[] mlock = null;

	public CardButtonManager(RoomActivity mContext) {
		this.mContext = mContext;
		mlock = new byte[0];
		init();
	}

	private void init() {
		drawCards = new ArrayList<CardButton>();
		selectCardsIdx = new ArrayList<Integer>();
		selectCards = new ArrayList<Card>();
		right = DdzApplication.getApplication().screenWidth;
		rect = new Rect(left, ConfigCenter.self_hand_card_PosY, right,
				ConfigCenter.self_hand_card_PosY
						+ ConfigCenter.self_hand_card_H);
		space = ConfigCenter.self_hand_card_Off_W;
	}

	public void clearAll() {
		if (drawCards != null) {
			for (CardButton card : drawCards) {
				if (card != null) {
					synchronized (card) {
						card.clear();
					}
				}
				card = null;
			}
			drawCards.clear();
			drawCards = null;
		}
		if (selectCardsIdx != null) {
			synchronized (selectCardsIdx) {
				selectCardsIdx.clear();
			}
			selectCardsIdx = null;
		}
		if (null != selectCards) {
			synchronized (selectCards) {
				selectCards.clear();
			}
			selectCards = null;
		}
		left = 0;
		right = 0;
		space = 0;
		rect = null;
		startX = 0;
		endX = 0;
		selectLength = 0;
		max = 0;
		min = 0;
		size = 0;
	}

	public void clear() {
		synchronized (mlock) {
			if (drawCards != null) {
				for (CardButton card : drawCards) {
					if (card != null) {
						synchronized (card) {
							card.clear();
						}
					}
				}
				drawCards.clear();
			}
			if (selectCardsIdx != null) {
				synchronized (selectCardsIdx) {
					selectCardsIdx.clear();
				}
			}
			if (null != selectCards) {
				synchronized (selectCards) {
					selectCards.clear();
				}
			}
			selectLength = 0;
			startX = 0;
			endX = 0;
			max = 0;
			min = 0;
			size = 0;
		}
	}

	public void draw(PCanvas canvas, int gameState, int selfState) {
		if (GameState.GAME_OVER == gameState)
			return;
		if (drawCards != null) {
			int tmpSize = drawCards.size();
			for (int i = 0; i < tmpSize; i++) {
				try {
					CardButton button = drawCards.get(i);
					if (button != null) {
						synchronized (button) {
							if (contain(i + 1)) {
								button.setIsTouch(true);
							} else {
								button.setIsTouch(false);
							}
							if (selectCardsIdx != null) {
								synchronized (selectCardsIdx) {
									if (selectCardsIdx.contains(i + 1)) {
										button.setIsUp(true);
									} else {
										button.setIsUp(false);
									}
								}
							}
							button.initDraw();
						}
						button.draw(canvas);
					}
				} catch (Exception e) {
					Log.e(this, e);
				}
			}
		}
	}

	private boolean contain(int index) {
		if (selectLength <= 100)
			return false;
		max = selectLength / 100;
		min = selectLength % 100;
		if (index >= min && index <= max) {
			return true;
		}
		return false;
	}

	public void dispatch(MotionEvent event) {
		int clickX = (int) event.getX();
		int clicky = (int) event.getY();
		if (rect.contains(clickX, clicky)) { // 当点击坐标在范围内时
			if (event.getAction() == MotionEvent.ACTION_UP) { // 当点击事件是松开时
				if (isTouchDown) {
					// 如果是松开，并且已经选择了一定的牌，则开始计算已经选择过的牌
					isTouchDown = false;
					endX = clickX;
					selectCard();
					// Log.i(this,
					// "action_up:statX="+startX+"endX="+endX+",selectLength---->"
					// + selectLength);
				}
			} else if (event.getAction() == MotionEvent.ACTION_DOWN) {// 当点击事件是按下时
				if (!isTouchDown) {
					// 如果是第一次按下，则记录下点击的位置
					startX = clickX;
					isTouchDown = true;
				}
				// Log.i(this,
				// "action_down:statX="+startX+"endX="+endX+",selectLength---->"
				// + selectLength);
			} else if (event.getAction() == MotionEvent.ACTION_MOVE) {// 当点击事件是按下时
				if (isTouchDown) {
					// 如果是移动，并且已经选择了一定的牌，则开始计算已经选择过的牌
					endX = clickX;
					selectLength = getSelectCard();

					// Log.i(this,
					// "action_move:statX="+startX+"endX="+endX+",selectLength---->"
					// + selectLength);
				}
			}
		} else { // 当点击坐标不在范围内时
			if (isTouchDown) {
				isTouchDown = false;
				selectCard();
				// Log.i(this,
				// "action_up:statX="+startX+"endX="+endX+",selectLength---->" +
				// selectLength);
				// 拖动出牌可以在这儿添加
			}
		}
	}

	private void selectCard() {
		selectLength = getSelectCard();
		max = selectLength / 100;
		min = selectLength % 100;
		if (selectCardsIdx != null) {
			synchronized (selectCardsIdx) {
				for (int i = min; i <= max; i++) {
					if (selectCardsIdx.contains((Object) i)) {
						selectCardsIdx.remove((Object) i);
					} else {
						selectCardsIdx.add(i);
					}
				}
			}
			updateSelectCard();
		}
		selectLength = 0;
		startX = 0;
		endX = 0;
	}

	/**
	 * 返回选中牌数据
	 * 
	 * @return 返回last和index的和： last=结果／100 结束index index=结果％100 开始index
	 */
	private int getSelectCard() {
		// +1是为了防止出现点击的是第0张牌
		if (endX > startX) { // 代表用户是从左到右选择
			// 首先根据起始位置和间距计算出起始位置的牌是第几张牌
			int index = (startX - left) / space + 1; // 点击起始点坐标减去牌绘制起始点坐标，然后除以每张牌的间隙，就是开始拍的位置
			int last = (endX - left) / space + 1; // 松开坐标减去牌绘制起始点坐标，然后除以每张牌的间隙，就是结束拍的位置
			if (last > size)
				last = size;
			return last * 100 + index;

		} else if (endX < startX) { // 代表用户是从右到左选择
			// 首先根据起始位置和间距计算出起始位置的牌是第几张牌
			int index = (endX - left) / space + 1; // 点击起始点坐标减去牌绘制起始点坐标，然后除以每张牌的间隙，就是开始拍的位置
			int last = (startX - left) / space + 1; // 松开坐标减去牌绘制起始点坐标，然后除以每张牌的间隙，就是结束拍的位置
			if (last > size)
				last = size;
			return last * 100 + index;
		} else {
			// 如果点击按下和松开的坐标值一样，则认为是选择了当前牌
			int index = (endX - left) / space + 1; // 点击起始点坐标减去牌绘制起始点坐标，然后除以每张牌的间隙，就是开始拍的位置
			if (index > size)
				index = size;
			return index * 100 + index;
		}
	}

	public ArrayList<Integer> getSelectCardsIdx() {
		return selectCardsIdx;
	}

	@Override
	public void unSelectAllCards() {
		isTouchDown = false;
		if (selectCardsIdx != null) {
			synchronized (selectCardsIdx) {
				selectCardsIdx.clear();
			}
		}
		if (null != selectCards) {
			synchronized (selectCards) {
				selectCards.clear();
			}
		}
	}

	private void updateSelectCard() {
		if (selectCards != null) {
			ArrayList<Card> mCards = new ArrayList<Card>();
			synchronized (selectCards) {
				selectCards.clear();
				ArrayList<Card> myCards = CardAssist.copyList(RoomInfo
						.getInstance().getMyCards());
				if (null == selectCardsIdx || null == myCards)
					return;
				// 实际选择的牌队列
				ArrayList<Card> actualSelectCards = new ArrayList<Card>();
				synchronized (myCards) {
					synchronized (selectCardsIdx) {
						for (Integer index : selectCardsIdx) {
							if (index - 1 < myCards.size() && index - 1 >= 0) {
								Card card = myCards.get(index - 1);
								if (null == card) {
									continue;
								}
								synchronized (card) {
									actualSelectCards.add(card);
								}
							}
						}
					}
				}
				// TODO:选择牌连续，然后数量超过5张，然后就从连续的选择牌（数量>=5），然后选出顺子牌
				ArrayList<Card> result = autoCard(actualSelectCards);
				// TODO:将result中的牌放入selectCards中，并且selectCardsIndex将对应的数据放入其中
				if (selectCards.isEmpty()
						&& !CardCompare.isEqualCards(result, actualSelectCards)) {// 输入和输出是不是完全一样
					for (int i = 0; i < actualSelectCards.size(); i++) {
						Card card = actualSelectCards.get(i);
						Integer integer = myCards.indexOf(card) + 1;
						if (result.contains(card)) {
							selectCards.add(card);
							mCards.add(card);
						} else {
							selectCardsIdx.remove(integer);
						}
					}
				} else {
					for (Card card : actualSelectCards) {
						selectCards.add(card);
						mCards.add(new Card(card));
					}
				}
			}
			if (null != mContext.getRoom().getBtnManager()) {
				mContext.getRoom().getBtnManager()
						.updateGameControlBtnState(mCards);
			}
		}
	}

	public ArrayList<Card> autoCard(ArrayList<Card> actualSelectCards) {
		ArrayList<Card> result = null;
		boolean isContinu5 = false;
		int selectSize = selectCardsIdx.size();
		// ①判断选择的牌连续，并且连续数量》=5
		if (selectCardsIdx.size() >= 5
				&& selectCardsIdx.get(selectSize - 1) - selectCardsIdx.get(0) == selectSize - 1) {
			isContinu5 = true;
		}
		// ②将选择的牌，抽选出所有的顺子。
		ArrayList<ArrayList<Card>> chainList = CardAuto
				.getAllCHAIN(actualSelectCards);
		ArrayList<Card> firstChain = null;
		if (null != chainList && !chainList.isEmpty()) {
			// TODO:规则：比配更多，更长
			firstChain = chainList.get(0);
		}
		// ③选取最长的顺子，然后将其他牌从selectCardsIndx和selectCards中移除
		if (isContinu5 && null != firstChain && !firstChain.isEmpty()) {
			result = firstChain;
		} else {
			result = actualSelectCards;
		}
		return result;
	}

	public ArrayList<Card> getSelectCards() {
		return selectCards;
	}

	@Override
	// 该方法在每次修改RoomInfo的myCards后调用，用于刷新用户的手里牌的显示
	public ArrayList<Point> updateCard(Card laiziCard) {
		ArrayList<Point> burstLaiziPosList = new ArrayList<Point>();
		clear();
		ArrayList<Card> myCards = RoomInfo.getInstance().getMyCards();
		if (myCards != null) {
			synchronized (myCards) {
				size = myCards.size();
				if (0 == size)
					return burstLaiziPosList;
				int matchSpace = (DdzApplication.getApplication().screenWidth - ConfigCenter.self_hand_card_W)
						/ size;
				space = (matchSpace > ConfigCenter.self_hand_card_max_Off_W ? ConfigCenter.self_hand_card_max_Off_W
						: matchSpace);

				// 计算左顶点位置
				left = (DdzApplication.getApplication().screenWidth
						- (size - 1) * space - ConfigCenter.self_hand_card_W) / 2;
				// 计算右定点位置
				right = (DdzApplication.getApplication().screenWidth
						+ (size - 1) * space + ConfigCenter.self_hand_card_W) / 2;
				// 设置事件的触发区域
				rect.set(left, ConfigCenter.self_hand_card_PosY, right,
						ConfigCenter.self_hand_card_PosY
								+ ConfigCenter.self_hand_card_H);
				// 将用户的手里牌添加到CardButton中用于显示
				for (int i = 0; i < size; i++) {
					Card card = myCards.get(i);
					if (card != null) {
						synchronized (card) {
							int icon = ResCenter.getCard(card.getColor(),
									card.getPoint(), card.isLaiZi(),
									card.isSmallLaizi(), card.isFlower());
							if (icon == R.drawable.card_back) {
								Log.i(this, card.description());
							} else if (card.isLaiZi()) {
								Log.i(this, card.description());
							}
							CardButton button = new CardButton(icon, left + i
									* space, ConfigCenter.self_hand_card_PosY,
									ConfigCenter.self_hand_card_W,
									ConfigCenter.self_hand_card_H,
									card.isLaiZi(), card.isSmallLaizi());
							if (null != laiziCard
									&& ((laiziCard.isSmallLaizi() == card
											.isSmallLaizi() && laiziCard
											.isEqualTo(card)) || (laiziCard
											.isSmallLaizi() == card
											.isSmallLaizi()
											&& laiziCard.isLaiZi() == card
													.isLaiZi() && laiziCard
												.isSamePoint(card)))) {
								Point point = new Point();
								point.set(button.getPositionX(),
										button.getPositionY());
								burstLaiziPosList.add(point);
							}
							if (drawCards != null) {
								synchronized (drawCards) {
									drawCards.add(button);
								}
							}
						}
					}
				}
			}
		}
		return burstLaiziPosList;
	}

	@Override
	public void selectCards(ArrayList<Card> promptSelectCards) {
		if (null != selectCards) {
			synchronized (selectCards) {
				selectCards.clear();
				selectCards = CardAssist.copyList(promptSelectCards);
			}
		}
		if (null == selectCardsIdx)
			return;
		ArrayList<Card> myCards = RoomInfo.getInstance().getMyCards();
		synchronized (selectCardsIdx) {
			if (null == selectCards)
				return;
			synchronized (selectCards) {
				selectCardsIdx.clear();
				for (Card card : selectCards) {
					int index = CardAssist.indexOf(card, myCards) + 1;// 由于index从1开始，所以加1
					if (index > 0) {
						selectCardsIdx.add(index);
					}
				}
			}
		}
	}
}
