/*
 * Copyright 2011 woozzu
 *
 * 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.cgt.weixin.view.widget;

import org.xbill.DNS.tests.primary;

import net.cgt.weixin.R;
import net.cgt.weixin.utils.L;
import net.cgt.weixin.utils.LogUtil;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.view.MotionEvent;
import android.widget.Adapter;
import android.widget.ListView;
import android.widget.SectionIndexer;

/**
 * 右侧的索引条
 * 
 * @author lijian-pc
 * @date 2014-11-26
 */
public class IndexScroller {

	private static final String LOGTAG = LogUtil
			.makeLogTag(IndexScroller.class);

	private Context mContext;

	/**
	 * 索引条宽度
	 **/
	private float mIndexbarWidth;
	/**
	 * 索引条外边距
	 **/
	private float mIndexbarMargin;
	/**
	 * 索引条内边距
	 **/
	private float mPreviewPadding;
	/**
	 * 密度
	 **/
	private float mDensity;
	/**
	 * 缩放密度
	 **/
	private float mScaledDensity;
	/**
	 * 透明度
	 **/
	private float mAlphaRate;
	/**
	 * 状态
	 **/
	private int mState = STATE_HIDDEN;
	/**
	 * ListView宽度
	 **/
	private int mListViewWidth;
	/**
	 * ListView高度
	 **/
	private int mListViewHeight;
	/**
	 * 当前部分
	 */
	private int mCurrentSection = -1;
	/**
	 * 是否正在索引
	 */
	private boolean mIsIndexing = false;
	/**
	 * 右侧索引文本色值
	 */
	private static final String COLOR_RIGHT_TEXT = "#565656";
	/**
	 * 右侧索引背景色值
	 */
	private static final String COLOR_RIGHT_BACKGROUND = "#808080";// "#bfbfbf";
	/**
	 * 中间预览文本色值
	 */
	private static final String COLOR_MIDDLE_TEXT = "#ffffff";
	/**
	 * 中间预览背景色值
	 */
	private static final String COLOR_MIDDLE_BACKGROUND = "#000000";// "#808080";

	private ListView mListView = null;
	private SectionIndexer mIndexer = null;
	private String[] mSections = null;
	private RectF mIndexbarRect;

	/** 4种状态(已隐藏) **/
	private static final int STATE_HIDDEN = 0;
	/** 4种状态(正在显示) **/
	private static final int STATE_SHOWING = 1;
	/** 4种状态(已显示) **/
	private static final int STATE_SHOWN = 2;
	/** 4种状态(正在隐藏) **/
	private static final int STATE_HIDING = 3;

	public IndexScroller(Context context, ListView lv) {
		this.mContext = context;
		mDensity = context.getResources().getDisplayMetrics().density;
		mScaledDensity = context.getResources().getDisplayMetrics().scaledDensity;
		mListView = lv;
		setAdapter(mListView.getAdapter());

		mIndexbarWidth = 25 * mDensity;
		mIndexbarMargin = 0 * mDensity;
		mPreviewPadding = 10 * mDensity;
	}

	public void draw(Canvas canvas) {
		if (mSections != null && mSections.length > 0) {
			onDrawRightIndexText(canvas);
		}

		if (mState == STATE_HIDDEN)
			return;

		onDrawRightIndexBackground(canvas);

		if (mSections != null && mSections.length > 0) {
			// Preview is shown when mCurrentSection is set
			// 中间预览文本
			if (mCurrentSection >= 0) {
				onDrawMiddlePreview(canvas);
			}
		}
	}

	/**
	 * 绘制右侧索引条文本
	 * 
	 * @param canvas
	 */
	private void onDrawRightIndexText(Canvas canvas) {
		L.d(LOGTAG, "onDrawRightIndexText");
		// 绘画右侧索引条的字母
		Paint indexPaint = new Paint();
		indexPaint.setColor(Color.parseColor(COLOR_RIGHT_TEXT));
		// indexPaint.setAlpha((int) (255 * mAlphaRate));
		indexPaint.setAntiAlias(true);
		indexPaint.setTextSize(14 * mScaledDensity);

		float sectionHeight = (mIndexbarRect.height() - 2 * mIndexbarMargin)
				/ mSections.length;
		float paddingTop = (sectionHeight - (indexPaint.descent() - indexPaint
				.ascent())) / 2;
		for (int i = 0; i < mSections.length; i++) {
			float paddingLeft = (mIndexbarWidth - indexPaint
					.measureText(mSections[i])) / 2;
			canvas.drawText(mSections[i], mIndexbarRect.left + paddingLeft,
					mIndexbarRect.top + mIndexbarMargin + sectionHeight * i
							+ paddingTop - indexPaint.ascent(), indexPaint);
		}
	}

