/*
 * Copyright (c) 2014. [email protected]
 *
 * 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 com.lzc.switchbutton.widget;

import java.util.concurrent.atomic.AtomicInteger;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.StateListDrawable;
import android.os.Build;
import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.TypedValue;
import android.view.Gravity;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;

import com.lzc.switchbutton.R;

/**
 * 选项卡
 * 
 * @author LiangZiChao created on 2014-8-28下午3:19:45
 */
@SuppressLint("Recycle")
public class SwitchButton extends RadioGroup implements OnCheckedChangeListener {

	private final int[] CHECKED_STATE = { android.R.attr.state_checked }, UNCHECKED_STATE = { -android.R.attr.state_checked };

	/** 默认选项卡数量 */
	private final static int DEFAULT_SWITCH_COUNT = 2;

	private final static int EX = 5;// 余量

	private ColorStateList mTextColor;

	private int mParentWidth, mParentHeight;

	private int mRadioStyle;

	private float cornerRadius, textSize;

	private int checkedColor, unCheckedColor, strokeColor, strokeWidth;

	private CharSequence[] mTexts;

	private int switchCount;

	// 是否测量完毕
	private boolean isMeasure;

	private SparseArray<RadioButton> mRadioArrays;
	private SparseArray<Drawable> mButtonDrawables;
	private SparseArray<StateListDrawable> mStateDrawables;
	private SparseIntArray mSparseIds;

	private int mCurrentPosition;

	private OnChangeListener changeListener;

	/**
	 * @param context
	 */
	public SwitchButton(Context context) {
		super(context, null);
	}

