/* FichothequeLib_API - Copyright (c) 2013-2017 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package net.fichotheque.corpus.fiche;

import java.util.List;
import net.fichotheque.corpus.metadata.CorpusField;
import net.fichotheque.corpus.metadata.FieldKey;
import net.mapeadores.util.localisation.Lang;


/**
 * Interface définissant le contenu d'une fiche.
 *
 * @author Vincent Calame
 */
public interface FicheAPI {

    /**
     * Retourne le titre de la fiche. La valeur n'est jamais nulle mais peut
     * être vide
     *
     * @return le titre de la fiche
     */
    public String getTitle();

    /**
     * Retourne la langue de la fiche. Peut être nul.
     * <p>
     * La langue d'une fiche est unique. Lorsqu'une fiche est multilingue, elle
     * aura comme valeur de langue <tt>mul</tt>.
     *
     * @return la langue de la fiche
     */
    public Lang getLang();


    /**
     * Retourne le sous-titre de la fiche. Peut être nul.
     * <p>
     * Le champ Sous-titre est le seul champ spécial quui est optionnel (i.e.
     * certains corpus ne l'utilisent pas).
     *
     * @return le sous-titre de la fiche.
     */
    public ParaItem getSubtitle();

    /**
     * Retourne la liste des rédacteurs de la fiche. Est nul ou de longueur non
     * nulle.
     * <p>
     * La liste des rédacteurs sert notamment à déterminer les droits sur la
     * fiche.
     *
     * @return la liste des rédacteurs
     */

    public FicheItems getOwners();

    public List<Prop> getPropList();

    public List<Info> getInfoList();

    public List<Section> getSectionList();

    /**
     * Retourne la propriété correspondant au champ en argument. Peut être nul
     * si la propriété n'existe pas et renvoie une exception si fieldKey n'est
     * pas la clé d'un champ de type Propriete.
     *
     * @param fieldKey clé du champ propriété
     * @return instance de Prop correspondante ou nul
     */
    public Prop getProp(FieldKey fieldKey);


    /**
     * Retourne l'information correspondant au champ en argument. Peut être nul
     * si l'information n'existe pas et renvoie une exception si fieldKey n'est
     * pas la clé d'un champ de type Information.
     *
     * @param fieldKey clé du champ information
     * @return instance de Info correspondante ou nul
     */
    public Info getInfo(FieldKey fieldKey);

    /**
     * Retourne la section correspondant au champ en argument. Peut être nul si
     * la section n'existe pas et renvoie une exception si fieldKey n'est pas la
     * clé d'un champ de type Section.
     *
     * @param fieldKey clé du champ section
     * @return instance de Section correspondante ou nul
     */
    public Section getSection(FieldKey fieldKey);

    /**
     * Retourne l'objet correspondant au champ indiqué par l'argument FieldKey.
     * L'objet retourné peut être nul ou une instance d'une des interfaces
     * suivantes :
     * <ul>
     * <li>FicheItem pour les champs de type Propriété, Sous-titre (instance de
     * Para) et langue (instance de Langue)
     * <li>FicheItems contenant au moins un élément pour les champs de type
     * Information et Rédacteurs
     * <li>FicheBlocks contenant au moins un élément pour les champs de type
     * Section
     * <li>String pour le titre (nul si le titre est de longueur nulle)
     * </ul>
     * <p>
     * Si fieldKey est égal à FieldKey.ID, cela entraine une exception car
     * FicheAPI ne contient pas l'identifiant de la fiche.
     *
     * @param fiche fiche dont il faut extraire une valeur
     * @param fieldKey clé du champ à extraire
     * @return Valeur correspondante, peut être nulle.
     */
    public default Object getValue(FieldKey fieldKey) {
        switch (fieldKey.getCategory()) {
            case FieldKey.PROP_CATEGORY:
                Prop prop = getProp(fieldKey);
                if (prop == null) {
                    return null;
                }
                return prop.getFicheItem();
            case FieldKey.INFO_CATEGORY:
                return getInfo(fieldKey);
            case FieldKey.SECTION_CATEGORY:
                return getSection(fieldKey);
            case FieldKey.SPECIAL_CATEGORY:
                switch (fieldKey.getKeyString()) {
                    case FieldKey.SPECIAL_TITLE:
                        String title = getTitle();
                        if (title.isEmpty()) {
                            return null;
                        } else {
                            return title;
                        }

                    case FieldKey.SPECIAL_SUBTITLE:
                        return getSubtitle();
                    case FieldKey.SPECIAL_LANG:
                        Lang lang = getLang();
                        if (lang == null) {
                            return null;
                        } else {
                            return new LanguageItem(lang);
                        }
                    case FieldKey.SPECIAL_OWNERS:
                        return getOwners();
                    case FieldKey.SPECIAL_ID:
                        throw new IllegalArgumentException("FieldKey.ID is not contained in FicheAPI ");
                    default:
                        return null;
                }
            default:
                return null;
        }
    }

    public default Object getValue(CorpusField corpusField) {
        return getValue(corpusField.getFieldKey());
    }

}
