package com.wasu.cs.widget.mediacontrol;

import java.util.List;

import com.wasu.widget.util.UIUtil;

import android.animation.AnimatorListenerAdapter;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
 * 循环滚动控件
 */
@SuppressLint("NewApi") 
public class SidePanelNavigator extends FrameLayout {

	private static final int ANIMATION_DURATION = 300;
	private int unselectColor = Color.parseColor("#80ffffff");
	private int selectColor = Color.parseColor("#ffffff00");

	/**
	 * 当前选中的index
	 */
	private int selectedViewIndex;
	/**
	 * 初始选中默认check的index
	 */
	private int checkedViewIndex;

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

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

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

	private void init(Context context) {
		selectedViewIndex = -1;
		checkedViewIndex = -1;
	}

	public void setNavigatorChildrenModel(List<INavigatorChildModel> childrenModel) {
		if (null == childrenModel)
			return;

		removeAllViews();

		for (int i = 0; i < childrenModel.size(); i++) {
			INavigatorChildModel model = childrenModel.get(i);

			LinearLayout child = new LinearLayout(getContext());
			child.setOrientation(LinearLayout.VERTICAL);
			child.setPadding(model.getPaddingLeft(), model.getPaddingTop(), model.getPaddingRight(), model.getPaddingBottom());
			child.setTag(model);
			
			LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0);
			lp.weight = 1;
			
			TextView title = new TextView(getContext());
			title.setLayoutParams(lp);
			title.setText(model.getString());
			title.setTextColor(unselectColor);
			title.setTextSize(TypedValue.COMPLEX_UNIT_PX, model.getTextSize());
			title.setGravity(Gravity.CENTER);
			
			TextView hint = new TextView(getContext());
			hint.setLayoutParams(lp);
			hint.setText(model.getHintString());
			hint.setTextColor(unselectColor);
			hint.setTextSize(TypedValue.COMPLEX_UNIT_PX, model.getHintTextSize());
			hint.setGravity(Gravity.CENTER);
			hint.setVisibility(View.GONE);
			
			child.addView(title);
			child.addView(hint);

			FrameLayout.LayoutParams childLp = new FrameLayout.LayoutParams(model.getWidth(), model.getHeight());
			childLp.gravity = Gravity.CLIP_VERTICAL;
			addView(child, childLp);
		}

