/*******************************************************************************
 * This file is part of GECAMed.
 * 
 * GECAMed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License (L-GPL) as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GECAMed is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License (L-GPL)
 * along with GECAMed.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * GECAMed is Copyrighted by the Centre de Recherche Public Henri Tudor (http://www.tudor.lu)
 * (c) CRP Henri Tudor, Luxembourg, 2008
 *******************************************************************************/
/*
 * UCMCodeField.java
 *
 * Created on May 26, 2005, 10:41 AM
 */

package lu.tudor.santec.gecamed.core.gui.widgets;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.text.ParseException;

import javax.swing.JFormattedTextField;
import javax.swing.text.DefaultFormatterFactory;

import lu.tudor.santec.gecamed.core.gui.GECAMedColors;
import lu.tudor.santec.gecamed.core.utils.SSNChecker;
import lu.tudor.santec.gecamed.core.utils.SSNFormatter;
import lu.tudor.santec.gecamed.patient.gui.PatientManagerModule;
import lu.tudor.santec.gecamed.patient.utils.SettingConstants;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

/**
 * The UCMCodeField swing component eases the input of UCM (Union des Caisses de Maladie) 
 * codes. UCM codes come in the format XXXXXX-YY. The 6 Xs represent the actual UCM code
 * whereas the 2 Ys are merely a checksum calculated from the 6 digits. Checksum
 * calculation is a simple module 97 operation. The UCMCodeField coerces the code
 * format and features an autocomplete function, triggered when hitting the '-' key.
 * @author nmac
 */

//***************************************************************************
//* Class Definition and Members                                            *
//***************************************************************************

