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

import fr.exemole.bdfserver.api.instruction.OutputParameters;
import fr.exemole.bdfserver.api.interaction.domains.PiocheDomain;
import fr.exemole.bdfserver.html.BdfServerHtmlProducer;
import fr.exemole.bdfserver.tools.externalsource.ExternalSourceUtils;
import fr.exemole.bdfserver.tools.instruction.BdfErrors;
import fr.exemole.bdfserver.tools.instruction.OutputRequestHandler;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import net.fichotheque.Subset;
import net.fichotheque.SubsetKey;
import net.fichotheque.externalsource.ExternalSource;
import net.fichotheque.thesaurus.Thesaurus;
import net.mapeadores.util.logging.CommandMessageBuilder;
import net.mapeadores.util.logging.ErrorMessageException;
import net.mapeadores.util.primitives.DegreDecimal;
import net.mapeadores.util.text.StringUtils;


/**
 *
 * @author Vincent Calame
 */
public final class PiocheHtmlProducerFactory {

    private PiocheHtmlProducerFactory() {
    }

    public static BdfServerHtmlProducer getHtmlProducer(OutputParameters parameters) throws ErrorMessageException {
        OutputRequestHandler requestHandler = OutputRequestHandler.init(parameters);
        String page = parameters.getOutput();
        switch (page) {
            case PiocheDomain.EXTERNALSOURCE_PAGE: {
                return new ExternalSourceHtmlProducer(parameters, getExternalSourceParameters(requestHandler));
            }
            case PiocheDomain.DOCUMENT_PAGE: {
                return new DocumentPiocheHtmlProducer(parameters, getDocumentParameters(requestHandler));
            }
            case PiocheDomain.GEOCODAGE_PAGE: {
                return new GeocodageHtmlProducer(parameters, getGeocodageParameters(requestHandler));
            }
            case PiocheDomain.FICHE_PAGE: {
                return new FichePiocheHtmlProducer(parameters, getFicheParameters(requestHandler));
            }
            case PiocheDomain.MOTCLE_PAGE: {
                return new MotclePiocheHtmlProducer(parameters, getMotcleParameters(requestHandler));
            }
            case PiocheDomain.USER_PAGE: {
                return new UserPiocheHtmlProducer(parameters, getRedacteurParameters(requestHandler));
            }
            case PiocheDomain.LANGUAGE_PAGE: {
                return new LanguagePiocheHtmlProducer(parameters, getParameters(requestHandler));
            }
            case PiocheDomain.COUNTRY_PAGE: {
                return new CountryPiocheHtmlProducer(parameters, getParameters(requestHandler));
            }
            case PiocheDomain.FIELD_PAGE: {
                return new FieldPiocheHtmlProducer(parameters, getFieldParameters(requestHandler));
            }
            default:
                return null;
        }
    }

    private static PiocheParameters getParameters(OutputRequestHandler requestHandler) throws ErrorMessageException {
        String appelant = requestHandler.getMandatoryParameter(PiocheDomain.APPELANT_PARAMNAME);
        int limit = getLimit(requestHandler);
        return PiocheParameters.init()
                .setAppelant(appelant)
                .setLimit(limit);
    }

    private static PiocheParameters getFieldParameters(OutputRequestHandler requestHandler) throws ErrorMessageException {
        String appelant = requestHandler.getMandatoryParameter(PiocheDomain.APPELANT_PARAMNAME);
        int limit = getLimit(requestHandler);
        return PiocheParameters.init()
                .setAppelant(appelant)
                .setLimit(limit)
                .putParameter(PiocheParameters.FIELDTYPE, requestHandler.getTrimedParameter(PiocheDomain.FIELDTYPE_PARAMNAME));
    }

