package usda.weru.mcrew;

import java.awt.*;
import javax.swing.*;
import java.util.Locale;
import java.text.DateFormat;
import java.util.GregorianCalendar;

import java.awt.event.*;
import com.klg.jclass.table.*;
import com.klg.jclass.cell.editors.JCStringCellEditor;
import com.klg.jclass.cell.JCCellEditorSupport;
import com.klg.jclass.cell.JCCellEditorListener;
import com.klg.jclass.cell.JCKeyModifier;
//import com.klg.jclass.cell.
import java.util.Arrays;

/**
 * A basic implementation of the JDialog class.
 */
public class MyDateCellEditor extends JCStringCellEditor //implements JCCellEditor
{
    private static final long serialVersionUID = 1L;

	/**
	 * Default constructor that redirects things up the heirarchy.
	 */
	
	MyDateCellEditor() {
		super();
	}

	/**
	 * One argument constructor that redirects instantiation up the heirarchy.
     * Also holds the pointer to the JCTable in which it resides.
	 */

	MyDateCellEditor(JCTable jct) {
		super();
	}

	/**
	 * Calendar passed to editor. Changes are made to this instance.
	 */
	
	private GregorianCalendar greCal = null;
	private GregorianCalendar orgGreCal = null;
	private boolean editFlg = false;
	
	/**
	 * Initializes editor when cell is editted.
	 */

	private int row = -1;

	private final int dbgIdx = 0;
	Object lastObj = null;
	
    /**
     * This method initialises the table date cell with data for that particular row.
     * @param ev The type of event that occcured in the cell
     * @param info Object that holds the information about that cell i:e date information
     * @param o The object that holds the old i:e information prior to changes in dates
     * on that cell.
     */    
    @Override
	public void initialize(AWTEvent ev, com.klg.jclass.cell.JCCellInfo info, Object o) {

		// this code is a kludge. ev is null when keyboard arrows are
		// used. however, up and down arrow may change the row. so we
		// init if the row has changed.
		
		JCTableCellInfo tci = (JCTableCellInfo) info;
		lastObj = o;
//		try {
////System.out.println("MDCE_i: T " + (dbgIdx++) + " " + getText() + " " + new MemoryDisplay().MemCvt((Object) o));
//		} catch (java.lang.UnsatisfiedLinkError x) {
//			//System.out.println("MDCE_x: " + x);
//		}
//		if (ev == null && row == tci.getRow()) {
//			//System.out.println("MDCE_i: null " + o);
//			return;
//		}
		row = tci.getRow();
//		//System.out.println("MDCE_i: not null " + o + " " + greCal);
//		//System.out.println("MDCE_i: " + getText());
//		if (!editFlg) {
//			//System.out.println("MDCE_i: init " + o);
			greCal = (GregorianCalendar) o;
			orgGreCal = new JulianCalendar(greCal);
			editFlg = true;
		
//		//System.out.println("MDCE_i: " + greCal.equals(orgGreCal));
//		GregorianCalendar greCal = (GregorianCalendar) o;
		String temp = greCal.get(GregorianCalendar.DAY_OF_MONTH) + "/" +
					  (greCal.get(GregorianCalendar.MONTH)+1) + "/" +
					  greCal.get(GregorianCalendar.YEAR);
		setText(temp);
//		selectAll();
//		super.initialize(ev, info, temp);
//		}

//		this.addMouseListener(new SymMouse());
//		NewCalendar nc = new NewCalendar((java.util.GregorianCalendar) o, this);
//		nc.setModal(false);
//		nc.setVisible(true);
	}

    /**
     * This method return the pointer to itself.
     * @return Pointer to itself. i:e the MyDateCellEditor
     */    
    @Override
	public Component getComponent() {
		return this;
	}

    /**
     * Fetches the value associated with the editable cell which is the date cell.
     * @return The actual value sitting in that cell in the form of an object.
     */    
    @Override
	public Object getCellEditorValue() {
////System.out.println("MDCE_gCEV: " + greCal + " " + getText());
		editFlg = false;
		return new JulianCalendar(greCal);
	}

