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

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import lu.tudor.santec.gecamed.core.ejb.entity.beans.Autocompletion;
import lu.tudor.santec.gecamed.core.ejb.session.beans.AutocompletionBean;
import lu.tudor.santec.gecamed.core.ejb.session.interfaces.AutocompletionInterface;
import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.i18n.Translatrix;
import lu.tudor.santec.org.fife.ui.autocomplete.AutoCompletionTextComponent;
import lu.tudor.santec.org.fife.ui.autocomplete.Completion;
import lu.tudor.santec.org.fife.ui.autocomplete.MWACEvent;
import lu.tudor.santec.org.fife.ui.autocomplete.MWACListener;
import lu.tudor.santec.org.fife.ui.autocomplete.MWCompletionProvider;
import lu.tudor.santec.org.fife.ui.autocomplete.Translator;


public class GECAMedAutoCompletionHandler implements MWACListener
{
	public static final String PRESCRIPTION_CONTEXT 	= "prescription";
	public static final String FINDING_CONTEXT 			= "finding";
	public static final String DIAGNOSIS_CONTEXT 		= "diagnosis";
	public static final String TREATMENT_CONTEXT 		= "treatment";
	public static final String ANAMNESIS_CONTEXT 		= "anamnesis";
	public static final String SICK_LEAVE_CONTEXT		= "sick_leave";
	public static final String CONS_1_CONTEXT			= "cons.1";
	public static final String CONS_2_CONTEXT			= "cons.2";
	public static final String CONS_3_CONTEXT			= "cons.3";
	public static final String FINDING_CONTEXT_CODE 	= "finding_code";
	public static final String DIAGNOSIS_CONTEXT_CODE 	= "diagnosis_code";
	public static final String TREATMENT_CONTEXT_CODE 	= "treatment_code";
	public static final String ANAMNESIS_CONTEXT_CODE 	= "anamnesis_code";
	public static final String CONS_1_CONTEXT_CODE		= "cons.1_code";
	public static final String CONS_2_CONTEXT_CODE		= "cons.2_code";
	public static final String CONS_3_CONTEXT_CODE		= "cons.3_code";
	
	private static HashMap<String, MWCompletionProvider> providerMap = new HashMap<String, MWCompletionProvider>();
	
//	private boolean properInitialized = false;
	
	
	static 
	{
		// initialize the translations
		Map<String, String> translations = new HashMap<String, String>();
		translations.put(Translator.ADD_COMPLETION, 				Translatrix.getTranslationString(Translator.ADD_COMPLETION));
		translations.put(Translator.ADD_SELECTED_TEXT, 				Translatrix.getTranslationString(Translator.ADD_SELECTED_TEXT));
		translations.put(Translator.CANCEL, 						Translatrix.getTranslationString(Translator.CANCEL));
		translations.put(Translator.CLOSE, 							Translatrix.getTranslationString(Translator.CLOSE));
		translations.put(Translator.COMPLETE_UNAMBIGUOUSLY_HOTKEY,	Translatrix.getTranslationString(Translator.COMPLETE_UNAMBIGUOUSLY_HOTKEY));
		translations.put(Translator.EDIT_COMPLETION_HOTKEY, 		Translatrix.getTranslationString(Translator.EDIT_COMPLETION_HOTKEY));
		translations.put(Translator.EDIT_COMPLETIONS, 				Translatrix.getTranslationString(Translator.EDIT_COMPLETIONS));
		translations.put(Translator.HOTKEYS, 						Translatrix.getTranslationString(Translator.HOTKEYS));
		translations.put(Translator.INPUT_TEXT_TOOL_TIP, 			Translatrix.getTranslationString(Translator.INPUT_TEXT_TOOL_TIP));
		translations.put(Translator.NO, 							Translatrix.getTranslationString(Translator.NO));
		translations.put(Translator.OK, 							Translatrix.getTranslationString(Translator.OK));
		translations.put(Translator.QUICK_ADD_HOTKEY, 				Translatrix.getTranslationString(Translator.QUICK_ADD_HOTKEY));
		translations.put(Translator.REPLACEMENT_TEXT_TOOL_TIP,		Translatrix.getTranslationString(Translator.REPLACEMENT_TEXT_TOOL_TIP));
		translations.put(Translator.SAVE_COMPLETION, 				Translatrix.getTranslationString(Translator.SAVE_COMPLETION));
		translations.put(Translator.SAVE_COMPLETION_HOTKEY, 		Translatrix.getTranslationString(Translator.SAVE_COMPLETION_HOTKEY));
		translations.put(Translator.START_AUTO_COMPLETION_HOTKEY,	Translatrix.getTranslationString(Translator.START_AUTO_COMPLETION_HOTKEY));
		translations.put(Translator.YES, 							Translatrix.getTranslationString(Translator.YES));
		
		AutoCompletionTextComponent.setTranslations(translations);
		
		// set default options
		AutoCompletionTextComponent.EDIT_HOT_KEYS_ENABLED_BY_DEFAULT = false;
	}

