package com.dclear.smartgwt.testbed.client;

import java.text.SimpleDateFormat;
import java.util.Date;

import com.google.gwt.user.client.Timer;
import com.smartgwt.client.core.Rectangle;
import com.smartgwt.client.types.Positioning;
import com.smartgwt.client.util.DateUtil;
import com.smartgwt.client.widgets.DateChooser;
import com.smartgwt.client.widgets.events.DataChangedEvent;
import com.smartgwt.client.widgets.events.DataChangedHandler;
import com.smartgwt.client.widgets.events.FocusChangedEvent;
import com.smartgwt.client.widgets.events.FocusChangedHandler;
import com.smartgwt.client.widgets.events.KeyPressEvent;
import com.smartgwt.client.widgets.events.KeyPressHandler;
import com.smartgwt.client.widgets.events.MouseOutEvent;
import com.smartgwt.client.widgets.events.MouseOutHandler;
import com.smartgwt.client.widgets.events.MouseOverEvent;
import com.smartgwt.client.widgets.events.MouseOverHandler;
import com.smartgwt.client.widgets.form.fields.FormItemIcon;
import com.smartgwt.client.widgets.form.fields.TextItem;
import com.smartgwt.client.widgets.form.fields.events.FormItemClickHandler;
import com.smartgwt.client.widgets.form.fields.events.FormItemIconClickEvent;
import com.smartgwt.client.widgets.form.validator.RegExpValidator;

/**
 * This is a customized text field which will accept Date and Validate for format 'MM/dd/YYYY'
 * We have used Date Chooser image as a dummy Date Chooser for this customized text field.  
 * 
 */
public class DateTextItem extends TextItem {
	
	public static final String UI_DATE_FORMAT = "MM/dd/yyyy";
	public static final String UI_DATE_FORMAT_REGEX = "([0][1-9]|[1][0-2])\\/([0][1-9]|[1-2][0-9]|[3][0-1])\\/[0-9]{4}";
	public static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat(UI_DATE_FORMAT);

	public static final String DATE_ICON = "DATE_ICON";
	private static final String IMAGE_BASE = "../SmartGwtTestbed/sc/skins/Enterprise/images/DynamicForm/date_control.png";
	private FormItemIcon datePickerIcon;
	
	public DateTextItem(String fieldName, String displayName) {
		super(fieldName, displayName);
		validateDate();
	}

	private void validateDate() {
		RegExpValidator regExpValidator = new RegExpValidator(UI_DATE_FORMAT_REGEX);
		regExpValidator.setErrorMessage("Invalid Date Format (MM/dd/YYYY)");
		setValidators(regExpValidator);
		setValidateOnExit(true);
		
		datePickerIcon = new FormItemIcon();
        datePickerIcon.setSrc(IMAGE_BASE);
        datePickerIcon.setPrompt("Show Date Chooser");
        datePickerIcon.setWidth(16);
        datePickerIcon.setHeight(14);
        datePickerIcon.setName(DATE_ICON);
        datePickerIcon.addFormItemClickHandler(new FormItemClickHandler() {
			
			@Override
			public void onFormItemClick(FormItemIconClickEvent event) {
				DateTextItem.this.showPicker();
			}
		});
	}
	
	@Override
	public FormItemIcon getIcon(String name) {
		return datePickerIcon;
	}
	
	@SuppressWarnings("deprecation")
	@Override
	public void showPicker() {
		super.showPicker();
		  
        final DateChooser dateChooser = new DateChooser();
        dateChooser.setWidth(100);
        dateChooser.setShowCancelButton(true);
        Date valueDate = (Date)DateTextItem.this.getValue();
        if(valueDate == null) {
        	valueDate = new Date();
        }
        int year = valueDate.getYear() + 1900;
		int month = valueDate.getMonth();
		int date = valueDate.getDate();
		dateChooser.setData(DateUtil.createLogicalDate(year, month, date));
        dateChooser.addDataChangedHandler(new DataChangedHandler() {  
            @Override  
            public void onDataChanged(DataChangedEvent event) {
                DateTextItem.this.setValue(dateChooser.getData());
                dateChooser.destroy();
            }  
        });  
		
		Rectangle iconRect = getIconPageRect(datePickerIcon);
		
		int offsetLeft = iconRect.getLeft();
		dateChooser.setLeft(offsetLeft);
		
		int offsetTop = iconRect.getTop();
		int offsetHeight = iconRect.getHeight();
		dateChooser.setTop(offsetTop + offsetHeight);
		dateChooser.setPosition(Positioning.RELATIVE);
		dateChooser.draw();
		
        dateChooser.focus();
		
		final boolean[] mouseOver = new boolean[] {false };
		// identify if mouse has moved over
        dateChooser.addMouseOverHandler(new MouseOverHandler() {

			@Override
			public void onMouseOver(MouseOverEvent event) {
				mouseOver[0] = true;
			}
		});
        // identify if mouse has moved out and if so then set focus()
        dateChooser.addMouseOutHandler(new MouseOutHandler() {
			
			@Override
			public void onMouseOut(MouseOutEvent event) {
				mouseOver[0] = false;
				dateChooser.focus();
			}
		});
        // hide date chooser when user click outside of focus on the element out side of it
        // FIXME: [JP] At the moment this is not working as expected for year selector in the date chooser component
        dateChooser.addFocusChangedHandler(new FocusChangedHandler() {
			
			@Override
			public void onFocusChanged(FocusChangedEvent event) {
				if(!event.getHasFocus() && !mouseOver[0]) {
					new Timer() {
						
						@Override
						public void run() {
							if(dateChooser.isVisible()) {
								dateChooser.destroy();
							}
						}
					}.schedule(50);
				}
			}
		});
        // hide date chooser on press of escape key
        dateChooser.addKeyPressHandler(new KeyPressHandler() {
			
			@Override
			public void onKeyPress(KeyPressEvent event) {
				if(event.getKeyName().equalsIgnoreCase("Escape")) {
					dateChooser.cancelClick();
				}
			}
		});
	}
	
	@Override
	public void setValue(Date value) {
		if(value != null){
			super.setValue(DATE_FORMATTER.format(value));
		} else {
			super.setValue(value);
		}
	}
	
	@Override
	public Object getValue() {
		Object value = super.getValue();
		if(value instanceof String){
			try {
				Date parseDate = DATE_FORMATTER.parse(value.toString());
				return parseDate;
			} catch (Exception e) {
				return null;
			}
		}
		return value;
	}
    
}


