/* FichothequeLib_Tools - Copyright (c) 2020-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.parsers;

import net.fichotheque.externalsource.ExternalSource;
import net.fichotheque.thesaurus.Motcle;
import net.fichotheque.thesaurus.Thesaurus;
import net.fichotheque.thesaurus.policies.DynamicEditPolicy;
import net.fichotheque.thesaurus.policies.PolicyProvider;
import net.fichotheque.tools.parsers.croisement.WeightMotcleToken;
import net.fichotheque.utils.ThesaurusUtils;
import net.mapeadores.util.text.CleanedString;


/**
 *
 * @author Vincent Calame
 */
final class DynamicEditFactory {

    private DynamicEditFactory() {

    }

    static DynamicEdit newInstance(DynamicEdit.Parameters parameters) {
        PolicyProvider policyProvider = parameters.getParseContext().getPolicyProvider();
        if (policyProvider == null) {
            return null;
        }
        DynamicEditPolicy dynamicEditPolicy = policyProvider.getDynamicEditPolicy(parameters.getMainThesaurus());
        boolean withIdalpha = parameters.getMainThesaurus().isIdalphaType();
        if (dynamicEditPolicy instanceof DynamicEditPolicy.Allow) {
            if (withIdalpha) {
                return null;
            } else {
                return new Allow(parameters);
            }
        } else if (dynamicEditPolicy instanceof DynamicEditPolicy.Transfer) {
            if (withIdalpha) {
                return null;
            } else {
                return new Transfer(parameters, (DynamicEditPolicy.Transfer) dynamicEditPolicy);
            }
        } else if (dynamicEditPolicy instanceof DynamicEditPolicy.Check) {
            if (withIdalpha) {
                return null;
            } else {
                return new Check(parameters, (DynamicEditPolicy.Check) dynamicEditPolicy);
            }
        } else if (dynamicEditPolicy instanceof DynamicEditPolicy.External) {
            ExternalSource externalSource = parameters.getParseContext().getExternalSourceProvider().getExternalSource(((DynamicEditPolicy.External) dynamicEditPolicy).getExternalSourceDef());
            if (externalSource != null) {
                return new External(parameters, externalSource);
            } else {
                return null;
            }
        } else {
            return null;
        }
    }


    private static class Allow extends DynamicEdit {

        Allow(DynamicEdit.Parameters parameters) {
            super(parameters);
        }

        @Override
        public void editToken(WeightMotcleToken motcleToken) {
            if (motcleToken.isIdBundle()) {
                return;
            }
            Motcle motcle = createMotcle(motcleToken.getText());
            createLien(motcle, motcleToken.getWeight());
        }

    }


    private static class Transfer extends DynamicEdit {

        private final DynamicEditPolicy.Transfer transferPolicy;

        Transfer(DynamicEdit.Parameters parameters, DynamicEditPolicy.Transfer transferPolicy) {
            super(parameters);
            this.transferPolicy = transferPolicy;
        }

        @Override
        public void editToken(WeightMotcleToken motcleToken) {
            if (motcleToken.isIdBundle()) {
                return;
            }
            CleanedString labelText = motcleToken.getText();
            Thesaurus transferThesaurus = ThesaurusUtils.getTransferThesaurus(parseContext.getFichotheque(), transferPolicy);
            Motcle transferMotcle = getMotcle(transferThesaurus, labelText);
            if (transferMotcle == null) {
                transferMotcle = createMotcle(transferThesaurus, labelText);
            }
            appendLien(transferMotcle, motcleToken.getWeight());
        }

    }


    private static class Check extends DynamicEdit {

        private final DynamicEditPolicy.Check checkPolicy;

        Check(DynamicEdit.Parameters parameters, DynamicEditPolicy.Check checkPolicy) {
            super(parameters);
            this.checkPolicy = checkPolicy;
        }

        @Override
        public void editToken(WeightMotcleToken motcleToken) {
            if (motcleToken.isIdBundle()) {
                return;
            }
            CleanedString labelText = motcleToken.getText();
            Thesaurus[] checkThesaurusArray = ThesaurusUtils.getCheckThesaurusArray(parseContext.getFichotheque(), checkPolicy);
            boolean done = false;
            for (Thesaurus checkThesaurus : checkThesaurusArray) {
                Motcle checkMotcle = getMotcle(checkThesaurus, labelText);
                if (checkMotcle != null) {
                    appendLien(checkMotcle, motcleToken.getWeight());
                    done = true;
                    break;
                }
            }
            if (!done) {
                Motcle motcle = createMotcle(labelText);
                createLien(motcle, motcleToken.getWeight());
            }

        }

    }


    private static class External extends DynamicEdit {

        private final ExternalSource externalSource;

        External(DynamicEdit.Parameters parameters, ExternalSource externalSource) {
            super(parameters);
            this.externalSource = externalSource;
        }

        @Override
        public void editToken(WeightMotcleToken motcleToken) {
            Motcle newMotcle;
            if (motcleToken.isIdBundle()) {
                newMotcle = externalSource.getMotcle(parameters.getParseContext().getFichothequeEditor(), parameters.getMainThesaurus(), motcleToken.getId());
            } else {
                newMotcle = externalSource.getMotcle(parameters.getParseContext().getFichothequeEditor(), parameters.getMainThesaurus(), motcleToken.getText().toString(), parameters.getLang());
            }
            if (newMotcle != null) {
                createLien(newMotcle, motcleToken.getWeight());
            }
        }

    }


}
