/* BdfServer_HtmlProducers - Copyright (c) 2011-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 fr.exemole.bdfserver.htmlproducers.main;

import fr.exemole.bdfserver.api.instruction.BdfParameters;
import fr.exemole.bdfserver.api.interaction.Domains;
import fr.exemole.bdfserver.api.interaction.domains.AddendaDomain;
import fr.exemole.bdfserver.api.interaction.domains.AlbumDomain;
import fr.exemole.bdfserver.api.interaction.domains.CorpusDomain;
import fr.exemole.bdfserver.api.interaction.domains.MainDomain;
import fr.exemole.bdfserver.api.interaction.domains.MiscDomain;
import fr.exemole.bdfserver.api.interaction.domains.SphereDomain;
import fr.exemole.bdfserver.api.interaction.domains.ThesaurusDomain;
import net.fichotheque.permission.PermissionSummary;
import fr.exemole.bdfserver.api.subsettree.GroupNode;
import fr.exemole.bdfserver.api.subsettree.SubsetNode;
import fr.exemole.bdfserver.api.subsettree.SubsetTree;
import fr.exemole.bdfserver.commands.addenda.AddendaCreationCommand;
import fr.exemole.bdfserver.commands.album.AlbumCreationCommand;
import fr.exemole.bdfserver.commands.corpus.CorpusCreationCommand;
import fr.exemole.bdfserver.commands.sphere.SphereCreationCommand;
import fr.exemole.bdfserver.commands.thesaurus.ThesaurusCreationCommand;
import fr.exemole.bdfserver.html.BdfHtmlConstants;
import fr.exemole.bdfserver.html.BdfHtmlUtils;
import fr.exemole.bdfserver.html.BdfServerHtmlProducer;
import fr.exemole.bdfserver.html.consumers.Button;
import fr.exemole.bdfserver.html.consumers.SubsetIcon;
import fr.exemole.bdfserver.html.consumers.Tree;
import fr.exemole.bdfserver.html.consumers.attributes.Deploy;
import fr.exemole.bdfserver.html.jslib.BdfJsLibs;
import fr.exemole.bdfserver.tools.BH;
import fr.exemole.bdfserver.tools.subsettree.TreeFilterEngine;
import fr.exemole.bdfserver.tools.subsettree.TreeUtils;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import net.fichotheque.Subset;
import net.fichotheque.SubsetKey;
import net.fichotheque.corpus.Corpus;
import net.fichotheque.thesaurus.Thesaurus;
import net.fichotheque.utils.FichothequeUtils;
import net.mapeadores.util.html.HA;
import net.mapeadores.util.html.HtmlAttributes;
import net.mapeadores.util.html.HtmlPrinter;
import net.mapeadores.util.html.HtmlWrapper;
import net.mapeadores.util.text.Label;


/**
 *
 * @author Vincent Calame
 */
public class CollectionsHtmlProducer extends BdfServerHtmlProducer {

    private final static HtmlWrapper GROUP_BRANCH = Tree.branch("collections-Branch");
    private final static HtmlWrapper TREE = Tree.tree("collections-Tree");
    private final static HtmlWrapper SUBSET_LEAF = Tree.leaf("collections-SubsetLeaf");
    private final PermissionSummary permissionSummary;
    private final boolean isFichothequeAdmin;
    private final Button isoButton = Button.link();

    public CollectionsHtmlProducer(BdfParameters bdfParameters) {
        super(bdfParameters);
        this.permissionSummary = bdfParameters.getPermissionSummary();
        this.isFichothequeAdmin = permissionSummary.isFichothequeAdmin();
        addThemeCss("collections.css");
        addJsLib(BdfJsLibs.DEPLOY);
        setMainStorageKey(Domains.MAIN, MainDomain.COLLECTIONS_PAGE);
    }

    @Override
    public void printHtml() {
        start();
        this
                .__(printCorpusCategory())
                .__(printThesaurusCategory())
                .__(printSphereCategory())
                .__(printAlbumCategory())
                .__(printAddendaCategory())
                .__(printIso());
        end();
    }

