
package pl.magot.vetch.ancal.views;


import android.content.*;
import android.graphics.*;
import android.view.MotionEvent;
import android.view.View;
import android.widget.*;
import pl.magot.vetch.ancal.*;

public class ViewDayHourItem extends LinearLayout
{
	//inner invisible view for touch mode
	public class InvisibleView extends View
	{
		//fields
		private final int iFrame = 2;
		
		//methods
		public InvisibleView(Context context)
		{
			super(context);
	    setFocusable(false);
	    LinearLayout.LayoutParams layParams = 
	    	new LinearLayout.LayoutParams(android.view.ViewGroup.LayoutParams.FILL_PARENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
	    this.setLayoutParams(layParams);
		}
		@Override
		protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
		{
	    setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));				 
		}		
	  private int measureWidth(int measureSpec)
	  {
	    return MeasureSpec.getSize(measureSpec);
	  }		 
	  private int measureHeight(int measureSpec)
	  {
		  return iFrame + iItemTextHeight + iFrame + iFrame;	  	
	  }		
	}

	//types
	public interface OnItemClick
	{
		public void OnClick(ViewDayHourItem item);
	}
	
	//fields
	private static final String sStrHour = "00";
	private static final String sStrTime = "00:00";
	private static final String sStrUSTimeMark = "mm"; //am/pm
	private static final String sStrUSTimeAM = "am";
	private static final String sStrUSTimePM = "pm";
	
	//fields
	private static final int iSpace = 4;
	private static final int iFrame = 2;
  private static final Typeface tfMono = Typeface.create(Typeface.MONOSPACE, Typeface.NORMAL);
	private static final float fTextSize = 20;

	//fields
	private boolean b24HourMode = false;
	private int iHour = 0;
	private int iCurrentHour = -1;
	protected OnItemClick itemClick = null;
	
	//default hour width, full time width, am/pm width
	private int iSpaceWidthUSTimeMark = 0;
	private int iSpaceWidthHourWithUSTimeMark = 0;	
	private int iSpaceWidthTimeWithUSTimeMark = 0;
	private int iSpaceWidthHourArea = 0;
	private int iSpaceWidthTimeArea = 0;
	private int iItemTextHeight = 0;
	
	//colors
	private final static int iColorTime = 0xFFFF8800;
	private final static int iColorMark = 0xFFAA5500;
	private final static int iColorTimeFocused = 0xFFFFCC66;
	private final static int iColorTimeTouch = 0xFF222222;
	private final int iTouchSliderColor = 0xBBFF8800;
	private final int iTouchPatternColor = 0xFF995500;
	
	//fields
	protected Paint mpt = null;

	//touch mode fields
	private static InvisibleView invView = null;
	private boolean bTouchedDown = false;
	private RectF rtTouchRect = new RectF();
	private RectF rtTimeTouchRect = new RectF();
	private RectF rtTouchSliderRect = new RectF();
	private RectF rectSliderArrow = new RectF();
	private int iTouchPosX = 0;
	private int iLastTimeMinutes = 0;

	//methods
	public ViewDayHourItem(Context context, int iHour, int iItemTextHeight)
	{
		super(context);

		this.iHour = iHour;
		this.iItemTextHeight = iItemTextHeight;
		
		mpt = new Paint();
		mpt.setAntiAlias(true);
		mpt.setTextSize(fTextSize);
		
		setWillNotDraw(false);
		
		setOrientation(LinearLayout.VERTICAL);
		LayoutParams lparams = new LinearLayout.LayoutParams(android.view.ViewGroup.LayoutParams.FILL_PARENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
		setLayoutParams(lparams);

		//invisible view
		if (invView == null)
		{
			invView = new InvisibleView(context);
			invView.setVisibility(View.INVISIBLE);
		}
	}
  	
	public void SetItemClick(OnItemClick itemClick)	
	{
		this.itemClick = itemClick;	
	}

	public void SetItemData(boolean b24HourMode, int iSpaceWidthHour, int iSpaceWidthTime, int iSpaceWidthUSTimeMark)
	{
		this.b24HourMode = b24HourMode;
  	UpdateTimeFormat(b24HourMode, iSpaceWidthHour, iSpaceWidthTime, iSpaceWidthUSTimeMark);
		UpdateHeight();
	}
	
	public void SetCurrentHour(int iCurrentHour)
	{
		this.iCurrentHour = iCurrentHour; 		
	}
	
	public void UpdateTimeFormat(boolean b24HourMode, int iSpaceWidthHour, int iSpaceWidthTime, int iSpaceWidthUSTimeMark)
	{
		this.iSpaceWidthUSTimeMark = (b24HourMode?0:iSpaceWidthUSTimeMark);
		this.iSpaceWidthHourWithUSTimeMark = iSpaceWidthHour + (b24HourMode?0:(iSpaceWidthUSTimeMark + iFrame));
		this.iSpaceWidthTimeWithUSTimeMark = iSpaceWidthTime + (b24HourMode?0:(iSpaceWidthUSTimeMark + iFrame));
		this.iSpaceWidthHourArea = iSpace + iSpaceWidthHourWithUSTimeMark + iSpace;
		this.iSpaceWidthTimeArea = iSpace + iSpaceWidthTimeWithUSTimeMark + iSpace;
  	setPadding(iSpaceWidthHourArea, iFrame + iFrame, iFrame, iFrame + iFrame);
	}
	
	
	public int GetHour()
	{
		return iHour;
	}
	
	public int GetMinutes()
	{
		return iLastTimeMinutes;
	}

	public static int GetTextHeight(Paint mpt)
	{
    mpt.setTypeface(null);
		mpt.setTextSize(fTextSize);		
    mpt.setFakeBoldText(true);
		return (int)(-mpt.ascent() + mpt.descent());
	}
	
	public static int GetSpaceWidthHour(Paint mpt)
	{
    mpt.setTypeface(tfMono);
		mpt.setTextSize(fTextSize);		
    mpt.setFakeBoldText(true);
		return (int)mpt.measureText(sStrHour);
	}
	
	public static int GetSpaceWidthTime(Paint mpt)
	{
    mpt.setTypeface(tfMono);
		mpt.setTextSize(fTextSize);		
    mpt.setFakeBoldText(true);
		return (int)mpt.measureText(sStrTime);		
	}

	public static int GetSpaceWidthUSTimeMark(Paint mpt)
	{
    mpt.setTypeface(tfMono);
		mpt.setTextSize(fTextSize);		
    mpt.setFakeBoldText(false);
		return (int)mpt.measureText(sStrUSTimeMark);		
	}	
		
  private int GetMinHeight()
  {
	  return getPaddingTop() + iFrame + iItemTextHeight + iFrame + getPaddingBottom() - 1;
  }

  public void UpdateHeight()
  {
  	this.getLayoutParams().height = android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
  	if (getChildCount() == 0)
  	{
  		if ((iHour >= 6) && (iHour <= 22))
  		{
  	  	this.getLayoutParams().height = GetMinHeight(); 
  		} else {
  	  	this.getLayoutParams().height = 0; 
  		}
  	}
  }
   
  public boolean IsMinimized()
  {
  	return getHeight() == 0;
  }
  
	@Override
	protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect)
	{
		super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
		invalidate();
	}
	
	@Override
	protected void onDraw(Canvas canvas)
	{
		super.onDraw(canvas);
				
		mpt.setAntiAlias(true);
		mpt.setTextSize(fTextSize);		
    mpt.setTypeface(tfMono);
    mpt.setFakeBoldText(true);
		mpt.setShader(null);
		mpt.setUnderlineText(false);
        
		final boolean bIsFocused = hasFocus();
  	final int iHeight = getHeight() - iFrame;
  	final int iWidth = getWidth();  	
		final int iTimePosY = (- (int)mpt.ascent()) + iFrame + iFrame + 1;

    if (!IsMinimized())
    {
    	GetTouchRectangle();
    	
  		DrawBackground(canvas, iWidth, iHeight, bIsFocused);
    	
  		DrawTime(canvas, iTimePosY, iWidth, iHeight, bIsFocused);
  		
  		if (bTouchedDown)
  		{
  			GetTouchSliderRectangle();
  			DrawTouchSlider(canvas);
  			DrawTouchBar(canvas);
  		}
    }
 	}

	private void DrawBackground(Canvas canvas, int iWidth, int iHeight, boolean bIsFocused)
	{    	
    mpt.setTypeface(null); 		
		mpt.setShader(null);		

		//draw touch slider background
		if (bTouchedDown)
    {
			mpt.setColor(iColorTime);
			canvas.drawRoundRect(rtTouchRect, 3, 3, mpt);
    }

		//draw gradient line 
		LinearGradient lGrad = new LinearGradient((getWidth() >> 2), 0, getWidth(), 0,
				0xFFFFFFFF, 0x00FFFFFF, Shader.TileMode.CLAMP);		
		mpt.setShader(lGrad);		
		canvas.drawLine(0, 0, getWidth(), 0, mpt);
		
		mpt.setShader(null);
	}
	
	private String GetHourString()
	{				
		if (b24HourMode)
		{
			return Integer.toString(iHour);
		} else {
			int iDisplayHour = iHour;			
			if (iDisplayHour == 0)
				iDisplayHour = 12;			
			if (iDisplayHour > 12)
				iDisplayHour -= 12;
			return Integer.toString(iDisplayHour);
		}
	}
	
	private String GetMinutesString()
	{		
		if (iLastTimeMinutes > 9)
			return ":" + Integer.toString(iLastTimeMinutes);
		return ":0" + Integer.toString(iLastTimeMinutes);
	}

	private String GetUSTimeMark()
	{
		if (iHour >= 12)
			return sStrUSTimePM;
		return sStrUSTimeAM;
	}

	private void DrawTime(Canvas canvas, int iTimePosY, int iWidth, int iHeight, boolean bIsFocused)
	{
		mpt.setAntiAlias(true);
		mpt.setTextSize(fTextSize);		
    mpt.setTypeface(tfMono);
    mpt.setFakeBoldText(true);
		mpt.setShader(null);
		
		mpt.setUnderlineText(false);
		if (iCurrentHour == iHour)
			mpt.setUnderlineText(true);
		
		//draw hour
		final String sHour = GetHourString();
		final int iStrHourWidth = (int)mpt.measureText(sHour);		
		final int iTimePosX = iSpaceWidthHourArea - iStrHourWidth - iFrame - iSpaceWidthUSTimeMark - iSpace;
		mpt.setColor((bTouchedDown)?iColorTimeTouch:iColorTime);
		if (bIsFocused)
			mpt.setColor(iColorTimeFocused);					
		canvas.drawText(sHour, iTimePosX, iTimePosY, mpt);
				
		//draw minutes
		int iMarkPosX = iTimePosX + iStrHourWidth + iFrame;
		if (bTouchedDown)
		{
			final String sMinutes = GetMinutesString();
			final int iStrMinutesWidth = (int)mpt.measureText(sMinutes);		
			final int iMinutesPosX = iTimePosX + iStrHourWidth;
			iMarkPosX = iMinutesPosX + iStrMinutesWidth + iFrame;
			canvas.drawText(sMinutes, iMinutesPosX, iTimePosY, mpt);
		}
		
		//draw us time mark
		if (!b24HourMode)
		{						
	    mpt.setFakeBoldText(false);
			mpt.setColor(iColorMark);
			if (bIsFocused)
				mpt.setColor(iColorTimeFocused);					
			canvas.drawText(GetUSTimeMark(), iMarkPosX, iTimePosY, mpt);
		}
		
		mpt.setUnderlineText(false);
	}
	
	private void DrawTouchSlider(Canvas canvas)
	{
		//draw inner background
		mpt.setShader(null);
		mpt.setColor(iColorTimeTouch);
		canvas.drawRoundRect(rtTouchSliderRect, 3, 3, mpt);
		
		//draw slider pattern
		mpt.setColor(iTouchPatternColor);
		mpt.setStrokeWidth(4);
		mpt.setStrokeCap(Paint.Cap.ROUND);
		
		rectSliderArrow.set(rtTouchSliderRect);		
		final int iArrowWidth = 6;
		final int iArrowSpace = 8;
		final int iArrowCount = (int)(rtTouchSliderRect.width() / (iArrowWidth + iArrowSpace));

		final int iMargin = (int)rtTouchSliderRect.width() - (iArrowCount * (iArrowWidth + iArrowSpace));
		rectSliderArrow.left += iMargin;
		
		for (int i = 0; i < iArrowCount; i++)
		{		
			DrawTouchSliderArrow(canvas, rectSliderArrow, iArrowWidth);			
			rectSliderArrow.left += iArrowWidth + iArrowSpace;
		}
						
		mpt.setStrokeWidth(0);
	}
	
	private void DrawTouchSliderArrow(Canvas canvas, RectF rect, int iArrowWidth)
	{
		int istartX = (int)(rect.left);
		int istopX = (int)(rect.left + iArrowWidth);		
		int iCenter = (int)(rect.top + (rect.height() / 2));		
		canvas.drawLine(istartX, rect.top + 5, istopX, iCenter, mpt);
		canvas.drawLine(istartX, rect.bottom - 5, istopX, iCenter, mpt);		
	}

	private void DrawTouchBar(Canvas canvas)
	{
		//draw inner background
		mpt.setShader(null);
		mpt.setColor(iTouchSliderColor);

		//control ranges
		float fMaxRight = rtTouchSliderRect.right;	
		rtTouchSliderRect.right = iTouchPosX;
		if (rtTouchSliderRect.right > fMaxRight)
			rtTouchSliderRect.right = fMaxRight;
		if (rtTouchSliderRect.right < rtTouchSliderRect.left)
			rtTouchSliderRect.right = rtTouchSliderRect.left;

		canvas.drawRoundRect(rtTouchSliderRect, 2, 2, mpt);
	}	
		
	public int CalculateTimeMinutes()
	{
		RectF rectSlider = GetTouchSliderRectangle();		
		if (iTouchPosX > 0)
		{
			if ((iTouchPosX > rectSlider.left) && (iTouchPosX < rectSlider.right))
			{
				float fRange = rectSlider.right - rectSlider.left;
				float fPos = iTouchPosX - rectSlider.left;				
				float fStep = (fRange / 60);
				int iMinutes = (int)(fPos / fStep);				
				if (iMinutes < 0)
					iMinutes = 0;
				if (iMinutes > 59)
					iMinutes = 59;
								
				int iModulo = iMinutes % 5;				
				iMinutes = iMinutes - iModulo; 
																
				return iMinutes;
			}
		}	
		return 0;
	}	
	
	public void doItemClick()
	{
		if (itemClick != null)
				itemClick.OnClick(this);	
	}
	
	private RectF GetTouchRectangle()
	{
 		rtTouchRect.set(0, 3, getWidth() - 1, GetMinHeight() - 2);  		
		return rtTouchRect;
	}
	
	private RectF GetTimeTouchRectangle()
	{
		rtTimeTouchRect.set(iFrame, 2, iSpaceWidthTimeArea - iFrame, GetMinHeight() - 2);
		return rtTimeTouchRect;
	}
	
	private RectF GetTouchSliderRectangle()
	{
		rtTouchSliderRect.set(GetTouchRectangle());		
		rtTouchSliderRect.inset(2, 2);
		rtTouchSliderRect.left = iSpaceWidthTimeArea + iSpace + iSpace;
		rtTouchSliderRect.right = rtTouchSliderRect.right - iSpace - iSpace - iSpace;
		return rtTouchSliderRect;
	}	
	
	private boolean TouchInTimeArea(MotionEvent event)
	{
		RectF rect = GetTimeTouchRectangle();
		if (rect.contains(event.getX(), event.getY()))
			return true;		
		return false;
	}
	
  @Override
	public boolean onTouchEvent(MotionEvent event)
  {
  	boolean bHandled = false;
  	if (event.getAction() == MotionEvent.ACTION_DOWN)
  	{  		
  		if (TouchInTimeArea(event))
  		{  				  		
    		bHandled = true;
  			bTouchedDown = true;
  			iLastTimeMinutes = 0;
  			iTouchPosX = 0;
  			EnableInnerViewSpace(true);
  			invalidate();
  			Utils.startAlphaAnimIn(ViewDayHourItem.this);
  		}
  	}
  	if (event.getAction() == MotionEvent.ACTION_CANCEL)
  	{
  		bHandled = true;
  		bTouchedDown = false;
			iTouchPosX = 0;
			EnableInnerViewSpace(false);
  		invalidate();
  	}
  	if (event.getAction() == MotionEvent.ACTION_UP)
  	{
 			bHandled = true;
 			bTouchedDown = false;
			EnableInnerViewSpace(false);
 			invalidate(); 			 			
  		doItemClick();
  	}
  	if (event.getAction() == MotionEvent.ACTION_MOVE)
  	{
  		bHandled = true;
			iTouchPosX = (int)event.getX();
 			iLastTimeMinutes = CalculateTimeMinutes(); 			
  		invalidate();
  	}
  	return bHandled;  	  	  	
  }
  
  private void EnableInnerViewSpace(boolean bEnable)
  {
		if (bEnable)
  	{
  		this.addView(invView, 0);  		
  	} else {
  		this.removeView(invView);
  	}
  }
    
}
