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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import lu.tudor.santec.gecamed.core.ejb.entity.beans.GECAMedLocale;
import lu.tudor.santec.gecamed.core.gui.GECAMedLists;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.esante.ejb.entity.beans.CdaCode;
import lu.tudor.santec.gecamed.esante.ejb.entity.beans.CdaCodeCategory;
import lu.tudor.santec.gecamed.esante.ejb.entity.beans.CdaCodeDescription;
import lu.tudor.santec.gecamed.esante.ejb.session.beans.ESanteConfigManagerBean;
import lu.tudor.santec.gecamed.esante.ejb.session.interfaces.ESanteConfigManager;

/**
 * @author jens.ferring(at)tudor.lu
 * 
 * @version <br>
 *          $Log: CodeFetcher.java,v $
 *          Revision 1.13  2013-12-27 18:09:26  donak
 *          Cleanup of imports
 *
 *          Revision 1.12  2013-12-08 22:14:40  donak
 *          Upload for CDA documents to eSanté platform finished. However upload is still not working as required codes do not seem to be implemented at the platform repository
 *
 *          Revision 1.11  2013-12-05 15:19:26  donak
 *          Partial upload support for the eSanté platform, not yet functional
 *
 *          Revision 1.10  2013-12-05 10:32:44  ferring
 *          code type removed
 *
 *          Revision 1.9  2013-12-04 15:22:35  ferring
 *          CdaCodeDescription added
 *
 *          Revision 1.8  2013-12-04 13:12:52  ferring
 *          CdaCodeDescription added
 *
 *          Revision 1.7  2013-10-21 08:19:54  ferring
 *          loading CdaCodes if there not loaded and creating not existing, if they don't exist in the DB
 *
 *          Revision 1.6  2013-10-17 14:54:30  donak
 *          Corrected upload handler for letters
 *          Defined incident entry dependent presets for upload metadata
 *          Bug fixing and documentation
 *
 *          Revision 1.5  2013-10-08 08:57:37  ferring
 *          commit comments utf8 correction
 *
 *          Revision 1.4  2013-10-03 16:32:37  donak
 *          eSanté integration CDA document upload metadata configuration dialog - there is a problem w/ the entity beans (CdaCodeCategory is not found), which needs to be addressed
 *
 *          Revision 1.3  2013-10-03 11:17:21  donak
 *          eSanté integration CDA document upload metadata configuration dialog
 * <br>
 *          Revision 1.2 2013-10-01 10:03:11 ferring <br>
 *          enhancement in code fetching <br>
 * <br>
 *          Revision 1.1 2013-10-01 07:04:37 ferring <br>
 *          CDA codes introduced <br>
 */

public class CodeFetcher {
    /* ======================================== */
    // CONSTANTS
    /* ======================================== */

    public static final String CLASS_CODE = "classCode";
//    public static final String CONTENT_TYPE_CODE = "contentTypeCode";
    public static final String TYPE_CODE = "typeCode";    
    public static final String LANGUAGE_CODE = "languageCode";
    public static final String FORMAT_CODE = "formatCode";
    public static final String CONFIDENTIALITY_CODE = "confidentialityCode";
    public static final String PRACTICE_SETTING_CODE = "practiceSettingCode";
    public static final String HEALTH_CARE_FACILITY_TYPE_CODE = "healthCareFacilityTypeCode";    
    public static final String AUTHOR_ROLE = "authorRole";    
    public static final String AUTHOR_SPECIALTY = "authorSpecialty";
//    public static final String EVENT_CODE_LIST = "eventCodeList";

    /* ======================================== */
    // MEMBERS
    /* ======================================== */

    private static Map<String, CdaCodeCategory> mapNameToCodeCategory;

    private static Map<String, CdaCodeCategory> mapUuidToCodeCategory;

    private static Map<Integer, List<CdaCode>> mapParentCodeIdToChildren = new HashMap<Integer, List<CdaCode>>();

    /* ======================================== */
    // CLASS BODY
    /* ======================================== */

//    /**
//     * Uses the method {@link GECAMedLists#getListCopy(Class)}, to return a list of all code categories.
//     * 
//     * @return A list of all code types, stored in the DB.
//     */
//    public List<CdaCodeCategory> getCdaCodeCategories() {
//        return GECAMedLists.getListCopy(CdaCodeCategory.class);
//    }

