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

import java.util.function.BiConsumer;
import java.util.function.Consumer;
import net.mapeadores.util.annotation.Nullable;
import net.mapeadores.util.html.HtmlAttributes;
import net.mapeadores.util.html.HtmlPrinter;
import net.mapeadores.util.html.HtmlWrapper;
import net.mapeadores.util.html.WrapperFactory;


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

    public final static HtmlWrapper BRANCH = WrapperFactory.ul("tree-Top");
    public final static HtmlWrapper LEAF = new NodeWrapper("tree-Leaf", "");
    public final static HtmlWrapper NODE = WrapperFactory.li("tree-Node");
    public final static HtmlWrapper TREE = WrapperFactory.ul("tree-Top");
    public final static HtmlWrapper OPEN_NODE = new NodeWrapper("tree-OpenContent", "");

    public static HtmlWrapper branch(String cssClasses) {
        return branch(cssClasses, false);
    }

    public static HtmlWrapper branch(String cssClasses, boolean withoutTop) {
        if (withoutTop) {
            return WrapperFactory.ul(cssClasses);
        } else {
            return WrapperFactory.ul(cssClasses + " tree-Top");
        }
    }

    public static HtmlWrapper tree(String cssClasses) {
        return tree(cssClasses, false);
    }

    public static HtmlWrapper tree(String cssClasses, boolean withoutTop) {
        if (withoutTop) {
            return WrapperFactory.ul(cssClasses);
        } else {
            return WrapperFactory.ul(cssClasses + " tree-Top");
        }
    }

    public static HtmlWrapper leaf(String supplementaryCssClasses) {
        return new NodeWrapper("tree-Leaf", supplementaryCssClasses);
    }

    public static HtmlWrapper openNode(String supplementaryCssClasses) {
        return new NodeWrapper("tree-OpenContent", supplementaryCssClasses);
    }

    public static Consumer<HtmlPrinter> checkboxLeaf(HtmlAttributes inputAttributes) {
        return new CheckboxLeaf(inputAttributes, null);
    }

    public static Consumer<HtmlPrinter> checkboxLeaf(HtmlAttributes inputAttributes, @Nullable Consumer<HtmlPrinter> contentConsumer) {
        return new CheckboxLeaf(inputAttributes, contentConsumer);
    }

    public static Consumer<HtmlPrinter> checkboxLeaf(HtmlAttributes inputAttributes, @Nullable Runnable contentRunnable) {
        return new CheckboxLeaf(inputAttributes, contentRunnable);
    }


    private static abstract class ContentFunction {

        protected final Object contentFunction;

        protected ContentFunction(Object contentFunction) {
            this.contentFunction = contentFunction;
        }

        protected void run(HtmlPrinter hp) {
            if (contentFunction != null) {
                if (contentFunction instanceof Consumer) {
                    ((Consumer<HtmlPrinter>) contentFunction).accept(hp);
                } else if (contentFunction instanceof Runnable) {
                    ((Runnable) contentFunction).run();
                }
            }
        }

    }


    private static class CheckboxLeaf extends ContentFunction implements Consumer<HtmlPrinter> {

        private final HtmlAttributes inputAttributes;

        private CheckboxLeaf(HtmlAttributes inputAttributes, Object contentFunction) {
            super(contentFunction);
            this.inputAttributes = inputAttributes;
        }

        @Override
        public void accept(HtmlPrinter hp) {
            hp
                    .LI("tree-Node")
                    .DIV("tree-Leaf command-FlexInput")
                    .INPUT_checkbox(inputAttributes)
                    .LABEL_for(inputAttributes.id());
            run(hp);
            hp
                    ._LABEL()
                    ._DIV()
                    ._LI();
        }

    }


    private static class NodeWrapper implements HtmlWrapper {

        private final String cssClasses;

        private NodeWrapper(String defaultClass, String supplementaryCssClasses) {
            if (!supplementaryCssClasses.isEmpty()) {
                this.cssClasses = defaultClass + " " + supplementaryCssClasses;
            } else {
                this.cssClasses = defaultClass;
            }
        }

        @Override
        public void wrap(HtmlPrinter hp, Consumer<HtmlPrinter> consumer) {
            hp
                    .LI("tree-Node")
                    .DIV(cssClasses);
            consumer.accept(hp);
            hp
                    ._DIV()
                    ._LI();
        }

        @Override
        public void wrap(HtmlPrinter hp, Runnable runnable) {
            hp
                    .LI("tree-Node")
                    .DIV(cssClasses);
            runnable.run();
            hp
                    ._DIV()
                    ._LI();
        }

        @Override
        public void wrap(HtmlPrinter hp, BiConsumer<HtmlPrinter, Object> consumer, Object argument) {
            hp
                    .LI("tree-Node")
                    .DIV(cssClasses);
            consumer.accept(hp, argument);
            hp
                    ._DIV()
                    ._LI();
        }

    }

}