	public SwitchButton(Context context, AttributeSet attrs) {
		super(context, attrs);
		TypedArray a = context.obtainStyledAttributes(attrs, new int[] { android.R.attr.orientation, android.R.attr.layout_height });
		setOrientation(a.getInt(0, LinearLayout.HORIZONTAL));
		mParentHeight = a.getDimensionPixelSize(1, 0);
		a.recycle();
		a = context.obtainStyledAttributes(attrs, R.styleable.switchButton);
		setTextColor(a.getColorStateList(R.styleable.switchButton_android_textColor));
		setTextArray(a.getTextArray(R.styleable.switchButton_sw_textArray));
		setSwitchCount(a.getInteger(R.styleable.switchButton_sw_switchCount, DEFAULT_SWITCH_COUNT));
		setSwitchStyle(a.getResourceId(R.styleable.switchButton_sw_ThemeStyle, 0));
		setCornerRadius(a.getDimension(R.styleable.switchButton_sw_CornerRadius, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5f, getResources().getDisplayMetrics())));
		setCheckedColor(a.getColor(R.styleable.switchButton_sw_checkedColor, Color.GREEN));
		setUnCheckedColor(a.getColor(R.styleable.switchButton_sw_unCheckedColor, Color.WHITE));
		setStrokeColor(a.getColor(R.styleable.switchButton_sw_strokeColor, Color.GREEN));
		setStrokeWidth((int) a.getDimension(R.styleable.switchButton_sw_strokeWidth, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1f, getResources().getDisplayMetrics())));
		setTextSize(a.getDimension(R.styleable.switchButton_android_textSize, 0f));
		a.recycle();
		setOnCheckedChangeListener(this);
	}

	/**
	 * 初始化UI
	 * 
	 * @param context
	 */
	@SuppressWarnings("deprecation")
	@SuppressLint("NewApi")
	private void initUI(Context context) {
		if (mTexts != null && mTexts.length != switchCount) {
			throw new IllegalArgumentException("The textArray's length must equal to the switchCount");
		}
		if (mParentWidth == 0)
			return;
		ColorDrawable colorDrawable = new ColorDrawable();
		LayoutParams mParams = new LayoutParams(mParentWidth / (switchCount > 2 ? switchCount : (switchCount + 1)), mParentHeight, 1),
				mFirstParams = new LayoutParams(mParentWidth / (switchCount > 2 ? switchCount : (switchCount + 1)), mParentHeight, 1);
		for (int i = 0; i < switchCount; i++) {
			if (mRadioArrays == null)
				mRadioArrays = new SparseArray<RadioButton>();
			RadioButton mRadioButton = mRadioArrays.get(i, createRadioView());
			mParams.leftMargin = i > 0 ? -strokeWidth : 0;
			mRadioButton.setLayoutParams(i == 0 ? mFirstParams : mParams);
			mRadioButton.setButtonDrawable(mButtonDrawables != null ? mButtonDrawables.get(i, colorDrawable) : colorDrawable);
			if (Build.VERSION.SDK_INT >= 16) {
				mRadioButton.setBackground(getStateDrawable(i));
			} else {
				mRadioButton.setBackgroundDrawable(getStateDrawable(i));
			}
			mRadioButton.setText(mTexts[i]);
			if (mRadioButton.getId() < 0) {
				int id = getViewId();
				if (mSparseIds == null)
					mSparseIds = new SparseIntArray();
				mSparseIds.put(i, id);
				mRadioButton.setId(id);
			} else {
				removeView(mRadioButton);
			}
			mRadioButton.setChecked(mCurrentPosition == i);
			addView(mRadioButton, i);
			mRadioArrays.put(i, mRadioButton);
		}
	}

	private Drawable getStateDrawable(int i) {
		if (mStateDrawables == null)
			mStateDrawables = new SparseArray<StateListDrawable>();
		StateListDrawable mStateListDrawable = mStateDrawables.size() >= i + 1 && (i != switchCount - 1 || i == switchCount - 1) ? null : mStateDrawables.get(i);
		if (mStateListDrawable == null) {
			float leftRadius = i == 0 ? cornerRadius : 0;
			float rightRadius = i == 0 ? 0 : i == switchCount - 1 ? cornerRadius : 0;
			float[] cRadius = { leftRadius, leftRadius, rightRadius, rightRadius, rightRadius, rightRadius, leftRadius, leftRadius };
			mStateListDrawable = new StateListDrawable();
			GradientDrawable cornerDrawable = new GradientDrawable();
			cornerDrawable.setColor(checkedColor);
			cornerDrawable.setCornerRadii(cRadius);
			mStateListDrawable.addState(CHECKED_STATE, cornerDrawable);
			cornerDrawable = new GradientDrawable();
			cornerDrawable.setColor(unCheckedColor);
			cornerDrawable.setStroke(strokeWidth, strokeColor);
			cornerDrawable.setCornerRadii(cRadius);
			mStateListDrawable.addState(UNCHECKED_STATE, cornerDrawable);
			mStateDrawables.put(i, mStateListDrawable);
		}
		return mStateListDrawable;
	}

	private RadioButton createRadioView() {
		RadioButton mRadioButton = new RadioButton(getContext(), null, mRadioStyle > 0 ? mRadioStyle : android.R.attr.radioButtonStyle);
		if (mRadioStyle == 0) {
			mRadioButton.setGravity(Gravity.CENTER);
			mRadioButton.setEllipsize(TruncateAt.END);
		}
		if (mTextColor != null)
			mRadioButton.setTextColor(mTextColor);
		if (textSize > 0)
			mRadioButton.setTextSize(textSize);
		return mRadioButton;
	}

	@Deprecated
	public void initialize() {
		notifyDataSetChange();
	}

	/**
	 * 刷新数据(Button数量跟随刷新的文本数据变化)
	 */
	public void notifyDataSetChange() {
		removeAllViews();
		switchCount = mTexts != null ? mTexts.length : switchCount;
		initUI(getContext());
	}

	@Override
	public void onWindowFocusChanged(boolean hasFocus) {
		super.onWindowFocusChanged(hasFocus);
		if (!isMeasure) {
			initUI(getContext());
			isMeasure = !isMeasure;
		}
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		mParentWidth = widthMeasureSpec - EX;
		mParentHeight = mParentHeight == 0 ? heightMeasureSpec : mParentHeight;
	}

	@Override
	public void onCheckedChanged(RadioGroup group, int checkedId) {
		if (changeListener != null)
			changeListener.onChange(mSparseIds.indexOfValue(checkedId));
	}

	/**
	 * 设置当前选中项
	 * 
	 * @param selectedPosition
	 */
	public void setCurrentPosition(int selectedPosition) {
		if (selectedPosition >= 0 && selectedPosition <= switchCount) {
			mCurrentPosition = selectedPosition;
		}
	}

	/**
	 * 设置选中项
	 * 
	 * @param selectedPosition
	 */
	public void setCheckedPosition(int selectedPosition) {
		if (selectedPosition >= 0 && selectedPosition <= switchCount) {
			mCurrentPosition = selectedPosition;
			if (mSparseIds != null)
				check(mSparseIds.get(mSparseIds.keyAt(selectedPosition)));
		}
	}

	public void setTextColor(ColorStateList mTextColor) {
		this.mTextColor = mTextColor;
	}

	public void setSwitchStyle(int mSwitchStyle) {
		this.mRadioStyle = mSwitchStyle;
	}

	public void setTextArray(CharSequence[] mTexts) {
		this.mTexts = mTexts;
	}

	public int getSwitchCount() {
		return switchCount;
	}

	public void setParentWidth(int mParentWidth) {
		this.mParentWidth = mParentWidth;
	}

	public void setParentHeight(int mParentHeight) {
		this.mParentHeight = mParentHeight;
	}

	public void setSwitchCount(int switchCount) {
		this.switchCount = switchCount < 2 ? DEFAULT_SWITCH_COUNT : switchCount;
		if (mButtonDrawables == null)
			mButtonDrawables = new SparseArray<Drawable>();
	}

	public void setCornerRadius(float cornerRadius) {
		this.cornerRadius = cornerRadius;
	}

	public void setCheckedColor(int checkedColor) {
		this.checkedColor = checkedColor;
	}

	public void setUnCheckedColor(int unCheckedColor) {
		this.unCheckedColor = unCheckedColor;
	}

	public void setStrokeColor(int strokeColor) {
		this.strokeColor = strokeColor;
	}

	public void setStrokeWidth(int strokeWidth) {
		this.strokeWidth = strokeWidth;
	}

	public void setTextSize(float textSize) {
		this.textSize = textSize;
	}

	public void setSwitchButton(int position, int mDrawableResId) {
		mButtonDrawables.put(position, getResources().getDrawable(mDrawableResId));
	}

	public void setOnChangeListener(OnChangeListener eventListener) {
		this.changeListener = eventListener;
	}

	public interface OnChangeListener {
		public void onChange(int position);
	}

	private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);

	public int getViewId() {
		for (;;) {
			final int result = sNextGeneratedId.get();
			// aapt-generated IDs have the high byte nonzero; clamp to the range
			// under that.
			int newValue = result + 1;
			if (newValue > 0x00FFFFFF)
				newValue = 1; // Roll over to 1, not 0.
			if (sNextGeneratedId.compareAndSet(result, newValue)) {
				return result;
			}
		}
	}
}