/* FichothequeLib_Tools - Copyright (c) 2018-2025 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.format.patterndefs;

import java.util.ArrayList;
import java.util.List;
import net.fichotheque.corpus.metadata.CorpusField;
import net.fichotheque.format.PatternDef;
import net.fichotheque.thesaurus.metadata.ThesaurusMetadata;
import net.mapeadores.util.date.FuzzyDate;
import net.mapeadores.util.format.FormatConstants;


/**
 *
 * @author Vincent Calame
 */
public class PatternDefCatalog {

    public final static List<PatternDef> ATTRIBUTE = attribute();
    public final static List<PatternDef> DOCUMENT = document();
    public final static List<PatternDef> EXTRACTION = extraction();
    public final static List<PatternDef> FICHEBLOCK = ficheBlock();
    public final static List<PatternDef> FICHEMETA = ficheMeta();
    public final static List<PatternDef> ILLUSTRATION = illustration();
    public final static List<PatternDef> MOTCLE_MULTI = motcle(ThesaurusMetadata.MULTI_TYPE);
    public final static List<PatternDef> MOTCLE_IDALPHA = motcle(ThesaurusMetadata.IDALPHA_TYPE);
    public final static List<PatternDef> MOTCLE_BABELIEN = motcle(ThesaurusMetadata.BABELIEN_TYPE);
    public final static List<PatternDef> IDALPHA = idalpha();
    public final static List<PatternDef> VALUE = value();

    private PatternDefCatalog() {

    }

    private static List<PatternDef> attribute() {
        return init()
                .add("value")
                .add("formsyntax")
                .toList();
    }

    private static List<PatternDef> document() {
        return init()
                .add("basename")
                .add("extensions")
                .add("addenda")
                .add("id")
                .add("weight")
                .add("formsyntax")
                .addJson("-type", "-id", "-basename", "-versions", "addenda", "size")
                .toList();
    }

    private static List<PatternDef> extraction() {
        return init()
                .add("xml")
                .add(PatternDefBuilder.init("transformation")
                        .setDirectValueType(PatternDef.TRANSFORMATION_FORMAT_DIRECTVALUE)
                        .addParameter("startlevel", "1…6")
                        .addParameter("externaltarget", "_blank")
                        .addParameter("lang", "_fiche, lang"))
                .add("formsyntax")
                .toList();
    }

    private static List<PatternDef> ficheBlock() {
        return init()
                .add("text")
                .add("values")
                .add("xml")
                .add(PatternDefBuilder.init("transformation")
                        .setDirectValueType(PatternDef.TRANSFORMATION_SECTION_DIRECTVALUE)
                        .addParameter("startlevel", "1…6")
                        .addParameter("externaltarget", "_blank")
                        .addParameter("lang", "_fiche, lang"))
                .add("formsyntax")
                .toList();
    }