	/**
	 * 绘制中间预览view
	 * 
	 * @param canvas
	 */
	private void onDrawMiddlePreview(Canvas canvas) {
		L.d(LOGTAG, "onDrawMiddlePreview");
		Paint previewPaint = new Paint(); // 用来绘画预览文本背景的画笔
		previewPaint.setColor(Color.parseColor(COLOR_MIDDLE_BACKGROUND));// 设置画笔颜色为黑色
		previewPaint.setAlpha(96); // 设置透明度
		previewPaint.setAntiAlias(true);// 设置抗锯齿
		previewPaint.setShadowLayer(3, 0, 0, Color.argb(64, 0, 0, 0)); // 设置阴影层

		Paint previewTextPaint = new Paint(); // 用来绘画预览字母的画笔
		previewTextPaint.setColor(Color.parseColor(COLOR_MIDDLE_TEXT)); // 设置画笔为白色
		previewTextPaint.setAntiAlias(true); // 设置抗锯齿
		previewTextPaint.setTextSize(60 * mScaledDensity); // 设置字体大小

		// 单个文本的宽度
		float previewTextWidth = previewTextPaint
				.measureText(mSections[mCurrentSection]);

		float previewSize = 2 * mPreviewPadding + previewTextPaint.descent()
				- previewTextPaint.ascent();

		RectF previewRect = new RectF((mListViewWidth - previewSize) / 2,
				(mListViewHeight - previewSize) / 2,
				(mListViewWidth - previewSize) / 2 + previewSize,
				(mListViewHeight - previewSize) / 2 + previewSize);

		// 中间索引的那个框
		canvas.drawRoundRect(previewRect, 5 * mDensity, 5 * mDensity,
				previewPaint);

		// 绘画索引字母
		canvas.drawText(mSections[mCurrentSection], previewRect.left
				+ (previewSize - previewTextWidth) / 2 - 1, previewRect.top
				+ mPreviewPadding - previewTextPaint.ascent() + 1,
				previewTextPaint);
	}

	/**
	 * 绘制右侧索引的背景
	 * 
	 * @param canvas
	 */
	private void onDrawRightIndexBackground(Canvas canvas) {
		L.d(LOGTAG, "onDrawRoundRectBackground");
		// mAlphaRate determines the rate of opacity
		Paint indexbarPaint = new Paint();
		// indexbarPaint.setColor(Color.BLACK);
		indexbarPaint.setColor(Color.parseColor(COLOR_RIGHT_BACKGROUND));
		indexbarPaint.setAlpha((int) (64 * mAlphaRate));
		indexbarPaint.setAntiAlias(true);
		// 画右侧字母索引的圆矩形
		// canvas.drawRoundRect(mIndexbarRect, 5 * mDensity, 5 * mDensity,
		// indexbarPaint);
		canvas.drawRect(mIndexbarRect, indexbarPaint);
	}

