package lu.tudor.santec.gecamed.esante.gui.worker;

import java.util.HashMap;
import java.util.Map;

import lu.tudor.santec.gecamed.esante.ejb.entity.beans.CdaDocument;
import lu.tudor.santec.gecamed.esante.gui.tab.CdaHandler;

import org.apache.log4j.Logger;

/**
 * @author jens.ferring(at)tudor.lu
 * 
 * @version
 * <br>$Log: DocumentQueueItem.java,v $
 * <br>Revision 1.8  2013-11-22 14:51:10  ferring
 * <br>Restructured CDA tree and list notification, in order not to use an EntityBean as model.
 * <br>Buttons added to delete the CDA file and remove the incident entry
 * <br>
 * <br>Revision 1.7  2013-11-12 15:37:53  ferring
 * <br>downloads can now be stopped
 * <br>
 * <br>Revision 1.6  2013-11-05 09:47:56  ferring
 * <br>ESantePatient changed to Dsp. The Dsp object will be stored in the database, if a patient is linked with eSanté.
 * <br>
 * <br>Revision 1.5  2013-10-22 06:00:38  ferring
 * <br>stop downloading folder (first steps)
 * <br>
 * <br>Revision 1.4  2013-10-08 08:54:13  ferring
 * <br>class name refactoring and tree view implementation (first steps)
 * <br>
 * <br>Revision 1.3  2013-10-01 13:14:57  ferring
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.2  2013-09-30 11:53:48  ferring
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.1  2013-09-30 10:56:26  ferring
 * <br>eSante integration in GECAMed and synchronise funktion added
 * <br>
 */

class DocumentQueueItem
{
	/* ======================================== */
	// MEMBERS
	/* ======================================== */
	
	private static Map<Integer, Integer>	statusTodoMapping;
	
	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(DocumentQueueItem.class.getName());
	
	
	private CdaHandler		cdaHandler;
	
	private Integer			dspId;
	
	private CdaDocument		document;
	
	private int				todo;
	
	private int				index;
	
	private boolean			singleDocument;
	
	
	
	/* ======================================== */
	// CONSTRUCTORS
	/* ======================================== */
	
	public DocumentQueueItem (CdaHandler handler, int todo)
	{
		this(null, handler, todo);
	}
	
	
	public DocumentQueueItem (CdaDocument document, CdaHandler handler, int todo)
	{
//		if (handler == null)
//			throw new InvalidParameterException("The CdaHandler must not be null!");
		
		this.cdaHandler		= handler;
		this.document		= document;
		this.todo			= todo;
		this.singleDocument	= document != null;
//		this.dspId			= handler.getDspId();
		reset();
	}
	
	
	
	/* ======================================== */
	// GETTER METHODS
	/* ======================================== */
	
	public CdaHandler getHandler ()
	{
		return cdaHandler;
	}
	
	
	public Integer getDspId ()
	{
		return dspId;
	}
	
	
	public int getTodo ()
	{
		return todo;
	}
	
	
	public boolean includesTodo (int bitmask)
	{
		return (todo & bitmask) == bitmask;
	}
	
	
	public void removeTodo (int toRemoveBitMask)
	{
		todo &= toRemoveBitMask ^ (-1);
	}
	
	
	public void addTodo (int toAddBitMask)
	{
		todo |= toAddBitMask;
	}
	
	
	public CdaDocument getDocument ()
	{
		return document;
	}
	
	
	
	/* ======================================== */
	// CLASS BODY
	/* ======================================== */
	