    private static PiocheParameters getGeocodageParameters(OutputRequestHandler requestHandler) throws ErrorMessageException {
        String appelant = requestHandler.getMandatoryParameter(PiocheDomain.APPELANT_PARAMNAME);
        String latString = requestHandler.getMandatoryParameter(PiocheDomain.LAT_PARAMNAME).trim();
        String lonString = requestHandler.getMandatoryParameter(PiocheDomain.LON_PARAMNAME).trim();
        DegreDecimal latDecimal = null;
        DegreDecimal lonDecimal = null;
        if ((latString.length() > 0) && (lonString.length() > 0)) {
            CommandMessageBuilder commandMessageBuilder = new CommandMessageBuilder();
            try {
                latDecimal = DegreDecimal.newInstance(StringUtils.parseDecimal(latString));
            } catch (NumberFormatException nfe) {
                commandMessageBuilder.addMultiError("_ error.wrong.geopoint_lat", latString);
            }
            try {
                lonDecimal = DegreDecimal.newInstance(StringUtils.parseDecimal(lonString));
            } catch (NumberFormatException nfe) {
                commandMessageBuilder.addMultiError("_ error.wrong.geopoint_lon", lonString);
            }
            if (commandMessageBuilder.hasMultiError()) {
                throw BdfErrors.error(commandMessageBuilder, "_ error.wrong.geopoint");
            }
        }
        return PiocheParameters.init()
                .setAppelant(appelant)
                .putParameter(PiocheParameters.LAT, latDecimal)
                .putParameter(PiocheParameters.LON, lonDecimal)
                .putParameter(PiocheParameters.ADDRESSFIELDS, requestHandler.getTrimedParameter(PiocheDomain.ADDRESSFIELDS_PARAMNAME))
                .putParameter(PiocheParameters.ZOOM, requestHandler.getTrimedParameter(PiocheDomain.ZOOM_PARAMNAME))
                .putParameter(PiocheParameters.NOCURRENT, requestHandler.isTrue(PiocheDomain.NOCURRENT_PARAMNAME));
    }

    private static PiocheParameters getFicheParameters(OutputRequestHandler requestHandler) throws ErrorMessageException {
        String appelant = requestHandler.getMandatoryParameter(PiocheDomain.APPELANT_PARAMNAME);
        int limit = getLimit(requestHandler);
        return PiocheParameters.init()
                .setAppelant(appelant)
                .setLimit(limit)
                .setSubsetList(getSubsetList(requestHandler, SubsetKey.CATEGORY_CORPUS))
                .putParameter(PiocheParameters.BUTTONS, requestHandler.getTrimedParameter(PiocheDomain.BUTTONS_PARAMNAME));
    }

    private static PiocheParameters getMotcleParameters(OutputRequestHandler requestHandler) throws ErrorMessageException {
        String appelant = requestHandler.getMandatoryParameter(PiocheDomain.APPELANT_PARAMNAME);
        int limit = getLimit(requestHandler);
        return PiocheParameters.init()
                .setAppelant(appelant)
                .setLimit(limit)
                .setSubsetList(getSubsetList(requestHandler, SubsetKey.CATEGORY_THESAURUS))
                .putParameter(PiocheParameters.CROISEMENT, getCroisementSubsetKey(requestHandler))
                .putParameter(PiocheParameters.WANTED, requestHandler.getTrimedParameter(PiocheDomain.WANTED_PARAMNAME));
    }

    private static PiocheParameters getDocumentParameters(OutputRequestHandler requestHandler) throws ErrorMessageException {
        String appelant = requestHandler.getMandatoryParameter(PiocheDomain.APPELANT_PARAMNAME);
        int limit = getLimit(requestHandler);
        return PiocheParameters.init()
                .setAppelant(appelant)
                .setLimit(limit)
                .setSubsetList(getSubsetList(requestHandler, SubsetKey.CATEGORY_ADDENDA));
    }

