/* FichothequeLib_Tools - Copyright (c) 2018-2023 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;


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

    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 PatternDefs() {

    }

    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("addenda", "basename", "versions", "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")
                        .toPatternDef())
                .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")
                        .toPatternDef())
                .add("formsyntax")
                .toList();
    }


    public static List<PatternDef> ficheItem(String ficheItemType) {
        switch (ficheItemType) {
            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", "code", "sphere", "login", "standard", "directory", "updirectory", "biblio", "upbiblio", "surname", "upsurname", "forename", "nonlatin", "surnamefirst", "organism", "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.DATE_FIELD:
                return init()
                        .add("code")
                        .add("iso")
                        .add("lastday")
                        .add("year")
                        .add("isomonth")
                        .add("lastmonth")
                        .add("label", PatternDef.LANGS_DIRECTVALUE)
                        .add("monthlabel", PatternDef.LANGS_DIRECTVALUE)
                        .add("pattern", PatternDef.LETTERS_DIRECTVALUE)
                        .add("formsyntax")
                        .addJson("type", "code", "iso", "lastday", "year", "isomonth", "lastmonth", "labels", "monthlabels", "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.NUMBER_FIELD:
                return init()
                        .add("code")
                        .add("label", PatternDef.LANGS_DIRECTVALUE)
                        .add("formsyntax")
                        .addJson("type", "code", "labels", "formsyntax")
                        .toList();
            case CorpusField.AMOUNT_FIELD:
                return init()
                        .add("code")
                        .add("label", PatternDef.LANGS_DIRECTVALUE)
                        .add("currency")
                        .add("decimal")
                        .add("long")
                        .add("formsyntax")
                        .addJson("type", "code", "currency", "decimal", "labels", "long", "formsyntax")
                        .toList();
            case CorpusField.EMAIL_FIELD:
                return init()
                        .add("complete")
                        .add("address")
                        .add("name")
                        .add("formsyntax")
                        .addJson("type", "complete", "address", "name", "formsyntax")
                        .toList();
            case CorpusField.LINK_FIELD:
                return init()
                        .add(PatternDefBuilder.init("href")
                                .addParameter("base", "")
                                .toPatternDef())
                        .add("title")
                        .add("comment")
                        .add("formsyntax")
                        .addJson("type", "href", "title", "comment", "formsyntax")
                        .toList();
            case CorpusField.ITEM_FIELD:
                return init()
                        .add("value")
                        .add("formsyntax")
                        .addJson("type", "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.PARA_FIELD:
                return init()
                        .add("raw")
                        .add("transformation", PatternDef.TRANSFORMATION_SECTION_DIRECTVALUE)
                        .add("formsyntax")
                        .addJson("type", "raw", "formsyntax")
                        .toList();
            case CorpusField.IMAGE_FIELD:
                return init()
                        .add(PatternDefBuilder.init("src")
                                .addParameter("base", "")
                                .toPatternDef())
                        .add("alt")
                        .add("title")
                        .add("formsyntax")
                        .addJson("type", "src", "title", "alt", "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("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()
                .toList();
    }

    private static List<PatternDef> motcle(short 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("thesaurus", "idalpha", "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("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("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 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 List<PatternDef> toList() {
            return PatternDefUtils.wrap(list.toArray(new PatternDef[list.size()]));
        }

    }

}