	public void reset ()
	{
		this.index = 0;
	}
	
	
	public boolean hasNext ()
	{
		CdaDocument document = this.document;
		int index = this.index;
		
		if (singleDocument)
		{
			return document.getStatus() < todo;
		}
		else
		{
			do
			{
				if (index >= cdaHandler.getDocumentCount())
					return false;
				
				document = cdaHandler.getDocument(index++);
			}
			while (document.getStatus() >= getStatusForTodo(todo));
			
			return document != null;
		}
	}
	
	
	public boolean next ()
	{
		if (singleDocument)
		{
			return document.getStatus() < todo;
		}
		else
		{
			do
			{
				if (index < cdaHandler.getDocumentCount())
				{
					document = cdaHandler.getDocument(index++);
				}
				else
				{
					document = null;
					break;
				}
			}
			while (document.getStatus() >= getStatusForTodo(todo));
			
			return document != null;
		}
	}
	
	
	public boolean isSingleDocument ()
	{
		return singleDocument;
	}
	
	
	@Override
	public boolean equals (Object obj)
	{
		if (this == obj)
		{
			return true;
		}
		else if (obj == null)
		{
			return false;
		}
		else if (singleDocument)
		{
			if (obj instanceof CdaDocument)
			{
				return this.document.equals(obj);
			}
			else if (obj instanceof DocumentQueueItem)
			{
				DocumentQueueItem item = (DocumentQueueItem) obj;
				if (!item.singleDocument)
					return false;
				else if (item.getDocument() != null
						&& getDocument() != null)
					return getDocument().equals(item.getDocument());
				else if (item.getDocument() == null
						&& getDocument() == null)
					return true;
			}
		}
		else // if (this.cdaHandler != null)
		{
//			if (obj instanceof Dsp)
//				return dsp.equals(obj);
			if (obj instanceof CdaHandler)
				return cdaHandler.equals(obj);
			else if (obj instanceof DocumentQueueItem)
			{
				DocumentQueueItem item = (DocumentQueueItem) obj;
				if (item.singleDocument)
					return false;
				else if (item.getDspId() != null
						&& dspId != null)
					return dspId.equals(item.getDspId());
				else
					cdaHandler.equals(item.getHandler());
//				else if (item.getDsp() == null
//						&& getDsp() == null)
//					return true;
			}
		}
		
		return super.equals(obj);
	}
	
	
	
	/* ======================================== */
	// HELP METHODS
	/* ======================================== */
	
	private static int getStatusForTodo (int todo)
	{
		if (statusTodoMapping == null)
		{
			statusTodoMapping	= new HashMap<Integer, Integer>();
			statusTodoMapping.put(DocumentWorker.DOWNLOAD_DOCUMENT,				CdaDocument.STATUS_UNREAD_AND_DOWNLOADED);
			statusTodoMapping.put(DocumentWorker.OPEN_DOCUMENT,					CdaDocument.MAX_STATUS);
			statusTodoMapping.put(DocumentWorker.INTEGRATE_DOCUMENT,			CdaDocument.STATUS_UNREAD_AND_INTEGRATED);
			statusTodoMapping.put(DocumentWorker.OPEN_AND_INTEGRATE_DOCUMENT,	CdaDocument.MAX_STATUS);
		}
		
		Integer status = statusTodoMapping.get(todo);
		
		if (status == null)
		{
			logger.warn("Todo " + todo + " is not supported!");
			return CdaDocument.MAX_STATUS;
		}
		else
		{
			return status.intValue();
		}
	}
	
	
//	public static void main (String[] args)
//	{
//		
//		DocumentQueueItem i = new DocumentQueueItem(null, DocumentWorker.OPEN_DOCUMENT);
//		System.out.println("  "+bitMaskString(i.getTodo()));
//		System.out.println("- "+bitMaskString(DocumentWorker.INTEGRATE_DOCUMENT));
//		i.addTodo(DocumentWorker.INTEGRATE_DOCUMENT);
//		System.out.println("= "+bitMaskString(i.getTodo()));
//	}
//	
//	
//	public static String bitMaskString (int i)
//	{
//		char[] bitmask = new char[32];
//		int index;
//		
//		for (index = bitmask.length-1; i != 0; index--)
//		{
//			if (index < 0)
//				System.out.println(i);
//			bitmask[index] = ((i & 1) > 0 ? '1' : '0');
//			i = i>>>1;
//		}
//		
//		while (index >= 0)
//			bitmask[index--] = '0';
//		
////		for (int index = 0; index < bitmask.length; index++)
////			System.out.print(bitmask[index]);
////		System.out.println();
//		return new String(bitmask);
//	}
}
