/* BdfServer_Html - Copyright (c) 2015-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 fr.exemole.bdfserver.html.forms;

import java.util.ArrayList;
import java.util.List;
import net.fichotheque.FichothequeConstants;
import net.fichotheque.thesaurus.Motcle;
import net.fichotheque.thesaurus.Thesaurus;
import net.mapeadores.util.attr.Attribute;
import net.mapeadores.util.html.HA;
import net.mapeadores.util.html.HtmlAttributes;
import net.mapeadores.util.html.HtmlPrinter;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.text.Label;
import fr.exemole.bdfserver.api.ficheform.include.ThesaurusEntry;


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

    public final static int DASH_IDALPHASTYLE = 1;
    public final static int BRACKETS_IDALPHASTYLE = 2;
    public final static int IGNORE_IDALPHASTYLE = 3;
    private final String value;
    private final String labelText;
    private final boolean selected;
    private final int depth;
    private final boolean shouldNotUse;
    private final boolean group;
    private final List<InputItem> childList = new ArrayList<InputItem>();

    public InputItem(String value, String labelText, boolean selected, int depth, boolean shouldNotUse, boolean group) {
        this.value = value;
        this.labelText = labelText;
        this.selected = selected;
        this.depth = depth;
        this.shouldNotUse = shouldNotUse;
        this.group = group;
    }

    public String getValue() {
        return value;
    }

    public String getLabelText() {
        return labelText;
    }

    public boolean isSelected() {
        return selected;
    }

    public int getDepth() {
        return depth;
    }

    public boolean isGroup() {
        return (group) && (shouldNotUse) && (!selected);
    }

    public boolean isShouldNotUse() {
        return shouldNotUse;
    }

    public void addChild(InputItem inputItem) {
        childList.add(inputItem);
    }

    private boolean testIsShouldNotUse() {
        if (!shouldNotUse) {
            return false;
        }
        if (selected) {
            return false;
        }
        if (childList.isEmpty()) {
            return true;
        }
        for (InputItem inputItem : childList) {
            if (!inputItem.testIsShouldNotUse()) {
                return false;
            }
        }
        return true;
    }

    public static void populateInputItems(ThesaurusEntry.Choice formEntry, Lang lang, List<InputItem> inputItemList) {
        int style = getStyleValue(formEntry.getIdalphaStyle());
        Thesaurus thesaurus = formEntry.getThesaurus();
        for (Motcle firstLevelMotcle : thesaurus.getFirstLevelList()) {
            InputItem.populateInputItem(firstLevelMotcle, formEntry, lang, inputItemList, style);
        }
    }

    private static void populateInputItem(Motcle motcle, ThesaurusEntry.Choice formEntry, Lang lang, List<InputItem> inputItemList, int style) {
        InputItem inputItem = toInputItem(motcle, formEntry, lang, 1, style);
        if (inputItem != null) {
            inputItemList.add(inputItem);
            for (Motcle child : motcle.getChildList()) {
                populateInputItem(child, formEntry, lang, inputItem, 2, style);
            }
        } else {
            for (Motcle child : motcle.getChildList()) {
                populateInputItem(child, formEntry, lang, inputItemList, style);
            }
        }
    }

    private static void populateInputItem(Motcle motcle, ThesaurusEntry.Choice formEntry, Lang lang, InputItem parent, int depth, int style) {
        InputItem inputItem = toInputItem(motcle, formEntry, lang, depth, style);
        if (inputItem != null) {
            parent.addChild(inputItem);
            for (Motcle child : motcle.getChildList()) {
                populateInputItem(child, formEntry, lang, inputItem, depth + 1, style);
            }
        } else {
            for (Motcle child : motcle.getChildList()) {
                populateInputItem(child, formEntry, lang, parent, depth, style);
            }
        }
    }

    private static InputItem toInputItem(Motcle motcle, ThesaurusEntry.Choice formEntry, Lang lang, int depth, int style) {
        boolean selected = formEntry.contains(motcle);
        if ((!selected) && (!formEntry.getFilterPredicate().test(motcle))) {
            return null;
        }
        String idalpha = motcle.getIdalpha();
        String currentValue;
        if (idalpha != null) {
            currentValue = idalpha;
        } else {
            currentValue = String.valueOf(motcle.getId());
        }
        String labelText = getText(motcle, lang, style);
        labelText = checkLength(labelText, 50);
        boolean shouldNotUse = motcle.shouldNotJunction(formEntry.getDestinationSubsetKey());
        boolean group = (motcle.getStatus().equals(FichothequeConstants.GROUP_STATUS));
        InputItem inputItem = new InputItem(currentValue, labelText, selected, depth, shouldNotUse, group);
        return inputItem;
    }


    public static boolean printInputList(HtmlPrinter hp, List<InputItem> inputItemList, HtmlAttributes inputAttr) {
        for (InputItem inputItem : inputItemList) {
            if ((!inputItem.isShouldNotUse()) || (inputItem.isSelected())) {
                String value = inputItem.getValue();
                String genId = hp.generateId();
                hp
                        .DIV("ficheform-Choice")
                        .INPUT(inputAttr.id(genId).value(value).checked(inputItem.isSelected()))
                        .LABEL_for(genId)
                        .__escape(inputItem.getLabelText())
                        ._LABEL()
                        ._DIV();
            }
            if (!inputItem.childList.isEmpty()) {
                printInputList(hp, inputItem.childList, inputAttr);
            }
        }
        return true;
    }

    public static boolean printOptions(HtmlPrinter hp, List<InputItem> inputItemList) {
        for (InputItem inputItem : inputItemList) {
            if (inputItem.testIsShouldNotUse()) {
                continue;
            }
            int depth = inputItem.getDepth();
            if (inputItem.isGroup()) {
                StringBuilder buf = new StringBuilder();
                for (int i = 2; i <= depth; i++) {
                    buf.append("\u00A0 \u00A0 ");
                }
                buf.append(inputItem.getLabelText());
                hp
                        .OPTGROUP(HA.label(buf.toString()))
                        ._OPTGROUP();
            } else {
                if ((inputItem.isShouldNotUse()) && (!inputItem.isSelected())) {
                    hp
                            .OPTION(HA.value(inputItem.getValue()).selected(inputItem.isSelected()).disabled(true));
                } else {
                    hp
                            .OPTION(inputItem.getValue(), inputItem.isSelected());
                }
                for (int i = 2; i <= depth; i++) {
                    hp
                            .__doublespace()
                            .__doublespace();
                }
                hp
                        .__escape(inputItem.getLabelText())
                        ._OPTION();
            }
            if (!inputItem.childList.isEmpty()) {
                printOptions(hp, inputItem.childList);
            }
        }
        return true;
    }

    private static String checkLength(String text, int maxStringLength) {
        if ((maxStringLength < 1) || (text.length() <= maxStringLength)) {
            return text;
        } else {
            return text.substring(0, maxStringLength) + "\u2026";
        }
    }

    public static int getStyleValue(Attribute attribute) {
        int style = DASH_IDALPHASTYLE;
        if (attribute != null) {
            if (attribute.contains("brackets")) {
                style = BRACKETS_IDALPHASTYLE;
            } else if (attribute.contains("ignore")) {
                style = IGNORE_IDALPHASTYLE;
            }
        }
        return style;
    }

    public static String getText(Motcle motcle, Lang lang, int idalphaStyle) {
        if (motcle.isBabelienType()) {
            return motcle.getBabelienLabel().getLabelString();
        } else {
            StringBuilder buf = new StringBuilder();
            String idalpha = motcle.getSignificantIdalpha();
            Label label = motcle.getLabels().getLangPartCheckedLabel(lang);
            if ((idalpha != null) && (idalphaStyle != IGNORE_IDALPHASTYLE)) {
                if (idalphaStyle == BRACKETS_IDALPHASTYLE) {
                    buf.append('[');
                    buf.append(idalpha);
                    buf.append(']');
                    if (label != null) {
                        buf.append(' ');
                        buf.append(label.getLabelString());
                    }
                } else {
                    buf.append(idalpha);
                    if (label != null) {
                        buf.append(" – ");
                        buf.append(label.getLabelString());
                    }
                }
            } else {
                if (label != null) {
                    buf.append(label.getLabelString());
                } else {
                    buf.append(String.valueOf(motcle.getId()));
                }
            }
            return buf.toString();
        }
    }


}