    /**
     * Provides a certain code category
     * 
     * @param categoryName
     *            The name of the desired code category
     * @return The code category
     */
    public static CdaCodeCategory getCodeCategoryByName(String categoryName) {
        if (mapNameToCodeCategory == null)
            init();
        
        return mapNameToCodeCategory.get(categoryName);
    }

    /**
     * Provides a certain code category
     * 
     * @param uuid
     *            The UUID of the CodeType to return
     * @return The CodeType with the specified UUID
     */
    public static CdaCodeCategory getCodeCategoryByUuid(String uuid) {
        if (mapUuidToCodeCategory == null) {
            init();
        }
        
        return mapUuidToCodeCategory.get(uuid);
    }

    /**
     * Provides a specific cda code of a specific category
     * 
     * @param categoryName
     *            The CodeType name to which the code belongs
     * @param codeId
     *            The code of the CodeAttributes to return
     * @return The CodeAttributes of the specified code type containing the specified code
     */
    public static CdaCode getCdaCode(String categoryName, String codeId) {
        CdaCodeCategory category = getCodeCategoryByName(categoryName);
        
        if (category == null) {
            return null;
        }
        
        CdaCode code = category.getCdaCodeByCodeId(codeId);
        
        if (code == null)
        {
        	// TODO REMOVE CHANGES AS SOON AS THE AGENCE ESANTE PROVIDED PROPER CODES FOR MULTILANGUAGE SUPPORT
//        	code = ESanteConfigManagerBean.getInstance().getCdaCode(category.getId(), codeId, 
//        			GECAMedModule.getCurrentUser().getGecamedLocale().getLanguage());
        	code = ESanteConfigManagerBean.getInstance().getCdaCode(category.getId(), codeId, 
        			GECAMedLocale.FRENCH);
        	category.getCodes().add(code);
        }
        
        return code;
    }
    

    /**
     * Provides all cda codes of a specific category
     * 
     * @param categoryName
     *            The CodeType name to which the code belongs

     * @return A list of all cda codes belonging to a specific cda category
     */
    public static List<CdaCode> getCdaCodes(String categoryName) {
        CdaCodeCategory category = getCodeCategoryByName(categoryName);

        if (category == null) {
            return null;
        }

        return category.getCodes();
    }

    /**
     * 
     * @param parentCodeAttributes
     *            The code of the parent {@link CdaCode}
     * @return A list of all {@link CdaCode}, that are child of the {@link CdaCode} with the specified code.
     */
    public static List<CdaCode> getChildren(CdaCode parentCdaCode) {
        Integer parentId = parentCdaCode.getId();
        List<CdaCode> attributes = mapParentCodeIdToChildren.get(parentId);
        
        if (attributes == null) {
            ESanteConfigManager manager = (ESanteConfigManager) ManagerFactory.getRemote(ESanteConfigManagerBean.class);
            attributes = manager.getCdaCodeChildren(parentId);
            if (attributes == null)
                attributes = new ArrayList<CdaCode>(0);

            mapParentCodeIdToChildren.put(parentId, attributes);
        }
        
        return attributes;
    }
    
    
    
    /* ======================================== */
    // HELP METHODS
    /* ======================================== */

	private static void init ()
	{
		List<CdaCodeCategory>	codeCategories = GECAMedLists.getListReference(CdaCodeCategory.class);
		Map<Integer, CdaCodeDescription>	codesOfCategory;
		
		
		// create the maps
		mapNameToCodeCategory = new HashMap<String, CdaCodeCategory>(codeCategories.size());
		mapUuidToCodeCategory = new HashMap<String, CdaCodeCategory>(codeCategories.size());
		
		for (CdaCodeCategory category : codeCategories)
		{
			// TODO REMOVE CHANGES AS SOON AS THE AGENCE ESANTE PROVIDED PROPER CODES FOR MULTILANGUAGE SUPPORT
//			codesOfCategory	= ESanteConfigManagerBean.getInstance().getCdaCodeDescriptionsOfCategory(
//					category.getId(), GECAMedModule.getCurrentUser().getGecamedLocale().getLanguage());
			codesOfCategory	= ESanteConfigManagerBean.getInstance().getCdaCodeDescriptionsOfCategory(
					category.getId(),GECAMedLocale.FRENCH);
			
			for (CdaCode code : category.getCodes())
			{
				code.setDescription(codesOfCategory.get(code.getId()));
			}
//			System.out.println("CdaCodeCategory added: " + category.getName());
			mapNameToCodeCategory.put(category.getName(), category);
			mapUuidToCodeCategory.put(category.getUuid(), category);
		}
	}
}