	public boolean onTouchEvent(MotionEvent ev) {
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			// If down event occurs inside index bar region, start indexing
			// 如果按下的事件发生在索引条区域内,开始索引
			if (contains(ev.getX(), ev.getY())) {
				setState(STATE_SHOWN);

				// It demonstrates that the motion event started from index bar
				mIsIndexing = true;
				// Determine which section the point is in, and move the list to
				// that section
				mCurrentSection = getSectionByPoint(ev.getY());

				// ListView.setSelection(int position)
				// ListView.setSelectionFromTop(int position, int y);
				// 其中
				// position指的是指定的item的在ListView中的索引,注意如果有Header存在的情况下,索引是从Header就开始算的。
				// y指的是到ListView可见范围内最上边边缘的距离。
				mListView.setSelection(mIndexer
						.getPositionForSection(mCurrentSection));
				return true;
			}
			break;
		case MotionEvent.ACTION_MOVE:
			if (mIsIndexing) {
				// If this event moves inside index bar
				if (contains(ev.getX(), ev.getY())) {
					// Determine which section the point is in, and move the
					// list to that section
					mCurrentSection = getSectionByPoint(ev.getY());
					mListView.setSelection(mIndexer
							.getPositionForSection(mCurrentSection));
				}
				return true;
			}
			break;
		case MotionEvent.ACTION_UP:
			if (mIsIndexing) {
				mIsIndexing = false;
				mCurrentSection = -1;
			}
			if (mState == STATE_SHOWN){
				setState(STATE_HIDING);
				return true;				
			}
			break;
		}
		return false;
	}

	/**
	 * 创建索引条大小
	 * 
	 * @param w
	 * @param h
	 * @param oldw
	 * @param oldh
	 */
	public void onSizeChanged(int w, int h, int oldw, int oldh) {
		mListViewWidth = w;
		mListViewHeight = h;
		mIndexbarRect = new RectF(w - mIndexbarMargin - mIndexbarWidth,
				mIndexbarMargin, w - mIndexbarMargin, h - mIndexbarMargin);
	}

	public void show() {
		if (mState == STATE_HIDDEN)
			setState(STATE_SHOWING);
		else if (mState == STATE_HIDING)
			setState(STATE_HIDING);
	}

	public void hide() {
		if (mState == STATE_SHOWN)
			setState(STATE_HIDING);
	}

	/**
	 * 设置右侧索引条数据
	 * 
	 * @param adapter
	 */
	public void setAdapter(Adapter adapter) {
		if (adapter instanceof SectionIndexer) {
			mIndexer = (SectionIndexer) adapter;
			mSections = (String[]) mIndexer.getSections();
		}
	}

	/**
	 * 设置显隐状态
	 * 
	 * @param state
	 */
	private void setState(int state) {
		if (state < STATE_HIDDEN || state > STATE_HIDING)
			return;

		mState = state;
		switch (mState) {
		case STATE_HIDDEN:
			// Cancel any fade effect
			mHandler.removeMessages(0);
			break;
		case STATE_SHOWING:
			// Start to fade in
			mAlphaRate = 0;
			fade(0);
			break;
		case STATE_SHOWN:
			// Cancel any fade effect
			mAlphaRate = 1;
			mHandler.removeMessages(0);
			break;
		case STATE_HIDING:
			// Start to fade out after three seconds
			mAlphaRate = 1;
			fade(3000);
			break;
		}
	}

	/**
	 * 检测触摸点是否在索引条区域内
	 * 
	 * @param x
	 * @param y
	 * @return
	 */
	private boolean contains(float x, float y) {
		// Determine if the point is in index bar region, which includes the
		// right margin of the bar
		return (x >= mIndexbarRect.left && y >= mIndexbarRect.top && y <= mIndexbarRect.top
				+ mIndexbarRect.height());
	}

	/**
	 * 根据触摸点的y坐标获得区域
	 * 
	 * @param y
	 * @return
	 */
	private int getSectionByPoint(float y) {
		// 如果索引字母不存在,返回0
		if (mSections == null || mSections.length == 0)
			return 0;
		// 如果在最顶部的索引字母之外,返回0
		if (y < mIndexbarRect.top + mIndexbarMargin)
			return 0;
		// 如果在最底部的索引字母之外,返回最后一个索引字母角标
		if (y >= mIndexbarRect.top + mIndexbarRect.height() - mIndexbarMargin)
			return mSections.length - 1;
		return (int) ((y - mIndexbarRect.top - mIndexbarMargin) / ((mIndexbarRect
				.height() - 2 * mIndexbarMargin) / mSections.length));
	}

	/**
	 * 设置多久后隐藏
	 * 
	 * @param delay
	 */
	private void fade(long delay) {
		mHandler.removeMessages(0);
		mHandler.sendEmptyMessageAtTime(0, SystemClock.uptimeMillis() + delay);
	}

	private Handler mHandler = new Handler() {

		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);

			switch (mState) {
			case STATE_SHOWING:
				// Fade in effect
				mAlphaRate += (1 - mAlphaRate) * 0.2;
				if (mAlphaRate > 0.9) {
					mAlphaRate = 1;
					setState(STATE_SHOWN);
				}

				mListView.invalidate();
				fade(10);
				break;
			case STATE_SHOWN:
				// If no action, hide automatically
				setState(STATE_HIDING);
				break;
			case STATE_HIDING:
				// Fade out effect
				mAlphaRate -= mAlphaRate * 0.2;
				if (mAlphaRate < 0.1) {
					mAlphaRate = 0;
					setState(STATE_HIDDEN);
				}

				mListView.invalidate();
				fade(10);
				break;
			}
		}

	};
}