package lu.tudor.santec.gecamed.formeditor.gui.component;

import java.math.BigDecimal;

import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

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

public class NumberDocument extends PlainDocument 
{
	/* ======================================== */
	// 		CONSTANTS
	/* ======================================== */
	
	private static final long serialVersionUID = 1L;
	
	
	
	/* ======================================== */
	// 		MEMBERS
	/* ======================================== */
	
	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(NumberDocument.class.getName());
	
	
	private boolean decimal = true;
	
	
	
	/* ======================================== */
	// 		CONSTRUCTORS
	/* ======================================== */
	
	public NumberDocument(boolean decimalAllowed)
	{
		this.decimal	= decimalAllowed;
	}
	
	
	public NumberDocument()
	{
		this.decimal	= true;
	}
	
	
	
	/* ======================================== */
	// 		CLASS BODY
	/* ======================================== */
	
	@Override
	public void insertString (int offs, String str, AttributeSet a) throws BadLocationException
	{
		this.replace(offs, 0, str, a);
	}
	
	
	@Override
	public void remove(int offs, int len) throws BadLocationException
	{
		this.replace(offs, len, "", null);
	}
	
	
	@Override
	public void replace(int offset, int length, String text, AttributeSet attrs) throws BadLocationException
	{
		String			front;
		String			back;
		
		
		if (EditableComponent.MISSING_VALUE.equals(text) && offset == 0 && length == getLength())
		{
			super.remove(0, getLength());
			super.insertString(0, text, attrs);
			return;
		}
		
		// get the text before and after the insertion
		front	= getText(0, offset);
		back	= getText(offset+length);
		
		// clean the text
		if (isDecimal())
		{
			
			// remove all invalid chars
			text	= text.replaceAll("[^\\d,\\.-]", "");
			
			if (offset == 0)
				// remove all minuses, except the first one 
				text	= text.replaceAll("-(?<=\\A.+-)", "");
			else 
				// remove all minuses
				text	= text.replaceAll("-", "");
			
			
			if (front.contains(".") 
					|| front.contains(",") 
					|| back.contains(".") 
					|| back.contains(","))
				text	= text.replaceAll("[\\.,]", "");
			if (offset == 0 || (offset == 1 && front.startsWith("-")))
				// remove decimal separator at front
				text	= text.replaceAll("[\\.,](?<=\\A-?[\\.,])", "");
		}
		else
		{
			// remove all invalid chars
			text	= text.replaceAll("[^\\d-]", "");
			
			if (offset == 0)
				// remove all minuses, except the first one 
				text	= text.replaceAll("-(?<=\\A.+-)", "");
			else 
				// remove all minuses
				text	= text.replaceAll("-", "");
		}
		
		if (offset == 0 && back.startsWith("-"))
		{
			super.remove(0, 1);
			if (!text.startsWith("-"))
				text	= "-" + text;
		}
		
		super.remove(offset, length);
		super.insertString(offset, text, attrs);
	}
	
	
	
	/* ======================================== */
	// 		GETTER & SETTER
	/* ======================================== */
	
	public void setDecimal (boolean decimal)
	{
		this.decimal = decimal;
		try
		{
			super.remove(0, getLength());
			super.insertString(0, String.valueOf(getLong()), null);
		}
		catch (BadLocationException e)
		{
			logger.log(Level.ERROR, e.getMessage(), e);
		}
	}
	
	
	public boolean isDecimal ()
	{
		return this.decimal;
	}
	
	
	public String getText(int offset) throws BadLocationException
	{
		return super.getText(offset, getLength()-offset);
	}
	
	
	public String getText ()
	{
		try
		{
			return super.getText(0, getLength());
		}
		catch (BadLocationException e)
		{
			logger.log(Level.ERROR, e.getMessage(), e);
			return null;
		}
	}
	
	
	public Long getLong ()
	{
		BigDecimal decimal	= getDecimal();
		
		
		if (decimal != null)
			 return decimal.longValue();
		else return null;
	}
	
	
	public BigDecimal getDecimal ()
	{
		String	text	= toString().replaceAll(",", ".");
		
		
		try
		{
			return new BigDecimal(text);
		}
		catch (NumberFormatException e)
		{
			return null;
		}
	}
	
	
	public Double getDouble ()
	{
		String	text	= toString().replaceAll(",", ".");
		
		
		try
		{
			return Double.parseDouble(text);
		}
		catch (NumberFormatException e)
		{
			return null;
		}
	}
	
	
	@Override
	public String toString()
	{
		String	text	= getText();
		boolean	sign;
		boolean	decimal;
		
		
		if (text == null)
			return "";
		
		// remove the leading zeros
		sign	= text.matches("\\A-.*");
		text	= text.replaceAll(",", ".")
				.replaceAll("\\A-?0+", "");
		
		// add the sign, if it was removed by the replacement action
		if (sign && !text.startsWith("-"))
			text	= "-"+text;
		
		// remove the decimal zeros ...
		decimal	= text.matches(".*[\\.,].*");
		// ... if there is a decimal point
		if (decimal)
		{
			text	= text.replaceAll("0+\\Z", "");
			if (text.endsWith("."))
				text	= text.substring(0, text.length()-1);
		}
		
		return text;
	}
	
	
	
	/* ======================================== */
	// 		MAIN (FOR TESTING)
	/* ======================================== */
	
	public static void main(String[] args)
	{
//		String front;
//		String back;
		String	text	= "-00001203.456780000";
		boolean	sign;
		boolean	decimal;
		
		// remove the leading zeros
		sign	= text.matches("\\A-.*");
		text	= text.replaceAll(",", ".")
				.replaceAll("\\A-?0+", "");
		if (sign && !text.startsWith("-"))
			text	= "-"+text;
		
		// remove the decimal zeros
		decimal	= text.matches(".*[\\.,].*");
		if (decimal)
		{
			text	= text.replaceAll("0+\\Z", "");
			if (text.endsWith("."))
				text	= text.substring(0, text.length()-1);
		}
		
		
		
		System.out.println(text);
		
//		StringBuilder number;
//
//		str	= str.replaceAll("[^\\d,\\.-]", "");
//		System.out.println(str);
//		str	= str.replaceAll("-(?<=\\A.+-)", "");
//		System.out.println(str);
//		str	= str.replaceAll("[\\.,](?<=\\A-?[\\.,])", "");
//		System.out.println(str);
//		front	= str.replaceAll("[\\.,].*", "");
//		System.out.println(front);
//		back	= str.substring(front.length()).replaceAll("[\\.,]", "");
//		System.out.println(back);
//		number	= new StringBuilder(front.length()+back.length()+1)
//				.append(front)
//				.append(str.charAt(front.length()))
//				.append(back);
//		System.out.println(number);
	}
}