    private boolean printCorpusCategory() {
        SubsetTree subsetTree = TreeFilterEngine.admin(permissionSummary, bdfServer.getTreeManager().getSubsetTree(SubsetKey.CATEGORY_CORPUS));
        int size = TreeUtils.size(subsetTree);
        if ((size == 0) && (!isFichothequeAdmin)) {
            return false;
        }
        String unitId = "unit_" + SubsetKey.CATEGORY_CORPUS_STRING;
        this
                .DETAILS(HA.id(unitId).classes("unit-Unit").populate(Deploy.DETAILS))
                .SUMMARY("collections-category-Summary family-CRP family-Colors")
                .__(printEntryTitle(SubsetKey.CATEGORY_CORPUS, size))
                .__((isFichothequeAdmin) ? printButton("action-New", BH.domain(Domains.CORPUS).page(CorpusDomain.CORPUS_CREATIONFORM_PAGE), CorpusCreationCommand.COMMANDKEY) : false)
                ._SUMMARY()
                .DIV("unit-Body")
                .__(new CollectionTree(subsetTree, unitId))
                ._DIV()
                ._DETAILS();
        return true;
    }

    private boolean printThesaurusCategory() {
        SubsetTree subsetTree = TreeFilterEngine.read(permissionSummary, bdfServer.getTreeManager().getSubsetTree(SubsetKey.CATEGORY_THESAURUS));
        int size = TreeUtils.size(subsetTree);
        if ((size == 0) && (!isFichothequeAdmin)) {
            return false;
        }
        String unitId = "unit_" + SubsetKey.CATEGORY_THESAURUS_STRING;
        this
                .DETAILS(HA.id(unitId).classes("unit-Unit").populate(Deploy.DETAILS))
                .SUMMARY("collections-category-Summary family-THS family-Colors")
                .__(printEntryTitle(SubsetKey.CATEGORY_THESAURUS, size))
                .__((isFichothequeAdmin) ? printButton("action-New", BH.domain(Domains.THESAURUS).page(ThesaurusDomain.THESAURUS_CREATIONFORM_PAGE), ThesaurusCreationCommand.COMMANDKEY) : false)
                ._SUMMARY()
                .DIV("unit-Body")
                .__(new CollectionTree(subsetTree, unitId))
                ._DIV()
                ._DETAILS();
        return true;
    }

    private boolean printSphereCategory() {
        SubsetTree subsetTree = TreeFilterEngine.read(permissionSummary, bdfServer.getTreeManager().getSubsetTree(SubsetKey.CATEGORY_SPHERE));
        int size = TreeUtils.size(subsetTree);
        if ((size == 0) && (!isFichothequeAdmin)) {
            return false;
        }
        String unitId = "unit_" + SubsetKey.CATEGORY_SPHERE_STRING;
        this
                .DETAILS(HA.id(unitId).classes("unit-Unit").populate(Deploy.DETAILS))
                .SUMMARY("collections-category-Summary family-SPH family-Colors")
                .__(printEntryTitle(SubsetKey.CATEGORY_SPHERE, size))
                .__((isFichothequeAdmin) ? printButton("action-New", BH.domain(Domains.SPHERE).page(SphereDomain.SPHERE_CREATIONFORM_PAGE), SphereCreationCommand.COMMANDKEY) : false)
                ._SUMMARY()
                .DIV("unit-Body")
                .__(new CollectionTree(subsetTree, unitId))
                ._DIV()
                ._DETAILS();
        return true;
    }

    private boolean printAlbumCategory() {
        SubsetTree subsetTree = TreeFilterEngine.read(permissionSummary, bdfServer.getTreeManager().getSubsetTree(SubsetKey.CATEGORY_ALBUM));
        int size = TreeUtils.size(subsetTree);
        if ((size == 0) && (!isFichothequeAdmin)) {
            return false;
        }
        String unitId = "unit_" + SubsetKey.CATEGORY_ALBUM_STRING;
        this
                .DETAILS(HA.id(unitId).classes("unit-Unit").populate(Deploy.DETAILS))
                .SUMMARY("collections-category-Summary family-ALB family-Colors")
                .__(printEntryTitle(SubsetKey.CATEGORY_ALBUM, size))
                .__((isFichothequeAdmin) ? printButton("action-New", BH.domain(Domains.ALBUM).page(AlbumDomain.ALBUM_CREATIONFORM_PAGE), AlbumCreationCommand.COMMANDKEY) : false)
                ._SUMMARY()
                .DIV("unit-Body")
                .__(new CollectionTree(subsetTree, unitId))
                ._DIV()
                ._DETAILS();
        return true;
    }

