package lu.tudor.santec.gecamed.esante.ejb.entity.beans;

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

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Transient;

import lu.tudor.santec.gecamed.core.ejb.entity.beans.GECAMedEntityBean;

/**
 * A java bean container for all CDA codes of a specific code category.
 * 
 * @author jens.ferring(at)tudor.lu
 * 
 * @version <br>
 *          $Log: CdaCodeCategory.java,v $
 *          Revision 1.9  2013-12-04 13:11:10  ferring
 *          CdaCodeDescription added
 *
 *          Revision 1.8  2013-10-22 06:54:00  ferring
 *          trailing comma removed
 *
 *          Revision 1.7  2013-10-21 08:15:30  ferring
 *          loading CdaCodes if there not loaded and creating not existing, if they don't exist in the DB
 *
 *          Revision 1.6  2013-10-08 16:43:43  donak
 *          Adjusted ErrorDialog to allow user to copy error details to clipboard or save them to file system
 *          Changed order of code display names in CdaUpload dialog for desc. to asc.
 *
 *          Revision 1.5  2013-10-08 08:57:36  ferring
 *          commit comments utf8 correction
 *
 *          Revision 1.4  2013-10-08 08:49:06  ferring
 *          orderBy fixed
 *
 *          Revision 1.3  2013-10-07 16:12:12  donak
 *          Logging, message backup, and error protocol creation
 *
 *          Revision 1.2  2013-10-04 17:22:44  donak
 *          eSanté upload dialog and integration of selected values
 *
 *          Revision 1.1  2013-10-03 11:17:21  donak
 *          eSanté integration CDA document upload metadata configuration dialog
 * <br>
 *          Revision 1.3 2013-10-01 10:03:11 ferring <br>
 *          enhancement in code fetching <br>
 * <br>
 *          Revision 1.2 2013-10-01 07:12:14 ferring <br>
 * @Transient added for method <br>
 * <br>
 *            Revision 1.1 2013-10-01 07:04:37 ferring <br>
 *            CDA codes introduced <br>
 */
@NamedQueries({
	@NamedQuery(name = CdaCodeCategory.GET_CATEGORY_BY_UUID,	query = "SELECT OBJECT(o) FROM CdaCodeCategory o " + 
																		"WHERE uuid = :uuid"),
	@NamedQuery(name = CdaCodeCategory.GET_CATEGORY_BY_NAME,	query = "SELECT OBJECT(o) FROM CdaCodeCategory o " + 
																		"WHERE name = :name")
})
@Entity
@Table(schema = "esante", name = "code_type")
public class CdaCodeCategory extends GECAMedEntityBean {
    /* ======================================== */
    // CONSTANTS
    /* ======================================== */
	
	public static final String GET_CATEGORY_BY_UUID = "getCategoryByUuid";
	public static final String GET_CATEGORY_BY_NAME = "getCategoryByName";
	

    private static final long serialVersionUID = 1L;

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

    private String name;

    private String uuid;

    private String codingScheme;

    private List<CdaCode> codes;

    /* ---------------------------------------- */
    // TRANSIENT MEMBERS
    /* ---------------------------------------- */

    // contains all codes of the current code categories, identified by their code ids
    private Map<String, CdaCode> mapCodeIdToCdaCode;

    /* ======================================== */
    // GETTER & SETTER
    /* ======================================== */

    /**
     * Provides the name of the CDA code category (e.g. typeCode)
     * 
     * @return The name of the CDA code category
     */
    @Column(name = "name")
    public String getName() {
        return name;
    }

    /**
     * Sets the name of the CDA code category
     * 
     * @param name
     *            The name of the CDA code category (e.g. typeCode)
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * Provides the uuid of the CDA code category (e.g. urn:uuid:f0306f51-975f-434e-a61c-c59651d33983)
     * 
     * @return The uuid of the CDA code category
     */
    @Column(name = "uuid")
    public String getUuid() {
        return uuid;
    }

    /**
     * Sets the uuid of the CDA code category
     * 
     * @param uuid
     *            The uuid of the CDA code category (e.g. urn:uuid:f0306f51-975f-434e-a61c-c59651d33983)
     */
    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    /**
     * Provides the coding scheme of the CDA code category (e.g. 1.2.250.1.213.1.1.4.12)
     * 
     * @return The coding scheme of the CDA code category
     */
    @Column(name = "coding_scheme")
    public String getCodingScheme() {
        return codingScheme;
    }

    /**
     * Sets the coding scheme of the CDA code category
     * 
     * @param codingScheme
     *            The coding scheme of the CDA code category (e.g. 1.2.250.1.213.1.1.4.12)
     */
    public void setCodingScheme(String codingScheme) {
        this.codingScheme = codingScheme;
    }

    /**
     * Provides all available CdaCodes independent of their category (?)
     * 
     * @return A list of all CDA codes
     */
    @OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
    @JoinColumn(name = "code_type_id")
    @OrderBy("codeId ASC")
    public List<CdaCode> getCodes() {
        return codes;
    }

    /**
     * Sets the list of all available CDA codes independent of their category (?)
     * 
     * @param codes
     *            A list containing all CDA cdes
     */
    public void setCodes(List<CdaCode> codes) {
        this.codes = codes;
    }

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

    /**
     * Provides a specific CDA code within the category
     * 
     * @param code
     *            The code id of the desired CDA code
     * @return The CDA code object or null if the desired code was not found
     */
    @Transient
    public CdaCode getCdaCodeByCodeId(String code) {
        if (mapCodeIdToCdaCode == null) {
            mapCodeIdToCdaCode = new HashMap<String, CdaCode>(codes.size());

            for (CdaCode cdaCode : codes)
                mapCodeIdToCdaCode.put(cdaCode.getCodeId(), cdaCode);
        }

        return mapCodeIdToCdaCode.get(code);
    }
}