    public static List<PatternDef> ficheItem(String ficheItemType) {
        switch (ficheItemType) {
            case CorpusField.AMOUNT_FIELD:
                return init()
                        .add("code")
                        .add(PatternDefBuilder.init("label")
                                .setDirectValueType(PatternDef.LANGS_DIRECTVALUE)
                                .addParameter("subunit", "force")
                                .addParameter("sep", ""))
                        .add("currency")
                        .add("decimal")
                        .add("long")
                        .add("formsyntax")
                        .addJson("-type", "-currency", "-decimal", "-long", "code", "labels", "formsyntax")
                        .toList();
            case CorpusField.COUNTRY_FIELD:
                return init()
                        .add("code")
                        .add("label", PatternDef.LANGS_DIRECTVALUE)
                        .add("formsyntax")
                        .addJson("-type", "-code", "labels", "formsyntax")
                        .toList();
            case CorpusField.DATE_FIELD:
                return init()
                        .add("code")
                        .add("iso")
                        .add("lastday")
                        .add("year")
                        .add("isomonth")
                        .add("lastmonth")
                        .add(PatternDefBuilder.init("label")
                                .setDirectValueType(PatternDef.LANGS_DIRECTVALUE)
                                .addParameter("datesyle", FormatConstants.SHORT_DATESTYLE, FormatConstants.MEDIUM_DATESTYLE, FormatConstants.LONG_DATESTYLE, FormatConstants.FULL_DATESTYLE)
                                .addParameter("truncate", FuzzyDate.MONTH_TYPE, FuzzyDate.QUARTER_TYPE, FuzzyDate.HALFYEAR_TYPE, FuzzyDate.YEAR_TYPE)
                                .addParameter("sep", ""))
                        .add(PatternDefBuilder.init("pattern")
                                .setDirectValueType(PatternDef.LETTERS_DIRECTVALUE)
                                .addParameter("lang", PatternDef.LANGS_DIRECTVALUE)
                                .addParameter("sep", "")
                        )
                        .add("formsyntax")
                        .add(initJson("-type", "-extent", "-code", "-iso", "lastday", "year", "isomonth", "lastmonth", "labels", "monthlabels", "formsyntax")
                                .addParameter("datastyle", FormatConstants.SHORT_DATESTYLE, FormatConstants.MEDIUM_DATESTYLE, FormatConstants.LONG_DATESTYLE, FormatConstants.FULL_DATESTYLE))
                        .toList();
            case CorpusField.EMAIL_FIELD:
                return init()
                        .add("complete")
                        .add("address")
                        .add("name")
                        .add("formsyntax")
                        .addJson("-type", "-address", "complete", "name", "formsyntax")
                        .toList();
            case CorpusField.GEOPOINT_FIELD:
                return init()
                        .add("lat")
                        .add("latlabel", PatternDef.LANGS_DIRECTVALUE)
                        .add("lon")
                        .add("lonlabel", PatternDef.LANGS_DIRECTVALUE)
                        .add("formsyntax")
                        .addJson("-type", "-lat", "-lon", "latlabels", "lonlabels", "formsyntax")
                        .toList();
            case CorpusField.IMAGE_FIELD:
                return init()
                        .add(PatternDefBuilder.init("src")
                                .addParameter("base", ""))
                        .add("alt")
                        .add("title")
                        .add("formsyntax")
                        .addJson("-type", "-src", "title", "alt", "formsyntax")
                        .toList();
            case CorpusField.PERSON_FIELD:
                return init()
                        .add("code")
                        .add("sphere")
                        .add("login")
                        .add("standard")
                        .add("directory")
                        .add("updirectory")
                        .add("biblio")
                        .add("upbiblio")
                        .add("surname")
                        .add("upsurname")
                        .add("forename")
                        .add("nonlatin")
                        .add("surnamefirst")
                        .add("organism")
                        .add("formsyntax")
                        .addJson("-type", "-standard", "code", "sphere", "login", "directory", "updirectory", "biblio", "upbiblio", "surname", "upsurname", "forename", "nonlatin", "surnamefirst", "organism", "formsyntax")
                        .toList();
            case CorpusField.ITEM_FIELD:
                return init()
                        .add("value")
                        .add("formsyntax")
                        .addJson("-type", "-value", "formsyntax")
                        .toList();
            case CorpusField.LANGUAGE_FIELD:
                return init()
                        .add("code")
                        .add("label", PatternDef.LANGS_DIRECTVALUE)
                        .add("formsyntax")
                        .addJson("-type", "-code", "labels", "formsyntax")
                        .toList();
            case CorpusField.LINK_FIELD:
                return init()
                        .add(PatternDefBuilder.init("href")
                                .addParameter("base", ""))
                        .add("title")
                        .add("comment")
                        .add("formsyntax")
                        .addJson("-type", "-href", "title", "comment", "formsyntax")
                        .toList();
            case CorpusField.NUMBER_FIELD:
                return init()
                        .add("code")
                        .add("label", PatternDef.LANGS_DIRECTVALUE)
                        .add("formsyntax")
                        .addJson("-type", "-code", "-value", "labels", "formsyntax")
                        .toList();
            case CorpusField.PARA_FIELD:
                return init()
                        .add("raw")
                        .add("transformation", PatternDef.TRANSFORMATION_SECTION_DIRECTVALUE)
                        .add("formsyntax")
                        .addJson("-type", "-raw", "formsyntax")
                        .toList();
            default:
                throw new IllegalArgumentException("Unknown ficheItemType: " + ficheItemType);
        }
    }