    private boolean printAddendaCategory() {
        SubsetTree subsetTree = TreeFilterEngine.read(permissionSummary, bdfServer.getTreeManager().getSubsetTree(SubsetKey.CATEGORY_ADDENDA));
        int size = TreeUtils.size(subsetTree);
        if ((size == 0) && (!isFichothequeAdmin)) {
            return false;
        }
        String unitId = "unit_" + SubsetKey.CATEGORY_ADDENDA_STRING;
        this
                .DETAILS(HA.id(unitId).classes("unit-Unit").populate(Deploy.DETAILS))
                .SUMMARY("collections-category-Summary family-ADD family-Colors")
                .__(printEntryTitle(SubsetKey.CATEGORY_ADDENDA, size))
                .__((isFichothequeAdmin) ? printButton("action-New", BH.domain(Domains.ADDENDA).page(AddendaDomain.ADDENDA_CREATIONFORM_PAGE), AddendaCreationCommand.COMMANDKEY) : false)
                ._SUMMARY()
                .DIV("unit-Body")
                .__(new CollectionTree(subsetTree, unitId))
                ._DIV()
                ._DETAILS();
        return true;
    }


    private boolean printIso() {
        String isoId = "unit_iso";
        this
                .DETAILS(HA.id(isoId).classes("collections-iso-Unit").populate(Deploy.DETAILS))
                .SUMMARY("collections-iso-Head")
                .__(SubsetIcon.ISO)
                .SPAN("collections-category-Title")
                .__localize("_ title.global.iso_collection")
                ._SPAN()
                ._SUMMARY()
                .DIV("collections-iso-Body")
                .__(isoLink("action-List_Lang", MiscDomain.ISO_LANGUAGES_PAGE, "_ title.misc.lang_list"))
                .__(isoLink("action-List_Country", MiscDomain.ISO_COUNTRIES_PAGE, "_ title.misc.country_list"))
                ._DIV()
                ._DETAILS();
        return true;
    }

    private boolean printEntryTitle(short subsetCategory, int size) {
        this
                .__(SubsetIcon.getIcon(subsetCategory))
                .SPAN("collections-category-Title")
                .__localize(BdfHtmlUtils.getSubsetCollectionLocKey(subsetCategory))
                .__space()
                .__(BdfHtmlUtils.printItemCount(this, bdfUser, size))
                ._SPAN();
        return true;
    }


    private boolean printButton(String action, CharSequence href, String titleLocKey) {
        /* Disposition différente des autres boutons à cause d'un problème dans Chrome quand le lien est dans un élement <summary>*/
        this
                .SPAN(action)
                .A(HA.href(href).target(BdfHtmlConstants.EDITION_FRAME).titleLocKey(titleLocKey).classes("global-button-Transparent global-button-Icon"))
                ._A()
                ._SPAN();
        return true;
    }

    private Button isoLink(String action, String page, String messageKey) {
        String href = BH.domain(Domains.MISC).page(page).toString();
        return isoButton.href(href).action(action).textL10nObject(messageKey);
    }


    private class CollectionTree implements Consumer<HtmlPrinter> {

        private final String deployPrefix;
        private final SubsetTree subsetTree;
        private final GroupBranch groupBranch = new GroupBranch();
        private final SubsetLi subsetLi = new SubsetLi();

        private CollectionTree(SubsetTree subsetTree, String deployPrefix) {
            this.subsetTree = subsetTree;
            this.deployPrefix = deployPrefix;
        }

        @Override
        public void accept(HtmlPrinter hp) {
            hp.__(TREE, () -> {
                for (SubsetTree.Node node : subsetTree.getNodeList()) {
                    if (node instanceof SubsetNode) {
                        printSubsetNode(hp, (SubsetNode) node);
                    } else if (node instanceof GroupNode) {
                        hp.__(groupBranch, node);
                    }
                }
            });
        }

        private boolean printSubsetNode(HtmlPrinter hp, SubsetNode subsetNode) {
            Subset subset = fichotheque.getSubset(subsetNode.getSubsetKey());
            if (subset == null) {
                return false;
            }
            hp.__(subsetLi, subset);
            return true;
        }