public class SSNField extends JFormattedTextField implements ActionListener, FocusListener
    {
	/* ======================================== */
	// 		CONSTANTS
	/* ======================================== */
	
	private static final long serialVersionUID = 1L;
    
    public static final int		DIGIT_LIMIT				= 128;
	
	
	
	/* ======================================== */
	// 		MEMBERS
	/* ======================================== */
	
	/** the logger Object for this class */
	private static Logger	logger = Logger.getLogger(SSNField.class.getName());
	
	private static Integer	m_EditMode;
	
	
	private Color			m_Foreground;
	
	private Color			m_Background;
	
	private SSNDocument		m_SSNDocument;
	
	private SSNFormatter	m_Formatter;
	
    
    
//***************************************************************************
//* Constructor(s)                                                          *
//***************************************************************************

public SSNField () 
    {
    this.addActionListener (this);
    m_Foreground	= this.getForeground ();
    m_Background	= this.getBackground ();
    
    // set the edit mode
    if (m_EditMode == null)
    	m_EditMode	= (Integer) PatientManagerModule.getInstance().administrativeElementsPlugin
    			.getValue(SettingConstants.SSN_EDIT_MODE);
    
    if (m_EditMode == null)
    	m_EditMode	= SettingConstants.SSN_DEFAULT_FORMAT_MODE;
    
    switch (m_EditMode.intValue())
		{
		case SettingConstants.SSN_FIX_FORMAT_MODE:
			m_Formatter		= new SSNFormatter();
			this.setFormatterFactory(new DefaultFormatterFactory(m_Formatter));
			this.setFormatter(m_Formatter);
			this.setFocusLostBehavior(JFormattedTextField.COMMIT);
//			this.addPropertyChangeListener(m_Formatter);
			break;
			
		case SettingConstants.SSN_FREE_FORMAT_MODE:
			m_SSNDocument		= new SSNDocument(getCaret());
			this.setDocument(m_SSNDocument);
			this.addFocusListener(this);
			break;
			
		case SettingConstants.SSN_NO_FORMAT_MODE:
			setDocument(new LimittedDocument(DIGIT_LIMIT));
			break;
//		default:
//			this.setFormatter(new DefaultFormatter());
		}
    }
    
//***************************************************************************
//* Class Primitives                                                        *
//***************************************************************************

//---------------------------------------------------------------------------

	private void reflectValidity ()
	{
		int		ssnDigits;
		String	ssn;
		
		if (m_EditMode == SettingConstants.SSN_NO_FORMAT_MODE)
			return;
		
		ssn	= getText();
		if (ssn != null)
			ssn = SSNChecker.PATTERN_SEARCH_WHITESPACES.matcher(ssn).replaceAll("");
		
		if (ssn == null || SSNChecker.PATTERN_EMPTY_SSN.matcher(ssn).matches())
		{
			this.setForeground(m_Foreground);
			this.setBackground(m_Background);
		}
		else if (SSNChecker.isValidSSN(ssn))
		{
			ssnDigits = ssn.length();
			
			if (ssnDigits == 11)
			{
				this.setForeground(Color.BLACK);
				this.setBackground(GECAMedColors.c_WarnFieldBackground);
			}
			else if (ssnDigits == 13)
			{
				this.setForeground(Color.BLACK);
				this.setBackground(GECAMedColors.c_ValidFieldBackground);
			}
		}
		else if (ssn.length() == 8 && SSNChecker.getValidDate(ssn, true) != null)
		{
			this.setForeground(Color.BLACK);
			this.setBackground(GECAMedColors.c_WarnFieldBackground);
		}
		else
		{
			this.setForeground(Color.BLACK);
			this.setBackground(GECAMedColors.c_InvalidFieldBackground);
		}
	}

//---------------------------------------------------------------------------

//***************************************************************************
//* Class Body                                                              *
//***************************************************************************

//---------------------------------------------------------------------------

public void commitEdit () throws ParseException
	{
	if (m_EditMode == SettingConstants.SSN_FIX_FORMAT_MODE)
		super.commitEdit();
	
	this.reflectValidity();
	}

//---------------------------------------------------------------------------

	public void setValue (Object p_Value)
	{
		if (m_EditMode == SettingConstants.SSN_FIX_FORMAT_MODE)
		{
			super.setValue(p_Value);
			p_Value = getValue();
		}
		else if (m_EditMode == SettingConstants.SSN_FREE_FORMAT_MODE)
			m_SSNDocument.setValue(p_Value);
		else
			setText(p_Value != null ? p_Value.toString() : "");
		
		this.reflectValidity();
	}

//---------------------------------------------------------------------------

public Object getValue()
	{
	if (m_EditMode == SettingConstants.SSN_FIX_FORMAT_MODE)
		return super.getValue();
	else if (m_EditMode == SettingConstants.SSN_FREE_FORMAT_MODE)
		return m_SSNDocument.getValue();
	else 
		return getText();
	}

//---------------------------------------------------------------------------
/**
 * the actionPerformed method, part of the ActionListener interface, intercepts the
 * ENTER key. In the context of the UCMCodeField, the method is either used to complete 
 * the checksum part of the UCM code field if not already specified or to verify the 
 * specified checksum.
 */
//---------------------------------------------------------------------------

public void actionPerformed(ActionEvent p_Event) 
	{
	this.reflectValidity();
    }

//---------------------------------------------------------------------------

	public void processFocusEvent (FocusEvent p_Event)
	{
		if (p_Event.getID() == FocusEvent.FOCUS_GAINED)
		{
			this.setForeground(m_Foreground);
			this.setBackground(m_Background);
		}
		else if (p_Event.getID() == FocusEvent.FOCUS_LOST)
		{
			reflectValidity();
		}
		
		super.processFocusEvent(p_Event);
	}

//---------------------------------------------------------------------------

public void focusGained(FocusEvent p_Event) {}

//---------------------------------------------------------------------------

public void focusLost(FocusEvent p_Event)
	{
	try
		{
		commitEdit();
		}
	catch (ParseException p_Exception)
		{
		logger.log(Level.ERROR, p_Exception.getMessage(), p_Exception);
		}
	}

//---------------------------------------------------------------------------

//***************************************************************************
//* End of Class                                                            *
//***************************************************************************



//public static void main (String[] args)
//{
//	final JTextField tf = new JTextField("1234567890");
//	tf.addKeyListener(new KeyListener()
//	{
//		
//		public void keyTyped (KeyEvent e)
//		{
//			Color c = tf.getBackground();
//			int a = c.getAlpha();
//			if (a == 255)
//				a = 50;
//			else 
//				a = 255;
//			c = new Color(c.getRed(), c.getGreen(), c.getBlue(), a);
//			tf.setBackground(c);
//		}
//		
//		
//		public void keyReleased (KeyEvent e) {}
//		
//		
//		public void keyPressed (KeyEvent e) {}
//	});
//	JFrame f = new JFrame("ALPHA TEST");
//	f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//	f.setLayout(new FormLayout("2dlu,p,5dlu,p,5dlu,p,2dlu", "f:p,0px:g"));
//	CellConstraints cc = new CellConstraints();
//	f.add(new JLabel("ALPHA"),	cc.xy(2, 1));
//	f.add(tf,					cc.xy(4, 1));
//	f.add(new JLabel("TEST"),	cc.xy(6, 1));
//	
//	f.pack();
//	f.setLocationRelativeTo(null);
//	f.setVisible(true);
//}

}
