/* BdfServer - 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 fr.exemole.bdfserver.storage.directory.oldversions;

import fr.exemole.bdfserver.api.BdfServerEditor;
import fr.exemole.bdfserver.tools.policies.UserAllowBuilder;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import net.fichotheque.Fichotheque;
import net.fichotheque.SubsetKey;
import net.fichotheque.thesaurus.Thesaurus;
import net.fichotheque.thesaurus.policies.DynamicEditPolicy;
import net.fichotheque.tools.thesaurus.DynamicEditPolicyBuilder;
import net.fichotheque.utils.ThesaurusUtils;
import net.mapeadores.util.logging.MessageHandler;
import net.mapeadores.util.xml.DOMUtils;
import net.mapeadores.util.xml.DomMessages;
import org.w3c.dom.Element;


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

    private final MessageHandler messageHandler;
    private BdfServerEditor bdfServerEditor;

    public PolicyManagerDOMReader(BdfServerEditor bdfServerEditor, MessageHandler messageHandler) {
        this.bdfServerEditor = bdfServerEditor;
        this.messageHandler = messageHandler;
    }

    public void readPolicyManager(Element element) {
        DOMUtils.readChildren(element, new RootConsumer());
    }


    private class RootConsumer implements Consumer<Element> {

        private RootConsumer() {
        }

        @Override
        public void accept(Element element) {
            String tagName = element.getTagName();
            if (tagName.equals("thesaurus-policy-list")) {
                DOMUtils.readChildren(element, new ThesaurusPolicyListConsumer());
            } else if (tagName.equals("user-allow-policy")) {
                UserAllowBuilder userAllowBuilder = new UserAllowBuilder();
                DOMUtils.readChildren(element, new UserAllowPolicyConsumer(userAllowBuilder));
                bdfServerEditor.setUserAllow(userAllowBuilder.toUserAllow());
            } else {
                DomMessages.unknownTagWarning(messageHandler, tagName);
            }
        }

    }


    private class UserAllowPolicyConsumer implements Consumer<Element> {

        private final UserAllowBuilder userAllowBuilder;

        private UserAllowPolicyConsumer(UserAllowBuilder userAllowBuilder) {
            this.userAllowBuilder = userAllowBuilder;

        }

        @Override
        public void accept(Element element) {
            String tagName = element.getTagName();
            if (tagName.equals("data")) {
                userAllowBuilder.setDataChangeAllowed(true);
            } else if (tagName.equals("password")) {
                userAllowBuilder.setPasswordChangeAllowed(true);
            } else {
                DomMessages.unknownTagWarning(messageHandler, tagName);
            }
        }

    }


    private class ThesaurusPolicyListConsumer implements Consumer<Element> {

        private final Fichotheque fichotheque;

        private ThesaurusPolicyListConsumer() {
            this.fichotheque = bdfServerEditor.getBdfServer().getFichotheque();
        }

        @Override
        public void accept(Element element) {
            String tagName = element.getTagName();
            if (tagName.equals("thesaurus-policy")) {
                String name = element.getAttribute("thesaurus-name");
                SubsetKey subsetKey;
                try {
                    subsetKey = SubsetKey.parse(SubsetKey.CATEGORY_THESAURUS, name);
                } catch (ParseException pe) {
                    return;
                }
                Thesaurus thesaurus = (Thesaurus) fichotheque.getSubset(subsetKey);
                if (thesaurus == null) {
                    return;
                }
                String type = element.getAttribute("type");
                if (type.length() == 0) {
                    type = element.getAttribute("ajout");
                }
                if (type.length() == 0) {
                    DomMessages.emptyAttribute(messageHandler, element.getTagName(), "type");
                    return;
                }
                List<SubsetKey> subsetKeyList = getSubsetKeyList(element);
                int size = subsetKeyList.size();
                DynamicEditPolicy policy;
                switch (type) {
                    case "none":
                        policy = ThesaurusUtils.NONE_POLICY;
                        break;
                    case "allow":
                        policy = ThesaurusUtils.ALLOW_POLICY;
                        break;
                    case "transfer":
                        if (size == 0) {
                            policy = ThesaurusUtils.NONE_POLICY;
                        } else {
                            policy = DynamicEditPolicyBuilder.buildTransfer(subsetKeyList.get(0));
                        }
                        break;
                    case "check":
                    case "verif":
                        if (size == 0) {
                            policy = ThesaurusUtils.ALLOW_POLICY;
                        } else {
                            policy = DynamicEditPolicyBuilder.buildCheck(subsetKeyList);
                        }
                        break;
                    default:
                        DomMessages.wrongAttributeValue(messageHandler, element.getTagName(), "type", type);
                        return;
                }
                bdfServerEditor.setSubsetPolicy(subsetKey, policy);
            } else {
                DomMessages.unknownTagWarning(messageHandler, tagName);
            }
        }

        private List<SubsetKey> getSubsetKeyList(Element element) {
            ThesaurusConsumer thesaurusConsumer = new ThesaurusConsumer(fichotheque);
            DOMUtils.readChildren(element, thesaurusConsumer);
            return thesaurusConsumer.getThesaurusList();
        }

    }


    private class ThesaurusConsumer implements Consumer<Element> {

        private final List<SubsetKey> thesaurusList = new ArrayList<SubsetKey>();
        private final Fichotheque fichotheque;

        private ThesaurusConsumer(Fichotheque fichotheque) {
            this.fichotheque = fichotheque;
        }

        @Override
        public void accept(Element element) {
            String tagName = element.getTagName();
            if (tagName.equals("thesaurus")) {
                String name = DOMUtils.readSimpleElement(element);
                if (name.length() > 0) {
                    try {
                        SubsetKey subsetKey = SubsetKey.parse(SubsetKey.CATEGORY_THESAURUS, name);
                        if (fichotheque.containsSubset(subsetKey)) {
                            thesaurusList.add(subsetKey);
                        }
                    } catch (ParseException pe) {
                    }

                }
            } else {
                DomMessages.unknownTagWarning(messageHandler, tagName);
            }
        }

        public List<SubsetKey> getThesaurusList() {
            return thesaurusList;
        }

    }

}
