/* FichothequeLib_Xml - Copyright (c) 2024 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.xml.defs;

import java.io.IOException;
import java.util.List;
import net.fichotheque.exportation.balayage.BalayageConstants;
import net.fichotheque.exportation.balayage.BalayageDef;
import net.fichotheque.exportation.balayage.BalayageOutput;
import net.fichotheque.exportation.balayage.BalayagePostscriptum;
import net.fichotheque.exportation.balayage.BalayageUnit;
import net.fichotheque.selection.DocumentQuery;
import net.fichotheque.selection.FicheQuery;
import net.fichotheque.selection.IllustrationQuery;
import net.fichotheque.selection.MotcleQuery;
import net.fichotheque.utils.FichothequeXMLUtils;
import net.mapeadores.util.attr.AttributeUtils;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.localisation.Langs;
import net.mapeadores.util.text.AccoladePattern;
import net.mapeadores.util.text.LabelUtils;
import net.mapeadores.util.text.StringUtils;
import net.mapeadores.util.xml.XMLPart;
import net.mapeadores.util.xml.XMLWriter;


/**
 *
 * @author Vincent Calame
 */
public class BalayageDefXMLPart extends XMLPart {

    public BalayageDefXMLPart(XMLWriter xmlWriter) {
        super(xmlWriter);
    }

    public BalayageDefXMLPart addBalayageDef(BalayageDef balayageDef) throws IOException {
        openTag("balayage");
        LabelUtils.addLabels(this, balayageDef.getTitleLabels());
        Langs langs = balayageDef.getLangs();
        if (!langs.isEmpty()) {
            openTag("langs");
            for (Lang lang : langs) {
                addSimpleElement("lang", lang.toString());
            }
            closeTag("langs");
        }
        addSimpleElement("target-name", balayageDef.getTargetName());
        addSimpleElement("target-path", balayageDef.getTargetPath().toString());
        addSimpleElement("default-lang-option", balayageDef.getDefaultLangOption());
        addBoolean("ignore-transformation", balayageDef.ignoreTransformation());
        addPostcriptum(balayageDef.getPostscriptum());
        addUnits(balayageDef.getBalayageUnitList());
        FichothequeXMLUtils.writeSelectionOptions(this, balayageDef.getSelectionOptions());
        AttributeUtils.addAttributes(this, balayageDef.getAttributes());
        closeTag("balayage");
        return this;
    }

    private void addPostcriptum(BalayagePostscriptum postscriptum) throws IOException {
        openTag("postscriptum");
        addList(postscriptum.getExternalScriptNameList(), "script");
        addList(postscriptum.getScrutariExportNameList(), "scrutari");
        addList(postscriptum.getSqlExportNameList(), "sql");
        closeTag("postscriptum");
    }

    private void addList(List<String> valueList, String tagName) throws IOException {
        for (String value : valueList) {
            addSimpleElement(tagName, value);
        }
    }

    private void addUnits(List<BalayageUnit> list) throws IOException {
        openTag("units");
        for (BalayageUnit balayageUnit : list) {
            addBalayageUnit(balayageUnit);
        }
        closeTag("units");
    }

    public BalayageDefXMLPart addBalayageUnit(BalayageUnit balayageUnit) throws IOException {
        String type = balayageUnit.getType();
        String tagName = getTagName(type);
        startOpenTag(tagName);
        addAttribute("name", balayageUnit.getName());
        if (!balayageUnit.isGlobalSelect()) {
            addAttribute("global-select", "false");
        }
        addAttribute("extraction", balayageUnit.getExtractionPath());
        addAttribute("mode", StringUtils.implode(balayageUnit.getModeList(), ' '));
        endOpenTag();
        switch (type) {
            case BalayageConstants.CORPUS_TYPE:
            case BalayageConstants.FICHE_TYPE:
                addFicheQuery(balayageUnit);
                break;
            case BalayageConstants.THESAURUS_TYPE:
            case BalayageConstants.MOTCLE_TYPE:
                addMotcleQuery(balayageUnit);
                break;
            case BalayageConstants.DOCUMENT_TYPE:
                addFicheQuery(balayageUnit);
                addDocumentQuery(balayageUnit);
                break;
            case BalayageConstants.ILLUSTRATION_TYPE:
                addIllustrationQuery(balayageUnit);
                break;
        }
        for (String extension : balayageUnit.getExtensionList()) {
            addSimpleElement("extension", extension);
        }
        for (BalayageOutput output : balayageUnit.getOutputList()) {
            addOutput(output);
        }
        closeTag(tagName);
        return this;
    }