    private static List<PatternDef> ficheMeta() {
        return init().add("id")
                .add("title")
                .add("lang")
                .add("corpus")
                .add("weight")
                .add("formsyntax")
                .addJsonWithProperties("-type", "-id", "corpus", "lang", "title")
                .toList();
    }

    private static List<PatternDef> idalpha() {
        return init()
                .add("value")
                .add("significant")
                .toList();
    }

    private static List<PatternDef> illustration() {
        return init().add("album")
                .add("id")
                .add("format")
                .add("weight")
                .add("formsyntax")
                .addJson("-type", "-id", "-format", "filename")
                .toList();
    }

    private static List<PatternDef> motcle(String thesaurusType) {
        switch (thesaurusType) {
            case ThesaurusMetadata.MULTI_TYPE:
                return init()
                        .add("id")
                        .add("label", PatternDef.LANGS_DIRECTVALUE)
                        .add("weight")
                        .add("thesaurus")
                        .add("position", PatternDef.POSITION_DIRECTVALUE)
                        .add("parent_id")
                        .add("formsyntax")
                        .addJsonWithProperties("-type", "-id", "-idalpha", "thesaurus", "idalpha_significant", "idalpha_always", "labels")
                        .toList();
            case ThesaurusMetadata.IDALPHA_TYPE:
                return init()
                        .add("id")
                        .add("idalpha", PatternDef.IDALPHA_DIRECTVALUE)
                        .add("label", PatternDef.LANGS_DIRECTVALUE)
                        .add("weight")
                        .add("thesaurus")
                        .add("position", PatternDef.POSITION_DIRECTVALUE)
                        .add("parent_id")
                        .add("parent_idalpha", PatternDef.IDALPHA_DIRECTVALUE)
                        .add("formsyntax")
                        .addJsonWithProperties("-type", "-id", "-idalpha", "thesaurus", "idalpha(_significant)", "labels")
                        .toList();
            case ThesaurusMetadata.BABELIEN_TYPE:
                return init()
                        .add("id")
                        .add("label")
                        .add("weight")
                        .add("thesaurus")
                        .add("position", PatternDef.POSITION_DIRECTVALUE)
                        .add("parent_id")
                        .add("lang")
                        .add("formsyntax")
                        .addJsonWithProperties("-type", "-id", "thesaurus", "idalpha", "labels")
                        .toList();
            default:
                throw new IllegalArgumentException("Unknown thesaurusType: " + thesaurusType);
        }

    }

    private static List<PatternDef> value() {
        return init()
                .add("value")
                .add("formsyntax")
                .toList();
    }

    private static PatternDefBuilder initJson(String... availableInclude) {
        return PatternDefBuilder.init("json").addParameter("include", availableInclude);
    }

    private static ListBuilder init() {
        return new ListBuilder();
    }


    private static class ListBuilder {

        private final List<PatternDef> list = new ArrayList<PatternDef>();

        private ListBuilder() {

        }

        private ListBuilder add(String name) {
            list.add(PatternDefBuilder.init(name).toPatternDef());
            return this;
        }

        private ListBuilder add(String name, String parameterFamily) {
            list.add(PatternDefBuilder.init(name).setDirectValueType(parameterFamily).toPatternDef());
            return this;
        }

        private ListBuilder addJson(String... availableInclude) {
            list.add(PatternDefBuilder.init("json").addParameter("include", availableInclude).toPatternDef());
            return this;
        }

        private ListBuilder addJsonWithProperties(String... availableInclude) {
            list.add(PatternDefBuilder.init("json").addParameter("include", availableInclude).addParameter("properties").toPatternDef());
            return this;
        }

        private ListBuilder add(PatternDef patternDef) {
            list.add(patternDef);
            return this;
        }

        private ListBuilder add(PatternDefBuilder patternDefBuilder) {
            list.add(patternDefBuilder.toPatternDef());
            return this;
        }


        private List<PatternDef> toList() {
            return PatternDefUtils.wrap(list.toArray(new PatternDef[list.size()]));
        }


    }

}