    private static PiocheParameters getExternalSourceParameters(OutputRequestHandler requestHandler) throws ErrorMessageException {
        String appelant = requestHandler.getMandatoryParameter(PiocheDomain.APPELANT_PARAMNAME);
        int limit = getLimit(requestHandler);
        List<Subset> thesaurusList = getSubsetList(requestHandler, SubsetKey.CATEGORY_THESAURUS);
        if (thesaurusList == null) {
            throw BdfErrors.emptyMandatoryParameter(PiocheDomain.SUBSETS_PARAMNAME);
        }
        ExternalSource externalSource = ExternalSourceUtils.getExternalSource(requestHandler.getBdfServer(), (Thesaurus) thesaurusList.get(0));
        if (externalSource == null) {
            throw BdfErrors.wrongParameterValue(PiocheDomain.SUBSETS_PARAMNAME, requestHandler.getMandatoryParameter(PiocheDomain.SUBSETS_PARAMNAME));
        }
        return PiocheParameters.init()
                .setAppelant(appelant)
                .setLimit(limit)
                .setSubsetList(thesaurusList)
                .putParameter(PiocheParameters.EXTERNALSOURCE, externalSource)
                .putParameter(PiocheParameters.CROISEMENT, getCroisementSubsetKey(requestHandler));
    }

    private static PiocheParameters getRedacteurParameters(OutputRequestHandler requestHandler) throws ErrorMessageException {
        String appelant = requestHandler.getMandatoryParameter(PiocheDomain.APPELANT_PARAMNAME);
        int limit = getLimit(requestHandler);
        return PiocheParameters.init()
                .setAppelant(appelant)
                .setLimit(limit)
                .setSubsetList(getSubsetList(requestHandler, SubsetKey.CATEGORY_SPHERE))
                .putParameter(PiocheParameters.DEFAULTSPHEREKEY, getDefaultSphereKey(requestHandler));
    }

    private static int getLimit(OutputRequestHandler requestHandler) throws ErrorMessageException {
        String limitString = requestHandler.getTrimedParameter(PiocheDomain.LIMIT_PARAMNAME);
        int limit = 5;
        if (!limitString.isEmpty()) {
            try {
                limit = Integer.parseInt(limitString);
                if (limit < 1) {
                    limit = 5;
                }
            } catch (NumberFormatException nfe) {
            }
        }
        return limit;
    }

    private static SubsetKey getDefaultSphereKey(OutputRequestHandler requestHandler) throws ErrorMessageException {
        String defaultsphereParam = requestHandler.getTrimedParameter(PiocheDomain.DEFAULSPHERE_PARAMNAME);
        if (defaultsphereParam.isEmpty()) {
            return null;
        }
        try {
            SubsetKey sphereKey = SubsetKey.parse(defaultsphereParam);
            if (sphereKey.isSphereSubset()) {
                return sphereKey;
            } else {
                return null;
            }
        } catch (java.text.ParseException pe) {
            return null;
        }
    }

    private static List<Subset> getSubsetList(OutputRequestHandler requestHandler, short category) throws ErrorMessageException {
        String subsetsParam = requestHandler.getMandatoryParameter(PiocheDomain.SUBSETS_PARAMNAME);
        if (subsetsParam.length() == 0) {
            return null;
        } else {
            String[] array = StringUtils.getTechnicalTokens(subsetsParam, true);
            ArrayList<Subset> subsetList = new ArrayList<Subset>();
            for (String name : array) {
                try {
                    SubsetKey subsetKey = SubsetKey.parse(category, name);
                    Subset subset = requestHandler.getFichotheque().getSubset(subsetKey);
                    if (subset != null) {
                        subsetList.add(subset);
                    }
                } catch (ParseException pe) {

                }
            }
            if (subsetList.isEmpty()) {
                throw BdfErrors.wrongParameterValue(PiocheDomain.SUBSETS_PARAMNAME, subsetsParam);
            }
            return subsetList;
        }
    }

    private static SubsetKey getCroisementSubsetKey(OutputRequestHandler requestHandler) throws ErrorMessageException {
        String subsetString = requestHandler.getTrimedParameter(PiocheDomain.CROISEMENT_PARAMNAME);
        if (subsetString.isEmpty()) {
            return null;
        }
        try {
            SubsetKey subsetKey = SubsetKey.parse(subsetString);
            return subsetKey;
        } catch (ParseException pe) {
            throw BdfErrors.wrongParameterValue(PiocheDomain.CROISEMENT_PARAMNAME, subsetString);
        }
    }

}