    /**
     * This method stops the editing of the date cell by setting the date after formatting it.
     * @return True if date is parsed correctly after being formatted else false.
     */    
    @Override
	public boolean stopCellEditing() {
////System.out.println("MDCE_sCE: " + getText());
		modFlg = false;
//		editFlg = false;
		DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.UK); //dd/mm/ yy format
		try {
			java.util.Date myDate = df.parse(getText());
				//			//System.out.println("MDCE_kT: " + getText() + " " + myDate);
//				((java.util.GregorianCalendar) oo).setTime(myDate);
			greCal.setTime(myDate);
		//	jcces.fireStopEditing(new com.klg.jclass.cell.JCCellEditorEvent(this));
		} catch (java.text.ParseException e) {	

//			//System.out.println("MDCE_kT: " + e);
			df = DateFormat.getDateInstance(DateFormat.MEDIUM);
			try {
				java.util.Date myDate = df.parse(getText());
					// //System.out.println("MDCE_kT: " + getText() + " " + myDate);
//					((java.util.GregorianCalendar) oo).setTime(myDate);
				greCal.setTime(myDate);
		//		jcces.fireStopEditing(new com.klg.jclass.cell.JCCellEditorEvent(this));
			} catch (java.text.ParseException f) {
				//	//System.out.println("MDCE_kT: " + f);
				JOptionPane.showMessageDialog(this,
											  "Invalid date: must be either\n"
											  + "  dd/mm/y , e.g. 8/6/1 or\n"
											  + "  dd mmm, y, eg 8 Jun, 1",
											  "Error converting date",
											  JOptionPane.ERROR_MESSAGE);
				usda.weru.util.Util.setFocus(this);
				return false;
			}
		}
//		//System.out.println("MDCE_sCE: * " + getText());
		return true;
	}

	private boolean modFlg = false;
	
    /**
     * Flag that informs the application that the date got modified
     * @return True if modified else false
     */    
    @Override
	public boolean isModified() {
//System.out.println("MDCE_iM: " + modFlg);		
//		return greCal.equals(orgGreCal);
		return modFlg;
	}

    /**
     * Assigns old calendar object back cancelling any modification that were just made.
     * i:e replaceing the new values by old values.
     */    
    @Override
	public void cancelCellEditing() {
//System.out.println("MDCE_cCE: " + getText());
		greCal = orgGreCal;
//		editFlg = false;
//		repaint();
	}

	private final JCKeyModifier[] reservedKeys = {
		new JCKeyModifier(KeyEvent.VK_ESCAPE),
		new JCKeyModifier(KeyEvent.VK_ENTER),
		new JCKeyModifier(KeyEvent.VK_LEFT),
		new JCKeyModifier(KeyEvent.VK_KP_LEFT),
		new JCKeyModifier(KeyEvent.VK_RIGHT),
		new JCKeyModifier(KeyEvent.VK_KP_RIGHT)
	};
							
	
    /**
     * This object fetches the reserved keys that are not supposed to be used in 
     * our application to link data in the datastructures used here 
     * i:e Retrieves the keys the editor would like to reserve for itself
     * @return An array that holds the reserved keys which cannot be used as 
     * keys to identify objects used to store information in MCREW application calendar.
     */    
    @Override
	public com.klg.jclass.cell.JCKeyModifier[] getReservedKeys() {
		return Arrays.copyOf(reservedKeys, reservedKeys.length);
	}

    /**
     * This method checks what type of key from the keyboard was type and to make
     * sure the data was modified or not. If modified it turns the flag for data 
     * modified to true.
     * @param ev Event about which key was hit on the keyboard.
     */    
    @Override
	public void keyTyped(KeyEvent ev) {

		if(ev.getKeyChar() == KeyEvent.VK_ESCAPE) {	
			jcces.fireCancelEditing(new com.klg.jclass.cell.JCCellEditorEvent(this));
		} else if (ev.getKeyChar() == '\n') {	
			jcces.fireStopEditing(new com.klg.jclass.cell.JCCellEditorEvent(this));
		} else {
			//System.out.print("MDCE_kT: " + ev.getKeyChar());
			super.keyTyped(ev);
			modFlg = true;
			//System.out.println(" " + getText());
		}
		
	}

	
	/* methods implementing the JCCellEditor interface */

	JCCellEditorSupport jcces = new JCCellEditorSupport();

    /**
     * Adds a listener to the list that is notified when the editor starts, stops, or cancels editing.
     * @param l - the JCCellEditorListener
     */    
    @Override
	public void addCellEditorListener(JCCellEditorListener l) {
		jcces.addCellEditorListener(l);
	}

    /**
     * Removes a listener from the list that is notified when the editor starts, stops, or cancels editing.
     * @param l - the JCCellEditorListener
     */    
    @Override
	public void removeCellEditorListener(JCCellEditorListener l) {
		jcces.removeCellEditorListener(l);
	}


}