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

import java.util.AbstractList;
import java.util.Collections;
import java.util.List;
import java.util.RandomAccess;
import java.util.SortedMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.mapeadores.util.text.RelativePath;
import net.mapeadores.util.text.StringUtils;


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

    public final static ResourceFolder EMPTY_ROOTFOLDER = new EmptyRootFolder();
    public final static Pattern NAME_PATTERN = Pattern.compile("^[_a-zA-Z][-_.a-zA-Z0-9]*$");

    private ResourceUtils() {

    }

    public static ResourceStorages toResourceStorages(ResourceStorage[] array) {
        return new InternalResourceStorages(array);
    }

    public static List<ResourceFolder> wrap(ResourceFolder[] array) {
        return new ResourceFolderList(array);
    }

    public static boolean isValidResourceName(String name) {
        Matcher matcher = NAME_PATTERN.matcher(name);
        if (matcher.matches()) {
            int idx = name.indexOf('.');
            if ((idx > 0) && (idx < (name.length() - 1))) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    public static boolean isValidFolderName(String name) {
        Matcher matcher = NAME_PATTERN.matcher(name);
        return matcher.matches();
    }

    public static boolean isValidResourceRelativePath(RelativePath relativePath) {
        String[] array = relativePath.toArray();
        int length = array.length;
        if (length < 2) {
            return false;
        }
        for (int i = 0; i < (length - 1); i++) {
            String name = array[i];
            if (!isValidFolderName(name)) {
                return false;
            }
        }
        return isValidResourceName(array[length - 1]);
    }

    static void addSubressources(SortedMap<String, RelativePath> map, ResourceFolder folder, RelativePath folderPath, String pathToRoot) {
        for (String resourceName : folder.getResourceNameList()) {
            RelativePath resourcePath = folderPath.buildChild(resourceName);
            map.put(pathToRoot + resourceName, resourcePath);
        }
        for (ResourceFolder subfolder : folder.getSubfolderList()) {
            String folderName = subfolder.getName();
            addSubressources(map, subfolder, folderPath.buildChild(folderName), pathToRoot + folderName + "/");
        }
    }


    private static class InternalResourceStorages extends AbstractList<ResourceStorage> implements ResourceStorages {

        private final ResourceStorage[] array;

        private InternalResourceStorages(ResourceStorage[] array) {
            this.array = array;
        }

        @Override
        public int size() {
            return array.length;
        }

        @Override
        public ResourceStorage get(int index) {
            return array[index];
        }

        @Override
        public ResourceStorage getResourceStorage(String name) {
            for (ResourceStorage resourceStorage : array) {
                if (resourceStorage.getName().equals(name)) {
                    return resourceStorage;
                }
            }
            return null;
        }

    }


    private static class ResourceFolderList extends AbstractList<ResourceFolder> implements RandomAccess {

        private final ResourceFolder[] array;

        private ResourceFolderList(ResourceFolder[] array) {
            this.array = array;
        }

        @Override
        public int size() {
            return array.length;
        }

        @Override
        public ResourceFolder get(int index) {
            return array[index];
        }

    }


    private static class EmptyRootFolder implements ResourceFolder {

        private final List<ResourceFolder> emptyList = Collections.emptyList();

        private EmptyRootFolder() {
        }

        @Override
        public String getName() {
            return "";
        }

        @Override
        public List<ResourceFolder> getSubfolderList() {
            return emptyList;
        }

        @Override
        public List<String> getResourceNameList() {
            return StringUtils.EMPTY_STRINGLIST;
        }

    }

}
