* Copyright (C) 2013 Peng fei Pan <sky@xiaopan.me>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.oschina.app.widget;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.oschina.app.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
 * 专为ViewPager定制的滑动选项卡 HOME
 * 
 * @version 1.3.0
 * @author Peng fei Pan
 */
public class PagerSlidingTabStrip extends HorizontalScrollView implements
		View.OnClickListener {
	private int currentPosition; 
	private int lastOffset;
	private int lastScrollX = 0;
	private float currentPositionOffset; 
	private boolean start;
	private boolean allowWidthFull; 
	private boolean disableViewPager; 
	private View currentSelectedTabView; 
	private Drawable slidingBlockDrawable; 
	private ViewPager viewPager; 
	private ViewGroup tabsLayout; 
	private ViewPager.OnPageChangeListener onPageChangeListener; 
	private OnClickTabListener onClickTabListener;
	private OnPagerChangeLis listener;
	private List<View> tabViews;
	public PagerSlidingTabStrip(Context context) {
		this(context, null);
	}
	public PagerSlidingTabStrip(Context context, AttributeSet attrs) {
		super(context, attrs);
		setHorizontalScrollBarEnabled(false); 
		if (attrs != null) {
			TypedArray attrsTypedArray = context.obtainStyledAttributes(attrs,
					R.styleable.PagerSlidingTabStrip);
			if (attrsTypedArray != null) {
				allowWidthFull = attrsTypedArray.getBoolean(
						R.styleable.PagerSlidingTabStrip_allowWidthFull, false);
				slidingBlockDrawable = attrsTypedArray
						.getDrawable(R.styleable.PagerSlidingTabStrip_slidingBlock);
				disableViewPager = attrsTypedArray.getBoolean(
						R.styleable.PagerSlidingTabStrip_disableViewPager,
						false);
				attrsTypedArray.recycle();
			}
		}
	}
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		if (!allowWidthFull)
			return;
		ViewGroup tabsLayout = getTabsLayout();
		if (tabsLayout == null
				|| tabsLayout.getMeasuredWidth() >= getMeasuredWidth())
			return;
		if (tabsLayout.getChildCount() <= 0)
			return;
		if (tabViews == null) {
			tabViews = new ArrayList<View>();
		} else {
			tabViews.clear();
		}
		for (int w = 0; w < tabsLayout.getChildCount(); w++) {
			tabViews.add(tabsLayout.getChildAt(w));
		}
		adjustChildWidthWithParent(
				tabViews,
				getMeasuredWidth() - tabsLayout.getPaddingLeft()
						- tabsLayout.getPaddingRight(), widthMeasureSpec,
				heightMeasureSpec);
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}
	
	 * 调整views集合中的View,让所有View的宽度加起来正好等于parentViewWidth
	 * 
	 * @param views
	 *            子View集合
	 * @param parentViewWidth
	 *            父Vie的宽度
	 * @param parentWidthMeasureSpec
	 *            父View的宽度规则
	 * @param parentHeightMeasureSpec
	 *            父View的高度规则
	 */
	private void adjustChildWidthWithParent(List<View> views,
			int parentViewWidth, int parentWidthMeasureSpec,
			int parentHeightMeasureSpec) {
		
		for (View view : views) {
			if (view.getLayoutParams() instanceof MarginLayoutParams) {
				LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) view
						.getLayoutParams();
				parentViewWidth -= lp.leftMargin + lp.rightMargin;
			}
		}
		
		int averageWidth = parentViewWidth / views.size();
		int bigTabCount = views.size();
		while (true) {
			Iterator<View> iterator = views.iterator();
			while (iterator.hasNext()) {
				View view = iterator.next();
				if (view.getMeasuredWidth() > averageWidth) {
					parentViewWidth -= view.getMeasuredWidth();
					bigTabCount--;
					iterator.remove();
				}
			}
			averageWidth = parentViewWidth / bigTabCount;
			boolean end = true;
			for (View view : views) {
				if (view.getMeasuredWidth() > averageWidth) {
					end = false;
				}
			}
			if (end) {
				break;
			}
		}
		
		for (View view : views) {
			if (view.getMeasuredWidth() < averageWidth) {
				LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) view
						.getLayoutParams();
				layoutParams.width = averageWidth;
				view.setLayoutParams(layoutParams);
				
				if (layoutParams instanceof MarginLayoutParams) {
					measureChildWithMargins(view, parentWidthMeasureSpec, 0,
							parentHeightMeasureSpec, 0);
				} else {
					measureChild(view, parentWidthMeasureSpec,
							parentHeightMeasureSpec);
				}
			}
		}
	}
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		super.onLayout(changed, l, t, r, b);
		ViewGroup tabViewGroup = getTabsLayout();
		if (tabViewGroup != null) {
			
			currentPosition = viewPager != null ? viewPager.getCurrentItem()
					: 0;
			if (!disableViewPager) {
				scrollToChild(currentPosition, 0); 
				selectedTab(currentPosition); 
			}
			
			for (int w = 0; w < tabViewGroup.getChildCount(); w++) {
				View itemView = tabViewGroup.getChildAt(w);
				itemView.setTag(w);
				itemView.setOnClickListener(this);
			}
		}
	}
	@Override
	public void onClick(View v) {
		int index = (Integer) v.getTag();
		if (onClickTabListener != null) {
			onClickTabListener.onClickTab(v, index);
		}
		if (viewPager != null) {
			viewPager.setCurrentItem(index, true);
		}
	}
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		if (disableViewPager)
			return;
		
		ViewGroup tabsLayout = getTabsLayout();
		if (tabsLayout != null && tabsLayout.getChildCount() > 0
				&& slidingBlockDrawable != null) {
			View currentTab = tabsLayout.getChildAt(currentPosition);
			if (currentTab != null) {
				float slidingBlockLeft = currentTab.getLeft();
				float slidingBlockRight = currentTab.getRight();
				if (currentPositionOffset > 0f
						&& currentPosition < tabsLayout.getChildCount() - 1) {
					View nextTab = tabsLayout.getChildAt(currentPosition + 1);
					if (nextTab != null) {
						final float nextTabLeft = nextTab.getLeft();
						final float nextTabRight = nextTab.getRight();
						slidingBlockLeft = (currentPositionOffset * nextTabLeft + (1f - currentPositionOffset)
								* slidingBlockLeft);
						slidingBlockRight = (currentPositionOffset
								* nextTabRight + (1f - currentPositionOffset)
								* slidingBlockRight);
					}
				}
				slidingBlockDrawable.setBounds((int) slidingBlockLeft, 0,
						(int) slidingBlockRight, getHeight());
				slidingBlockDrawable.draw(canvas);
			}
		}
	}
	
	 * 获取布局
	 */
	private ViewGroup getTabsLayout() {
		if (tabsLayout == null) {
			if (getChildCount() > 0) {
				tabsLayout = (ViewGroup) getChildAt(0);
			} else {
				removeAllViews();
				tabsLayout = new LinearLayout(getContext());
				addView(tabsLayout, new ViewGroup.LayoutParams(
						ViewGroup.LayoutParams.WRAP_CONTENT,
						ViewGroup.LayoutParams.WRAP_CONTENT));
			}
		}
		return tabsLayout;
	}
	
	 * 滚动到指定的位置
	 */
	private void scrollToChild(int position, int offset) {
		ViewGroup tabsLayout = getTabsLayout();
		if (tabsLayout != null && tabsLayout.getChildCount() > 0
				&& position < tabsLayout.getChildCount()) {
			View view = tabsLayout.getChildAt(position);
			if (view != null) {
				
				int newScrollX = view.getLeft() + offset;
				if (position > 0 || offset > 0) {
					newScrollX -= 240 - getOffset(view.getWidth()) / 2;
				}
				
				if (newScrollX != lastScrollX) {
					lastScrollX = newScrollX;
					scrollTo(newScrollX, 0);
				}
			}
		}
	}
	
	 * 获取偏移量
	 */
	private int getOffset(int newOffset) {
		if (lastOffset < newOffset) {
			if (start) {
				lastOffset += 1;
				return lastOffset;
			} else {
				start = true;
				lastOffset += 1;
				return lastOffset;
			}
		}
		if (lastOffset > newOffset) {
			if (start) {
				lastOffset -= 1;
				return lastOffset;
			} else {
				start = true;
				lastOffset -= 1;
				return lastOffset;
			}
		} else {
			start = true;
			lastOffset = newOffset;
			return lastOffset;
		}
	}
	
	 * 选中指定位置的TAB
	 */
	private void selectedTab(int currentSelectedTabPosition) {
		ViewGroup tabsLayout = getTabsLayout();
		if (currentSelectedTabPosition > -1 && tabsLayout != null
				&& currentSelectedTabPosition < tabsLayout.getChildCount()) {
			if (currentSelectedTabView != null) {
				currentSelectedTabView.setSelected(false);
			}
			currentSelectedTabView = tabsLayout
					.getChildAt(currentSelectedTabPosition);
			if (currentSelectedTabView != null) {
				currentSelectedTabView.setSelected(true);
			}
		}
	}
	
	 * 添加Tab
	 */
	public void addTab(View tabView, int index) {
		if (tabView != null) {
			getTabsLayout().addView(tabView, index);
			requestLayout();
		}
	}
	
	 * 添加Tab
	 */
	public void addTab(View tabView) {
		addTab(tabView, -1);
	}
	
	 * 添加Tab
	 * 
	 * @param tabViews
	 *            可以一次添加多个Tab
	 */
	public void addTab(View... tabViews) {
		if (tabViews != null) {
			for (View view : tabViews) {
				getTabsLayout().addView(view);
			}
			requestLayout();
		}
	}
	
	 * 添加Tab
	 */
	public void addTab(List<View> tabViews) {
		if (tabViews != null) {
			for (View view : tabViews) {
				getTabsLayout().addView(view);
			}
			requestLayout();
		}
	}
	
	
	 * 移除一个tab
	 * 
	 * @param index
	 */
	public void removeTab(int index) {
		removeTab(index, 1);
	}
	
	
	 * 移除tab
	 * 
	 * @param start 开始位置
	 * @param count 移除的数量
	 */
	public void removeTab(int start, int count) {
		int tabCount = getTabCount();
		if (start < 0 || start > tabCount) {
			start = 0;
		}
		if (count < 0 || count > tabCount) {
			count = 1;
		}
		if (count - start > tabCount) {
			count = tabCount - start;
		}
		
		getTabsLayout().removeViews(start, count);
		requestLayout();
	}
	
	
	 * 移除所有
	 */
	public void removeAllTab() {
		getTabsLayout().removeAllViews();
		requestLayout();
	}
	
	public View getChild(int idx) {
		return getTabsLayout().getChildAt(idx);
	}
	public View getBadgeView(int i) {
		return getTabsLayout().getChildAt(i).findViewById(R.id.tab_mes);
	}
	
	 * 设置ViewPager
	 * 
	 * @param viewPager
	 *            ViewPager
	 */
	public void setViewPager(ViewPager viewPager) {
		if (disableViewPager)
			return;
		this.viewPager = viewPager;
		this.viewPager.setOnPageChangeListener(new OnPageChangeListener() {
			@Override
			public void onPageSelected(int position) {
				selectedTab(position);
				if (onPageChangeListener != null) {
					onPageChangeListener.onPageSelected(position);
				}
				if (listener != null)
					listener.onChanged(position);
			}
			@Override
			public void onPageScrolled(int nextPagePosition,
					float positionOffset, int positionOffsetPixels) {
				ViewGroup tabsLayout = getTabsLayout();
				if (nextPagePosition < tabsLayout.getChildCount()) {
					View view = tabsLayout.getChildAt(nextPagePosition);
					if (view != null) {
						currentPosition = nextPagePosition;
						currentPositionOffset = positionOffset;
						scrollToChild(nextPagePosition,
								(int) (positionOffset * view.getWidth()));
						invalidate();
					}
				}
				if (onPageChangeListener != null) {
					onPageChangeListener.onPageScrolled(nextPagePosition,
							positionOffset, positionOffsetPixels);
				}
			}
			@Override
			public void onPageScrollStateChanged(int arg0) {
				if (onPageChangeListener != null) {
					onPageChangeListener.onPageScrollStateChanged(arg0);
				}
			}
		});
		requestLayout();
	}
	
	 * 设置Page切换监听器
	 * 
	 * @param onPageChangeListener
	 *            Page切换监听器
	 */
	public void setOnPageChangeListener(
			OnPageChangeListener onPageChangeListener) {
		this.onPageChangeListener = onPageChangeListener;
	}
	
	 * 设置是否充满屏幕
	 * 
	 * @param allowWidthFull
	 *            true:当内容的宽度无法充满屏幕时,自动调整每一个Item的宽度以充满屏幕
	 */
	public void setAllowWidthFull(boolean allowWidthFull) {
		this.allowWidthFull = allowWidthFull;
		requestLayout();
	}
	
	 * 设置滑块图片
	 */
	public void setSlidingBlockDrawable(Drawable slidingBlockDrawable) {
		this.slidingBlockDrawable = slidingBlockDrawable;
		requestLayout();
	}
	
	 * 获取Tab总数
	 */
	public int getTabCount() {
		ViewGroup tabsLayout = getTabsLayout();
		return tabsLayout != null ? tabsLayout.getChildCount() : 0;
	}
	
	 * 设置Tab点击监听器
	 * 
	 * @param onClickTabListener
	 *            Tab点击监听器
	 */
	public void setOnClickTabListener(OnClickTabListener onClickTabListener) {
		this.onClickTabListener = onClickTabListener;
	}
	
	 * 设置不使用ViewPager
	 * 
	 * @param disableViewPager
	 *            不使用ViewPager
	 */
	public void setDisableViewPager(boolean disableViewPager) {
		this.disableViewPager = disableViewPager;
		if (viewPager != null) {
			viewPager.setOnPageChangeListener(onPageChangeListener);
			viewPager = null;
		}
		requestLayout();
	}
	
	 * Tab点击监听器
	 * 
	 * @author xiaopan
	 * 
	 */
	public interface OnClickTabListener {
		public void onClickTab(View tab, int index);
	}
	public void setOnPagerChange(OnPagerChangeLis l) {
		this.listener = l;
	}
	public interface OnPagerChangeLis {
		void onChanged(int page);
	}
}