package com.zcw.widget;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

public class MonthView extends ViewGroup{
	static final Calendar calendar = Calendar.getInstance(Locale.getDefault());
	
	int thisYear = 1970;
	int thisMonth = 0;
	long time;
	
	/** 视图回收列表*/
	protected List<View> scrapCellViews = new ArrayList<View>(7);
	
	/** 每个视图的宽度*/
	protected int cellWidth;
	/** 每个视图的高度*/
	protected int cellHeight;
	
	/** 元素间距*/
	protected final int cellPadding = 0;
	/** 元素列*/
	protected final int cellColums = 7;
	protected final int cellRows = 6;
	
	protected MonthAdapter adapter;
	
	public MonthView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		setup(context);
	}
	
	public MonthView(Context context, AttributeSet attrs) {
		super(context, attrs);
		setup(context);
	}
	public MonthView(Context context) {
		super(context);
		setup(context);
	}
	
	private void setup(Context context) {
	}
	
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int widthSize = MeasureSpec.getSize(widthMeasureSpec);
		int heightSize = MeasureSpec.getSize(heightMeasureSpec);
		final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
		
		cellWidth = (int)((widthSize - getPaddingLeft() - getPaddingRight() - cellPadding  * (cellColums - 1)) / cellColums );
		cellHeight = cellWidth;
		
		widthSize = getPaddingLeft() + getPaddingRight() + cellColums * cellWidth + cellPadding  * (cellColums - 1);
		if(heightMode == MeasureSpec.UNSPECIFIED || heightMode == MeasureSpec.AT_MOST){
			int maxHeightSize = getPaddingBottom() + getPaddingTop() + cellPadding * (cellRows - 1) + cellRows * cellHeight;
			heightSize = Math.min(heightSize, maxHeightSize);
		}
		setMeasuredDimension(widthSize, heightSize);
	}
	
	@Override
	protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
		if(adapter == null){
			scrapAllViews();
			return;
		}
		
		if(changed){
			scrapAllViews();
		}
		layoutChildren();
	}
	
	protected void layoutChildren() {
		int index = 0;
		int left ;
		int top = getPaddingTop();
		calendar.setTimeInMillis(time);
		
		for (int row = 0; row < cellRows; row++) {
			left = getPaddingLeft();
			for (int col = 0; col < cellColums; col++) {
				makeAndAddCellView(left, top, index);
				index++;
				left += (cellWidth + cellPadding);
				calendar.add(Calendar.DAY_OF_MONTH, 1);
			}
			top += (cellHeight + cellPadding);
		}
		
		postInvalidate();
	}
	
	/**
	 * @param left
	 * @param top
	 * @param index
	 */
	protected void makeAndAddCellView(int left, int top, int index) {
		final boolean recycled = !scrapCellViews.isEmpty();
		final View child = recycled ? (scrapCellViews.remove(0)) : (adapter.createCellView(this, index));
		adapter.bindCellView(this, child, index, calendar);
		
		LayoutParams lp = child.getLayoutParams();
		if(lp == null){
			lp = new LayoutParams(cellWidth, cellHeight);
		}
		
		if(recycled){
			attachViewToParent(child, index, lp);
		}else{
			addViewInLayout(child, index, lp, true);
		}
		
		final boolean needToMeasure = !recycled || child.isLayoutRequested();
		
		if (needToMeasure) {
		    final int childWidthSpec = getChildMeasureSpec(
		            MeasureSpec.makeMeasureSpec(cellWidth, MeasureSpec.EXACTLY), 0, lp.width);
		    final int childHeightSpec = getChildMeasureSpec(
		            MeasureSpec.makeMeasureSpec(cellHeight, MeasureSpec.EXACTLY), 0, lp.height);
		    child.measure(childWidthSpec, childHeightSpec);
		} else {
		    cleanupLayoutState(child);
		}
		
		if (needToMeasure) {
			child.layout(left, top,left + cellWidth, top + cellHeight);
		} else {
			child.offsetLeftAndRight(left - child.getLeft());
			child.offsetTopAndBottom(top - child.getTop());
		}
	}
	
	private void scrapView(View child){
		scrapCellViews.add(child);
		detachViewFromParent(child);
	}
	
	private void scrapAllViews(){
		final int childCount = getChildCount();
		for (int i = 0; i < childCount; i++) {
			final View child = getChildAt(i);
			scrapCellViews.add(child);
        }
		detachAllViewsFromParent();
	}
	
	public MonthAdapter getAdapter() {
		return adapter;
	}
	
	public void setAdapter(MonthAdapter adapter) {
		this.adapter = adapter;
		requestLayout();
	}
	
	public void setTime(final long time){
		calendar.setTimeInMillis(time);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		
		thisYear = calendar.get(Calendar.YEAR);
		thisMonth = calendar.get(Calendar.MONTH);
		
		final int firstDayOfWeekInMonth = calendar.get(Calendar.DAY_OF_WEEK);
		final int between = firstDayOfWeekInMonth - Calendar.MONDAY;
		calendar.set(Calendar.DAY_OF_MONTH, -between);
		this.time = calendar.getTimeInMillis();
		
		requestLayout();
	}
	
	public void refresh() {
		final int childCount = getChildCount();
		calendar.setTimeInMillis(time);
		
		for (int i = 0; i < childCount; i++) {
			final View child = getChildAt(i);
			adapter.bindCellView(this, child, i, calendar);
			calendar.add(Calendar.DAY_OF_MONTH, 1);
		}
	}

	public long getTime() {
		return time;
	}

	public int getThisYear() {
		return thisYear;
	}

	public int getThisMonth() {
		return thisMonth;
	}
}