    private void addFicheQuery(BalayageUnit balayageUnit) throws IOException {
        FicheQuery ficheQuery = balayageUnit.getFicheQuery();
        if (ficheQuery.isEmpty()) {
            return;
        }
        FichothequeXMLUtils.writeFicheQuery(this, ficheQuery);
    }

    private void addMotcleQuery(BalayageUnit balayageUnit) throws IOException {
        MotcleQuery motcleQuery = balayageUnit.getMotcleQuery();
        if (motcleQuery.isEmpty()) {
            return;
        }
        FichothequeXMLUtils.writeMotcleQuery(this, motcleQuery);
    }

    private void addIllustrationQuery(BalayageUnit balayageUnit) throws IOException {
        IllustrationQuery illustrationQuery = balayageUnit.getIllustrationQuery();
        if (illustrationQuery.isEmpty()) {
            return;
        }
        FichothequeXMLUtils.writeIllustrationQuery(this, illustrationQuery);
    }

    private void addDocumentQuery(BalayageUnit balayageUnit) throws IOException {
        DocumentQuery documentQuery = balayageUnit.getDocumentQuery();
        if (documentQuery.isEmpty()) {
            return;
        }
        FichothequeXMLUtils.writeDocumentQuery(this, documentQuery);
    }

    private void addOutput(BalayageOutput output) throws IOException {
        startOpenTag("output");
        addAttribute("name", output.getName());
        addAttribute("xslt", output.getXsltPath());
        AccoladePattern pattern = output.getPattern();
        if (pattern != null) {
            addAttribute("pattern", pattern.toString());
        }
        if (output.isIncludeOutput()) {
            addAttribute("path", "_inc_/");
        } else {
            AccoladePattern outputPathPattern = output.getOutputPath();
            if (outputPathPattern != null) {
                addAttribute("path", outputPathPattern.toString());
            }
        }
        addAttribute("mode", output.getName());
        addAttribute("posttransform", output.getPosttransform());
        if (output.isCleanBefore()) {
            addAttribute("clean", "true");
        }
        Langs langs = output.getCustomLangs();
        if (langs != null) {
            addAttribute("langs", langs.toString(";"));
        }
        List<BalayageOutput.Param> paramList = output.getParamList();
        if (paramList.isEmpty()) {
            closeEmptyTag();
        } else {
            endOpenTag();
            for (BalayageOutput.Param param : paramList) {
                startOpenTag("param");
                addAttribute("name", param.getName());
                addAttribute("value", param.getValue());
                closeEmptyTag();
            }
            closeTag("output");
        }
    }

    private void addBoolean(String name, boolean value) throws IOException {
        if (value) {
            addEmptyElement(name);
        }
    }

    public static BalayageDefXMLPart init(XMLWriter xmlWriter) {
        return new BalayageDefXMLPart(xmlWriter);
    }

    private static String getTagName(String unitType) {
        switch (unitType) {
            case BalayageConstants.UNIQUE_TYPE:
                return "unique-balayage";
            case BalayageConstants.CORPUS_TYPE:
                return "corpus-balayage";
            case BalayageConstants.FICHE_TYPE:
                return "fiche-balayage";
            case BalayageConstants.THESAURUS_TYPE:
                return "thesaurus-balayage";
            case BalayageConstants.MOTCLE_TYPE:
                return "motcle-balayage";
            case BalayageConstants.DOCUMENT_TYPE:
                return "document-balayage";
            case BalayageConstants.ILLUSTRATION_TYPE:
                return "illustration-balayage";
            default:
                throw new IllegalArgumentException("wrong type value: " + unitType);
        }
    }

}