	public void completionAdded(MWACEvent event)
	{
		MWCompletionProvider 	provider 	= event.getSource();
		List<Completion> 		completions	= event.getCompletions();
		
		if (provider == null
				|| provider.getContext() == null
				|| provider.getContext().length() == 0)
			return;
		
		AutocompletionInterface manager = getManager();
		String 					context = provider.getContext();
		Integer 				userId	= GECAMedModule.getCurrentUser().getId();
		GECAMedAutoCompletion 	gecamCompletion;
		Autocompletion 			ac;
		boolean 				isPrivate;
		String 					inputText;
		String 					replacementText;
		
		for (Completion c : completions)
		{
			inputText 					= c.getInputText();
			replacementText 			= c.getReplacementText();
			
			if (c instanceof GECAMedAutoCompletion)
			{
				gecamCompletion 		= ((GECAMedAutoCompletion) c);
				ac 						= gecamCompletion.getACBean();
			}
			else
			{
				gecamCompletion 		= null;
				ac 						= null;
			}
			
			isPrivate 					= (ac != null) ? ac.getUserId() != null : false;
			
			if (	   inputText == null
					|| inputText == replacementText
					|| inputText.equals(""))
				inputText 				= null;
			
			if (ac != null)
			{
				gecamCompletion.setACBean(manager.updateCompletion(ac));
			}
			else
			{
				ac = manager.addCompletion(context, 
						inputText, replacementText, isPrivate ? userId : null);
				provider.removeCompletion(c);
				provider.addCompletion(new GECAMedAutoCompletion(provider, ac));
			}
		}
	}

	public void completionRemoved(MWACEvent event)
	{
		MWCompletionProvider provider 	= event.getSource();
		List<Completion> completions	= event.getCompletions();

		if (provider == null
				|| provider.getContext() == null
				|| provider.getContext().length() == 0)
			return;
		
		AutocompletionInterface manager = getManager();
		String 					context = provider.getContext();
		Integer 				userId 	= GECAMedModule.getCurrentUser().getId();
		String 					inputText;
		String 					replacementText;
		
		for (Completion c : completions)
		{
			inputText 					= c.getInputText();
			replacementText 			= c.getReplacementText();
			
			if (c instanceof GECAMedAutoCompletion)
				manager.removeCompletion(((GECAMedAutoCompletion) c).getACBean().getId());
			else
				manager.removeCompletion(manager.getCompletion(inputText, replacementText, context, userId));
		}
	}

	public void completionChanged(MWACEvent event)
	{
		MWCompletionProvider provider 	= event.getSource();
		Completion newCompletion		= event.getCompletion();
		Completion oldCompletion		= event.getPreviousCompletion();

		if (provider == null
				|| provider.getContext() == null
				|| provider.getContext().length() == 0)
			return;
		
		AutocompletionInterface manager = getManager();
		String 	context 				= provider.getContext();
		Integer userId 					= GECAMedModule.getCurrentUser().getId();
		String 	inputText 				= oldCompletion.getInputText();
		String 	replacementText 		= oldCompletion.getReplacementText();
		
		Autocompletion ac;
		if (newCompletion instanceof GECAMedAutoCompletion)
		{
			// the bean already contains the changes
			GECAMedAutoCompletion c 	= (GECAMedAutoCompletion)newCompletion;
			ac = c.getACBean();
			ac.setUserId(c.isPrivate() ? userId : null);
			if (!c.isInputTextSet())
				ac.setInputText(null);
		}
		else
		{
			ac = manager.getCompletion(inputText, replacementText, context, null);
			ac.setReplacementText(newCompletion.getReplacementText());
			ac.setInputText(newCompletion.getInputText());
		}
		
		manager.updateCompletion(ac);
	}

	public void initializeCompletion(MWACEvent event)
	{
		MWCompletionProvider provider 	= event.getSource();
		AutocompletionInterface manager = getManager();
		
		reloadProvider(provider, manager);
	}

	
	public MWCompletionProvider getProviderByContext (String context)
	{
		if (context == null || context.trim().equals(""))
			return new MWCompletionProvider(context);
	
		MWCompletionProvider provider = providerMap.get(context);
		
		if (provider == null)
		{
			provider = new MWCompletionProvider(context);
			providerMap.put(context, provider);
		}
		
		return provider;
	}
	
	
	public static void reloadProvider (Collection<String> contexts)
	{
		AutocompletionInterface manager = getManager();
		for (String context : contexts)
			reloadProvider(providerMap.get(context), manager);
	}
	
	
	public static void reloadProvider (String context)
	{
		reloadProvider(providerMap.get(context), getManager());
	}
	
	
	private static void reloadProvider (MWCompletionProvider provider, AutocompletionInterface manager)
	{
		if (provider == null)
			return;
		
		String context = provider.getContext();
		Integer 				userId 		= GECAMedModule.getCurrentUser().getId();
		List<Completion> 		completions = new LinkedList<Completion>();
		List<Autocompletion> 	results		= manager.getCompletions(context, userId);
		
		provider.clear();
		
		if (results != null)
			for (Autocompletion ac : results)
				completions.add(new GECAMedAutoCompletion(provider, ac));
		
		provider.initializeProviderCompletions(completions);
	}
	
	
//	public void contextChanged(MWACEvent event)
//	{
//		if (!properInitialized)
//			return;
//		
//		event.getSource().getContext();
//	}
	
	
	private static AutocompletionInterface getManager ()
	{
		return (AutocompletionInterface)ManagerFactory.getRemote(AutocompletionBean.class);
	}
}
