package com.wasu.cs.widget;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import cn.com.wasu.main.AppUtil;
import cn.com.wasu.main.R;

import com.wasu.widget.util.UIUtil;

public class SpecialListView extends FrameLayout {

	private Context context;

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

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

	public SpecialListView(Context context, AttributeSet attrs,
			int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		init(context);
	}

	private void init(Context c) {
		context = c;
		setChildrenDrawingOrderEnabled(true);
		setClipChildren(false);
		setClipToPadding(false);
	}
	
	private Stack<ViewPackage> viewPackages = new Stack<ViewPackage>();
	private BaseAdapter adapter;
	private boolean isFirstLoad = true;
	private int showItemCount = 5;
	
	public void setAdapter(BaseAdapter adapter) {
		this.viewPackages.clear();
		this.adapter = adapter;
		if (isFirstLoad) {
			firstLoadViews();
			isFirstLoad = false;
		} else {
			reloadAllView();
		}
	}
	
	private ViewPackage createViewPackage(int position, View preItem) {
		View view = adapter.getView(position, null, null);

		if (view == null)
			return null;

		LayoutParams lp = new FrameLayout.LayoutParams(
				LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
		lp.leftMargin = 0;
		view.setLayoutParams(lp);

		ViewPackage vp = new ViewPackage(view);
		vp.setPosition(position);
		vp.setId(AppUtil.createId());

		if (preItem != null) {
			preItem.setNextFocusDownId(view.getId());
			view.setNextFocusUpId(preItem.getId());
		}

		return vp;
	}
	
	private void firstLoadViews() {
		if (adapter == null)
			return;

		removeAllViews();
		int count = adapter.getCount();
		View preView = null;
		ViewPackage vp = null;

		for (int i = 0; i < showItemCount+2; i++) {
			if(i+1 > count) break;
			
			vp = createViewPackage(i, preView);
			if (vp != null) {
				addView(vp.getView());
				viewPackages.add(vp);
				preView = vp.getView();
			}
		}

	}

	private void reloadAllView() {

	}
	
	private boolean isInitLayout = false;
	private int mSpacing = getResources().getDimensionPixelSize(R.dimen.d_21dp);
	
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		if (isInitLayout || this.adapter == null
				|| this.adapter.getCount() == 0)
			return;

		int i = 0;
		View child = null;
		int pWidth = r - l;
		int top = getPaddingTop();

		while (i < viewPackages.size()) {
			child = viewPackages.get(i).getView();

			int left = (pWidth - child.getMeasuredWidth()) / 2;
			int right = left + child.getMeasuredWidth();
			int bottom = top + child.getMeasuredHeight();
			child.layout(left, top, right, bottom);

			top += child.getMeasuredHeight() + mSpacing;

			i++;
		}

		modifyPosition();

		isInitLayout = true;
	}
	
	private View newItem = null;
	
	private void fillTop() {
		ViewPackage firstVp = viewPackages.firstElement();
		int firstPosition = firstVp.getPosition();
		View firstView = firstVp.getView();

		ViewPackage vp = viewPackages.pop();
		View view = vp.getView();
		int position = firstPosition - 1;
		if (position < 0) {
//			position = adapter.getCount() - 1;
			return;
		}
		View newView = adapter.getView(position, view, null);

		if (newView == null)
			return;

		newView.setVisibility(View.GONE);
		vp.setView(newView);
		vp.setPosition(position);

		viewPackages.insertElementAt(vp, 0);

		firstView.setNextFocusUpId(newView.getId());
		newView.setNextFocusDownId(firstView.getId());
		newView.setNextFocusUpId(newView.getId());

		int top = firstView.getTop() - newView.getMeasuredHeight() - mSpacing;
		int left = newView.getLeft();
		int right = newView.getRight();
		int bottom = top + newView.getMeasuredHeight();
		newView.layout(left, top, right, bottom);
//		newView.setY(top);
		newView.setVisibility(View.VISIBLE);
		newView.setFocusable(false);
		newItem = newView;

		modifyPosition();
	}

	private void fillDown() {
		ViewPackage lastVp = viewPackages.lastElement();
		int lastPosition = lastVp.getPosition();
		View lastView = lastVp.getView();

		ViewPackage vp = viewPackages.get(0);
		View view = vp.getView();
		viewPackages.remove(0);
		int position = lastPosition + 1;
		if (position + 1 > adapter.getCount()) {
//			position = 0;
			return;
		}
		View newView = adapter.getView(position, view, null);

		if (newView == null)
			return;

		newView.setVisibility(View.GONE);
		vp.setView(newView);
		vp.setPosition(position);

		viewPackages.add(vp);

		lastView.setNextFocusDownId(newView.getId());
		newView.setNextFocusUpId(lastView.getId());
		newView.setNextFocusDownId(newView.getId());

		int top = lastView.getTop() + lastView.getMeasuredHeight() + mSpacing;
		int left = newView.getLeft();
		int right = newView.getRight();
		int bottom = top + newView.getMeasuredHeight();
		newView.layout(left, top, right, bottom);
//		newView.setY(top);
		newView.setVisibility(View.VISIBLE);
		newView.setFocusable(false);
		newItem = newView;

		modifyPosition();
	}

	private void scrollPreItem() {
		int position = viewPackages.firstElement().getPosition();
		if(focusedItemIndex<1 && position > 0) {
			fillTop();
		}
		
		animViews(false);
	}

	private void scrollNextItem() {
		int position = viewPackages.lastElement().getPosition();
		if(focusedItemIndex > showItemCount && position+1 < adapter.getCount()) {
			fillDown();
		}
		
		animViews(true);
	}

