/* UtilLib - Copyright (c) 2022-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 net.mapeadores.util.jslib;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import net.mapeadores.util.text.RelativePath;
import net.mapeadores.util.text.StringUtils;


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

    private final List<JsLib> dependencyList = new ArrayList<JsLib>();
    private final List<RelativePath> jsScriptList = new ArrayList<RelativePath>();
    private final List<ThirdLib> thirdLibList = new ArrayList<ThirdLib>();
    private final List<TemplateFamily> templateFamilyList = new ArrayList<TemplateFamily>();
    private final List<RelativePath> cssPathList = new ArrayList<RelativePath>();
    private final Set<String> existingCss = new HashSet<String>();
    private final Set<String> existingJs = new HashSet<String>();

    public JsLibBuilder() {

    }

    public JsLibBuilder addCssPath(RelativePath relativePath) {
        if (relativePath == null) {
            throw new IllegalArgumentException("cssPath is null");
        }
        String path = relativePath.getPath();
        if (!existingCss.contains(path)) {
            cssPathList.add(relativePath);
            existingCss.add(path);
        }
        return this;
    }

    public JsLibBuilder addDependency(JsLib dependency) {
        if (dependency == null) {
            throw new IllegalArgumentException("dependency is null");
        }
        dependencyList.add(dependency);
        return this;
    }

    public JsLibBuilder addJsScript(RelativePath relativePath) {
        if (relativePath == null) {
            throw new IllegalArgumentException("relativePath is null");
        }
        String path = relativePath.getPath();
        if (!existingJs.contains(path)) {
            jsScriptList.add(relativePath);
            existingJs.add(path);
        }
        return this;
    }

    public JsLibBuilder addTemplateFamily(TemplateFamily templateFamily) {
        if (templateFamily == null) {
            throw new IllegalArgumentException("templateFamily is null");
        }
        templateFamilyList.add(templateFamily);
        return this;
    }

    public JsLibBuilder addThirdLib(ThirdLib thirdLib) {
        if (thirdLib == null) {
            throw new IllegalArgumentException("thirdLib is null");
        }
        thirdLibList.add(thirdLib);
        return this;
    }

    public JsLib toJsLib() {
        List<JsLib> finalDependencyList;
        if (dependencyList.isEmpty()) {
            finalDependencyList = JsLibUtils.EMPTY_JSLIBLIST;
        } else {
            finalDependencyList = JsLibUtils.wrap(dependencyList.toArray(new JsLib[dependencyList.size()]));
        }
        List<RelativePath> finalJsScriptList;
        if (jsScriptList.isEmpty()) {
            finalJsScriptList = StringUtils.EMPTY_RELATIVEPATHLIST;
        } else {
            finalJsScriptList = StringUtils.wrap(jsScriptList.toArray(new RelativePath[jsScriptList.size()]));
        }
        List<ThirdLib> finalThirdLibList;
        if (thirdLibList.isEmpty()) {
            finalThirdLibList = JsLibUtils.EMPTY_THIRDLIBLIST;
        } else {
            finalThirdLibList = JsLibUtils.wrap(thirdLibList.toArray(new ThirdLib[thirdLibList.size()]));
        }
        List<TemplateFamily> finalJsrenderTemplateList;
        if (templateFamilyList.isEmpty()) {
            finalJsrenderTemplateList = JsLibUtils.EMPTY_TEMPLATEFAMILYLIST;
        } else {
            finalJsrenderTemplateList = JsLibUtils.wrap(templateFamilyList.toArray(new TemplateFamily[templateFamilyList.size()]));
        }
        List<RelativePath> finalcssPathList;
        if (cssPathList.isEmpty()) {
            finalcssPathList = StringUtils.EMPTY_RELATIVEPATHLIST;
        } else {
            finalcssPathList = StringUtils.wrap(cssPathList.toArray(new RelativePath[cssPathList.size()]));
        }
        return new InternalJsLib(finalDependencyList, finalJsScriptList, finalThirdLibList, finalJsrenderTemplateList, finalcssPathList);
    }

    public static JsLibBuilder init() {
        return new JsLibBuilder();
    }


    private static class InternalJsLib implements JsLib {

        private final List<JsLib> dependencyList;
        private final List<RelativePath> jsScriptList;
        private final List<ThirdLib> thirdLibList;
        private final List<TemplateFamily> templateList;
        private final List<RelativePath> cssPathList;

        private InternalJsLib(List<JsLib> dependencyList, List<RelativePath> jsScriptList, List<ThirdLib> thirdLibList, List<TemplateFamily> templateList, List<RelativePath> cssPathList) {
            this.dependencyList = dependencyList;
            this.jsScriptList = jsScriptList;
            this.thirdLibList = thirdLibList;
            this.templateList = templateList;
            this.cssPathList = cssPathList;
        }

        @Override
        public List<JsLib> getDependencyList() {
            return dependencyList;
        }

        @Override
        public List<RelativePath> getJsScriptList() {
            return jsScriptList;
        }

        @Override
        public List<ThirdLib> getThirdLibList() {
            return thirdLibList;
        }

        @Override
        public List<TemplateFamily> getTemplateFamilyList() {
            return templateList;
        }

        @Override
        public List<RelativePath> getCssPathList() {
            return cssPathList;
        }

    }

}