		requestLayout();
	}

	public void clearNavigatorChildrenModel() {
		this.removeAllViews();
		requestLayout();
	}

	public int getSelectedViewIndex() {
		return selectedViewIndex;
	}

	public void setSelectedViewIndex(int index) {
		if (-1 < index && index < getChildCount()) {
			checkedViewIndex = index;
			
			View v = getChildAt(selectedViewIndex);
			if (v != null) {
				onSelectEvent(v, false);
				v.animate().setDuration(ANIMATION_DURATION).translationY(0).scaleX(1.0f).scaleY(1.0f);
			}
			
			selectedViewIndex = index;
			v = getChildAt(selectedViewIndex);
			
			if (v != null) {
				onSelectEvent(v, true);
				v.animate().setDuration(ANIMATION_DURATION).translationY(0).scaleX(1.5f).scaleY(1.5f);
			}
		}
	}

	public View getSelectedView() {
		if (-1 == selectedViewIndex) {
			return null;
		}
		return getChildAt(selectedViewIndex);
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {

		int viewCount = getChildCount();

		if (-1 == selectedViewIndex) {
			if (0 < getChildCount()) {
				selectedViewIndex = 0;
				onSelectEvent(getChildAt(selectedViewIndex), true);
			} else {
				super.onLayout(changed, l, t, r, b);
				return;
			}
		}

		if (0 < viewCount)
			layoutInLoopMode(changed, l, t, r, b);

	}

	private int getLoopItemIndex(int total, int start, int offset) {
		if (0 == total)
			return 0;
		if (offset > 0) {
			return (start + offset) % total;
		} else {
			offset = offset % total;
			return (start + (total + offset)) % total;
		}
	}

	private void layoutInLoopMode(boolean changed, int l, int t, int r, int b) {
		View selectedView = getChildAt(selectedViewIndex);

		int parentCentralX = (b - t) / 2;
		int selectedViewTop = parentCentralX - (selectedView.getMeasuredHeight() / 2);
		int totalViewCount = getChildCount();
		selectedView.layout(getPaddingLeft(), selectedViewTop, getPaddingRight() + selectedView.getMeasuredWidth(), selectedViewTop + selectedView.getMeasuredHeight());
		
		if (totalViewCount == 1) {
			return;
		}

		int i = 0;
		int offsetXBottom = selectedViewTop;
		int processedView = 1;
		for (;;) {
			int prevIndex = getLoopItemIndex(totalViewCount, selectedViewIndex, --i);
			View view = getChildAt(prevIndex);

			view.layout(getPaddingLeft(), offsetXBottom - view.getMeasuredHeight(), getPaddingRight() + view.getMeasuredWidth(), offsetXBottom);

			offsetXBottom -= view.getMeasuredHeight();
			processedView++;

			if (processedView >= (totalViewCount / 2)) {
				break;
			}
		}

		i = 0;
		int offsetXTop = selectedViewTop + selectedView.getMeasuredHeight();
		for (;;) {

			if (processedView >= totalViewCount) {
				break;
			}

			int nextIndex = getLoopItemIndex(totalViewCount, selectedViewIndex, ++i);

			View view = getChildAt(nextIndex);

			view.layout(getPaddingLeft(), offsetXTop, getPaddingRight() + view.getMeasuredWidth(), offsetXTop + view.getMeasuredHeight());

			offsetXTop += view.getMeasuredHeight();
			processedView++;

		}

	}

	private int focusId = android.R.color.transparent;
	private boolean drawFocusOnTop = true;

	public void setFocusResId(int resId) {
		focusId = resId;
	}

	public void setDrawFocusOnTop(boolean top) {
		drawFocusOnTop = top;
	}

	@Override
	protected void dispatchDraw(Canvas canvas) {
		if (drawFocusOnTop) {
			super.dispatchDraw(canvas);
			drawFocusStatic(canvas);
		} else {
			drawFocusStatic(canvas);
			super.dispatchDraw(canvas);
		}
	}

	private void drawFocusStatic(Canvas canvas) {
		View view = getSelectedView();
		if (null == view)
			return;

		Rect rect = new Rect();

		// draw shadow and highlighted focus.
		UIUtil.getViewRect(view,null, rect);
		UIUtil.drawDrawableAt(canvas, rect, getResources().getDrawable(focusId), true);

	}




	public void goNext() {
		int next = getLoopItemIndex(getChildCount(), selectedViewIndex, 1);
		if (getChildCount() <= next) {
			return;
		}

		onSelectEvent(getSelectedView(), false);
		selectedViewIndex = next;
		requestLayout();
		animateNextPrev(true);
		invalidate();
	}

	public void goPrev() {
		int prev = getLoopItemIndex(getChildCount(), selectedViewIndex, -1);
		if (prev < 0) {
			return;
		}

		onSelectEvent(getSelectedView(), false);
		selectedViewIndex = prev;
		requestLayout();
		animateNextPrev(false);
		invalidate();
	}

	public void click() {
		View view = getSelectedView();
		if (null != view) {
			INavigatorChildModel model = (INavigatorChildModel) view.getTag();
			
			setSelectedViewIndex(getSelectedViewIndex());
			if (null != model) {
				model.onClick();
			}
		}
	}

	private void onSelectEvent(final View view, boolean selected) {
		ViewGroup parent = (ViewGroup) view;
		if (null != parent) {
			INavigatorChildModel model = (INavigatorChildModel) parent.getTag();
			
			TextView title = (TextView) parent.getChildAt(0);
			TextView hint = (TextView) parent.getChildAt(1);
			if (selected) {
				if (selectedViewIndex == checkedViewIndex) {
					if (!TextUtils.isEmpty(model.getHintString().trim())) {
						hint.setVisibility(View.VISIBLE);
						title.setText(model.getString());
					}
				}
				
				// tx.setShadowLayer(20.f, 0.f, 0.f, Color.YELLOW);
				title.setTextColor(selectColor);
				hint.setTextColor(selectColor);
			} else {
				if (selectedViewIndex == checkedViewIndex) {
					if (!TextUtils.isEmpty(model.getHintString().trim())) {
						hint.setVisibility(View.GONE);
						title.setText(model.getHintString() + model.getString());
					}
				}
				
				// tx.setShadowLayer(0.f, 0.f, 0.f, Color.WHITE);
				title.setTextColor(unselectColor);
				hint.setTextColor(unselectColor);
			}
		}
	}

	private void animateNextPrev(final boolean next) {
		final ViewTreeObserver observer = this.getViewTreeObserver();
		observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {

			@Override
			public boolean onPreDraw() {
				getViewTreeObserver().removeOnPreDrawListener(this);

				int totalViewCount = getChildCount();
				View toView = getChildAt(selectedViewIndex);
				View fromView = null;
				int delta = 0;
				if (next) {
					// / We are going up to highlight next.
					fromView = getChildAt(getLoopItemIndex(totalViewCount, selectedViewIndex, -1));
					if (fromView != null) {
						delta = -(fromView.getMeasuredHeight() + toView.getMeasuredHeight()) / 2;
					}
				} else {
					// / We are going down to highlight prev.
					fromView = getChildAt(getLoopItemIndex(totalViewCount, selectedViewIndex, 1));
					if (fromView != null) {
						delta = (fromView.getMeasuredHeight() + toView.getMeasuredHeight()) / 2;
					}
				}

				boolean isFirstAnimation = true;
				for (int i = 0; i < getChildCount(); i++) {
					View child = getChildAt(i);
					// / We need to change back to the previous state.
					child.setTranslationY(-delta);
					if (child == toView) {
						child.animate().setDuration(ANIMATION_DURATION).translationY(0).scaleX(1.5f).scaleY(1.5f);
					} else if (child == fromView) {
						child.animate().setDuration(ANIMATION_DURATION).translationY(0).scaleX(1.0f).scaleY(1.0f);
					} else {
						child.animate().setDuration(ANIMATION_DURATION).translationY(0);
					}
					if (isFirstAnimation) {
						child.animate().setListener(new AnimatorListenerAdapter() {
							@Override
							public void onAnimationEnd(android.animation.Animator animation) {
								onSelectEvent(getSelectedView(), true);
								invalidate();
							};
						});

					}
					isFirstAnimation = false;
				}

				return true;
			}
		});
	}

	public void refresh() {
		for (int i = 0; i < getChildCount(); i++) {
			ViewGroup parent = (ViewGroup) getChildAt(i);
			INavigatorChildModel model = (INavigatorChildModel) parent.getTag();
			TextView title = (TextView) parent.getChildAt(0);
			TextView hint = (TextView) parent.getChildAt(1);
			title.setText(model.getString());
			hint.setText(model.getHintString());
		}
	}

	public interface INavigatorChildModel {

		int getWidth();

		int getHeight();

		int getPaddingLeft();

		int getPaddingTop();

		int getPaddingRight();

		int getPaddingBottom();

		int getTextSize();
		
		int getHintTextSize();

		String getString();
		
		String getHintString();

		void onClick();
	}
}
