/* FichothequeLib_Tools - Copyright (c) 2008-2022 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.tools.conversion.fieldtofield;

import java.util.ArrayList;
import java.util.List;
import net.fichotheque.corpus.fiche.Cdatadiv;
import net.fichotheque.corpus.fiche.Code;
import net.fichotheque.corpus.fiche.Div;
import net.fichotheque.corpus.fiche.Fiche;
import net.fichotheque.corpus.fiche.FicheBlock;
import net.fichotheque.corpus.fiche.FicheBlocks;
import net.fichotheque.corpus.fiche.FicheItem;
import net.fichotheque.corpus.fiche.Li;
import net.fichotheque.corpus.fiche.Ln;
import net.fichotheque.corpus.fiche.P;
import net.fichotheque.corpus.fiche.ParaItem;
import net.fichotheque.corpus.fiche.ParagraphBlock;
import net.fichotheque.corpus.fiche.S;
import net.fichotheque.corpus.fiche.Table;
import net.fichotheque.corpus.fiche.Td;
import net.fichotheque.corpus.fiche.Tr;
import net.fichotheque.corpus.fiche.Ul;
import net.fichotheque.corpus.metadata.FieldKey;
import net.fichotheque.utils.FicheUtils;
import net.mapeadores.util.logging.MultiMessageHandler;


/**
 *
 * @author Vincent Calame
 */
class SectionToFicheItemField extends FieldToFieldConverter {

    private final FieldKey sourceKey;
    private final FieldKey destinationKey;

    SectionToFicheItemField(FieldKey sourceKey, FieldKey destinationKey, MultiMessageHandler messageHandler) {
        super(messageHandler);
        this.sourceKey = sourceKey;
        this.destinationKey = destinationKey;
    }

    @Override
    void convertContent(Fiche fiche, boolean removeOldField) {
        FicheBlocks ficheBlocks = fiche.getSection(sourceKey);
        if ((ficheBlocks == null) || (ficheBlocks.size() == 0)) {
            return;
        }
        List<FicheItem> ficheItems = new ArrayList<FicheItem>();
        boolean onlyP = appendPara(ficheItems, ficheBlocks);
        if (!onlyP) {
            addWarning("_ warning.conversion.containsnotonlyp", sourceKey.getKeyString());
        }
        int size = ficheItems.size();
        if (size == 0) {
            return;
        }
        if (destinationKey.isProp()) {
            FicheItem ficheItem = ficheItems.get(0);
            fiche.setProp(destinationKey, ficheItem);
            if (size > 1) {
                addWarning("_ warning.conversion.manyficheblocks", sourceKey.getKeyString());
            }
        } else {
            fiche.appendInfo(destinationKey, FicheUtils.toFicheItems(ficheItems));
        }
        if (removeOldField) {
            fiche.setSection(sourceKey, null);
        }
    }

    private boolean appendPara(List<FicheItem> list, FicheBlocks ficheBlocks) {
        boolean onlyP = true;
        int size = ficheBlocks.size();
        for (int i = 0; i < size; i++) {
            FicheBlock ficheBlock = ficheBlocks.get(i);
            if (!(ficheBlock instanceof P)) {
                onlyP = false;
            }
            if (ficheBlock instanceof ParagraphBlock) {
                ParaItem para = toPara((ParagraphBlock) ficheBlock);
                if (para != null) {
                    list.add(para);
                }
            } else if (ficheBlock instanceof Div) {
                appendPara(list, ((Div) ficheBlock));
            } else if (ficheBlock instanceof Cdatadiv) {
                String s = ((Cdatadiv) ficheBlock).getCdata();
                if (s.length() > 0) {
                    ParaItem.Builder builder = new ParaItem.Builder();
                    builder.addText(s);
                    list.add(builder.toParaItem());
                }
            } else if (ficheBlock instanceof Ul) {
                for (Li li : (Ul) ficheBlock) {
                    appendPara(list, li);
                }
            } else if (ficheBlock instanceof Code) {
                for (Ln ln : (Code) ficheBlock) {
                    ParaItem para = toPara(ln);
                    if (para != null) {
                        list.add(para);
                    }
                }
            } else if (ficheBlock instanceof Table) {
                for (Tr tr : (Table) ficheBlock) {
                    for (Td td : tr) {
                        ParaItem para = toPara(td);
                        if (para != null) {
                            list.add(para);
                        }
                    }
                }
            }
        }
        return onlyP;
    }

    private ParaItem toPara(ParagraphBlock paragraphBlock) {
        ParaItem.Builder builder = new ParaItem.Builder();
        if (paragraphBlock.isEmpty()) {
            return null;
        }
        for (Object obj : paragraphBlock) {
            if (obj instanceof S) {
                builder.addS((S) obj);
            } else if (obj instanceof String) {
                builder.addText((String) obj);
            }
        }
        return builder.toParaItem();
    }

}