	private int anim_duration = 200;
	
	private void animViews(boolean scrollLeft) {
		float y = focusItem.getY();
		float paddingTop = getPaddingTop();
		int maxY = getMeasuredHeight() - getPaddingBottom() - focusItem.getMeasuredHeight();
		if(y >= paddingTop && y <= maxY) {
			isDrawFocusItem = true;
			return;
		}
		
		int count = viewPackages.size();
		
		if(scrollLeft) {
			y = maxY - y;
			
		} else {
			y = paddingTop - y;
		}
		
		System.out.println("-------------iyadi y: " + y);
		
		if (y != 0) {
			List<Animator> animators = new ArrayList<Animator>();
			AnimatorSet animatorSet = new AnimatorSet();
			
			View child = viewPackages.get(0).getView();
			System.out.println("-------------iyadi child.getY(): " + child.getY());
			y = child.getY() + y;
			ObjectAnimator viewAnim = ObjectAnimator.ofFloat(child, "Y", y);
			viewAnim.setDuration(anim_duration);
			viewAnim.setInterpolator(new AccelerateDecelerateInterpolator());
			animators.add(viewAnim);
			
			View tempView = child;
			for (int i=1; i < count; i++) {
				child = viewPackages.get(i).getView();
				y += tempView.getMeasuredHeight() + mSpacing;

				viewAnim = ObjectAnimator.ofFloat(child, "Y", y);
				viewAnim.setDuration(anim_duration);
				viewAnim.setInterpolator(new AccelerateDecelerateInterpolator());
				animators.add(viewAnim);

				tempView = child;
			}

			animatorSet.playTogether(animators);
			animatorSet.addListener(new AnimatorListener() {

				@Override
				public void onAnimationStart(Animator animation) {
					// mIsScrolling = true;
					// selectedView(getSelectedView(), false);
				}

				@Override
				public void onAnimationRepeat(Animator animation) {

				}

				@Override
				public void onAnimationEnd(Animator animation) {
					isDrawFocusItem = true;
					postInvalidate();
					if (newItem != null) {
						newItem.setFocusable(true);
					}
				}

				@Override
				public void onAnimationCancel(Animator animation) {

				}
			});

			animatorSet.start();
		}
	}
	
	private void modifyPosition() {
		ViewPackage vp = null;
		for (int i = 0; i < viewPackages.size(); i++) {
			vp = viewPackages.get(i);
			ShortVideoSpecialItem item = (ShortVideoSpecialItem) vp.getView();
			item.setIndex(i);
		}
	}
	
	private int keyCode = 0;

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		this.keyCode = keyCode;
		return super.onKeyDown(keyCode, event);
	}
	
	private Drawable focusShadowDrawable;
	private boolean isDrawFocusItem = true;
	private int mFocusEdgeOffset = getResources().getDimensionPixelSize(R.dimen.d_0dp);

	@Override
	protected void dispatchDraw(Canvas canvas) {

		super.dispatchDraw(canvas);

		if (focusItem != null && isDrawFocusItem) {
			if (focusShadowDrawable == null)
				focusShadowDrawable = context.getResources().getDrawable(
						R.drawable.main_page_item_selected);

			Rect toFocusedViewRect = UIUtil.createViewRect(this, focusItem,
					mFocusEdgeOffset);

			UIUtil.drawDrawableAt(canvas, toFocusedViewRect,
					focusShadowDrawable,true);
		}
	}

	private int focusedItemIndex = -1;
	private ShortVideoSpecialItem focusItem = null;

	/**
	 * 获取子控件dispatchDraw的次序
	 */
	@Override
	protected int getChildDrawingOrder(int childCount, int i) {
		if (focusedItemIndex < 0)
			return i;

		if (i < (childCount - 1)) {
			if (focusedItemIndex == i)
				i = childCount - 1;
		} else {
			if (focusedItemIndex < childCount)
				i = focusedItemIndex;
		}

		return i;
	}
	
	/**
	 * 
	 * @author 海迪
	 * @Title: setFocusedItemIndex
	 * @Description: 设置当前获取焦点的Item及Index
	 * @param @param focusItem 获取焦点的Item
	 * @param @param focusedItemIndex 获取焦点Item的Index
	 * @return void
	 * @throws
	 * 
	 * @param focusItem
	 * @param focusedItemIndex
	 */
	public void setFocusedItemIndex(ShortVideoSpecialItem focusItem,
			int focusedItemIndex) {

		this.focusItem = focusItem;
		this.focusedItemIndex = focusedItemIndex;
		
		if(focusItem != null && onItemSelectedListener != null) {
			onItemSelectedListener.onItemSelected(focusItem, focusItem.getPosition());
		}

		this.postInvalidate();

		if (focusItem == null) {
			return;
		}

		if (adapter == null || adapter.getCount() < showItemCount) {
			return;
		}

		if (KeyEvent.KEYCODE_DPAD_DOWN == keyCode) {
			isDrawFocusItem = false;
			scrollNextItem();
		} else if (KeyEvent.KEYCODE_DPAD_UP == keyCode) {
			isDrawFocusItem = false;
			scrollPreItem();
		}

	}
	
	public interface OnItemSelectedListener {
		public void onItemSelected(View view, int position);
	}
	
	private OnItemSelectedListener onItemSelectedListener;

	public void setOnItemSelectedListener(
			OnItemSelectedListener onItemSelectedListener) {
		this.onItemSelectedListener = onItemSelectedListener;
	}
}
