/* BdfServer - Copyright (c) 2013-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 net.fichotheque.tools.exportation.transformation;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import net.fichotheque.exportation.transformation.TemplateContentDescription;
import net.fichotheque.exportation.transformation.TemplateDef;
import net.fichotheque.exportation.transformation.TemplateDescription;
import net.fichotheque.utils.TransformationUtils;
import net.mapeadores.util.localisation.LocalisationUtils;
import net.mapeadores.util.localisation.Message;
import net.mapeadores.util.logging.MessageHandler;


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

    private final static List<Message> EMPTY_MESSAGELIST = Collections.emptyList();
    private final static List<TemplateContentDescription> EMPTY_CONTENTLIST = Collections.emptyList();
    private final InternalMessageHandler messageHandler = new InternalMessageHandler();
    private final TemplateDef templateDef;
    private final String type;
    private final List<Message> errorList = new ArrayList<Message>();
    private final List<Message> warningList = new ArrayList<Message>();
    private final List<TemplateContentDescription> templateContentDescriptionList = new ArrayList<TemplateContentDescription>();

    public TemplateDescriptionBuilder(TemplateDef templateDef, String type) {
        if (templateDef == null) {
            throw new IllegalArgumentException("templateDef is null");
        }
        if (templateDef.getTemplateKey().isDist()) {
            throw new IllegalArgumentException("templateDef.getTemplateKey() is dist key");
        }
        if (type == null) {
            throw new IllegalArgumentException("type is null");
        }
        this.templateDef = templateDef;
        this.type = type;
    }

    public MessageHandler getMessageHandler() {
        return messageHandler;
    }

    public TemplateDescriptionBuilder addTemplateContentDescription(TemplateContentDescription templateContentDescription) {
        templateContentDescriptionList.add(templateContentDescription);
        return this;
    }

    public TemplateDescriptionBuilder addAll(List<TemplateContentDescription> list) {
        templateContentDescriptionList.addAll(list);
        return this;
    }

    public TemplateDescription toTemplateDescription() {
        String state = checkState();
        List<Message> finalErrorList = LocalisationUtils.wrap(errorList.toArray(new Message[errorList.size()]));
        List<Message> finalWarningList = LocalisationUtils.wrap(warningList.toArray(new Message[warningList.size()]));
        List<TemplateContentDescription> finalTemplateContentDescriptionList = TransformationUtils.wrap(templateContentDescriptionList.toArray(new TemplateContentDescription[templateContentDescriptionList.size()]));
        return new InternalTemplateDescription(templateDef, type, state, finalErrorList, finalWarningList, finalTemplateContentDescriptionList);
    }

    private String checkState() {
        if (!errorList.isEmpty()) {
            return TemplateDescription.ERROR_STATE;
        }
        boolean withWarning = (!warningList.isEmpty());
        for (TemplateContentDescription templateContentDescription : templateContentDescriptionList) {
            String contentState = templateContentDescription.getState();
            if (!contentState.equals(TemplateContentDescription.OK_STATE)) {
                if (templateContentDescription.isMandatory()) {
                    return TemplateDescription.ERROR_STATE;
                } else {
                    withWarning = true;
                }
            }
        }
        if (withWarning) {
            return TemplateDescription.WITH_WARNINGS_STATE;
        } else {
            return TemplateDescription.OK_STATE;
        }
    }

    public static TemplateDescriptionBuilder init(TemplateDef templateDef, String type) {
        return new TemplateDescriptionBuilder(templateDef, type);
    }

    public static TemplateDescription buildUnknownType(TemplateDef templateDef, String type) {
        List<Message> errorList = Collections.singletonList(LocalisationUtils.toMessage("_ error.unknown.transformation.templatetype", type));
        return new InternalTemplateDescription(templateDef, type, TemplateDescription.UNKNOWN_TEMPLATE_TYPE_STATE, errorList, EMPTY_MESSAGELIST, EMPTY_CONTENTLIST);
    }


    private class InternalMessageHandler implements MessageHandler {

        private InternalMessageHandler() {

        }

        @Override
        public void addMessage(String category, Message message) {
            if (category.contains("warning")) {
                warningList.add(message);
            } else {
                errorList.add(message);
            }
        }

    }


    private static class InternalTemplateDescription implements TemplateDescription {

        private final TemplateDef templateDef;
        private final String type;
        private final String state;
        private final List<Message> errorList;
        private final List<Message> warningList;
        private final List<TemplateContentDescription> templateContentDescriptionList;

        private InternalTemplateDescription(TemplateDef templateDef, String type, String state,
                List<Message> errorList, List<Message> warningList, List<TemplateContentDescription> templateContentDescriptionList) {
            this.templateDef = templateDef;
            this.type = type;
            this.state = state;
            this.errorList = errorList;
            this.warningList = warningList;
            this.templateContentDescriptionList = templateContentDescriptionList;
        }

        @Override
        public TemplateDef getTemplateDef() {
            return templateDef;
        }

        @Override
        public String getState() {
            return state;
        }

        @Override
        public String getType() {
            return type;
        }

        @Override
        public List<Message> getErrorMessageList() {
            return errorList;
        }


        @Override
        public List<Message> getWarningMessageList() {
            return warningList;
        }

        @Override
        public List<TemplateContentDescription> getTemplateContentDescriptionList() {
            return templateContentDescriptionList;
        }

    }

}