        private class GroupBranch implements BiConsumer<HtmlPrinter, Object> {

            private GroupBranch() {

            }

            @Override
            public void accept(HtmlPrinter hp, Object object) {
                GroupNode groupNode = (GroupNode) object;
                String groupId = deployPrefix + "-" + groupNode.getName();
                hp.__(Tree.NODE, () -> {
                    hp
                            .DETAILS(HA.id(groupId).classes("collections-Group").populate(Deploy.DETAILS))
                            .SUMMARY()
                            .__escape(TreeUtils.getTitle(bdfServer, groupNode, workingLang))
                            ._SUMMARY()
                            .__(GROUP_BRANCH, () -> {
                                for (SubsetTree.Node subnode : groupNode.getSubnodeList()) {
                                    if (subnode instanceof SubsetNode) {
                                        printSubsetNode(hp, (SubsetNode) subnode);
                                    } else if (subnode instanceof GroupNode) {
                                        hp.__(this, subnode);
                                    }
                                }
                            });
                });
            }


        }


        private class SubsetLi implements BiConsumer<HtmlPrinter, Object> {

            private SubsetLi() {

            }

            @Override
            public void accept(HtmlPrinter hp, Object object) {
                Subset subset = (Subset) object;
                short category = subset.getSubsetKey().getCategory();
                hp.__(SUBSET_LEAF, () -> {
                    hp
                            .__(printSubsetLink(hp, subset, category));
                    if (category == SubsetKey.CATEGORY_CORPUS) {
                        Corpus corpus = (Corpus) subset;
                        Subset masterSubset = corpus.getMasterSubset();
                        if (masterSubset != null) {
                            String masterTitle;
                            if (permissionSummary.isSubsetAdmin(masterSubset.getSubsetKey())) {
                                masterTitle = FichothequeUtils.getTitleWithKey(masterSubset, workingLang);
                            } else {
                                masterTitle = FichothequeUtils.getTitle(masterSubset, workingLang);
                            }
                            String locKey;
                            if (masterSubset instanceof Thesaurus) {
                                locKey = "_ info.corpus.thesaurusmaster";
                            } else {
                                locKey = "_ info.corpus.corpusmaster";
                            }
                            hp
                                    .DIV("collections-MasterInfo")
                                    .__localize(locKey, masterTitle)
                                    ._DIV();
                        }
                    }
                });
            }

            private boolean printSubsetLink(HtmlPrinter hp, Subset currentSubset, short currentCategory) {
                HtmlAttributes attr = HA.href(BH.domain(BdfHtmlUtils.getDomain(currentCategory)).subset(currentSubset).page(BdfHtmlUtils.getPage(currentCategory))).classes("collections-SubsetLink");
                SubsetKey subsetKey = currentSubset.getSubsetKey();
                if ((subsetKey.isSphereSubset()) || (permissionSummary.isSubsetAdmin(subsetKey))) {
                    Label label = FichothequeUtils.getTitleLabel(currentSubset, workingLang);
                    if (label != null) {
                        hp
                                .A(attr)
                                .__(SubsetIcon.getIcon(currentCategory))
                                .__escape(label.getLabelString())
                                .__space()
                                .SPAN("collections-SubsetKey")
                                .__escape("[")
                                .__escape(subsetKey.getSubsetName())
                                .__escape("]")
                                ._SPAN()
                                .__space()
                                .__(BdfHtmlUtils.printItemCount(hp, bdfUser, currentSubset.size()))
                                ._A();
                    } else {
                        hp
                                .A(attr)
                                .__(SubsetIcon.getIcon(currentCategory))
                                .__escape("[")
                                .__escape(subsetKey.getSubsetName())
                                .__escape("]")
                                .__space()
                                .__(BdfHtmlUtils.printItemCount(hp, bdfUser, currentSubset.size()))
                                ._A();
                    }
                } else {
                    hp
                            .A(attr)
                            .__(SubsetIcon.getIcon(currentCategory))
                            .__escape(FichothequeUtils.getTitle(currentSubset, workingLang))
                            .__space()
                            .__(BdfHtmlUtils.printItemCount(hp, bdfUser, currentSubset.size()))
                            ._A();
                }
                return true;
            }

        }

    }

}
