/* 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.io.File;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import net.mapeadores.util.io.docstream.FileDocStream;
import net.mapeadores.util.mimetype.MimeTypeResolver;
import net.mapeadores.util.mimetype.MimeTypeUtils;
import net.mapeadores.util.text.RelativePath;


/**
 *
 * @author Vincent Calame
 */
public class DirectoryResourceStorage implements ResourceStorage {

    private final String name;
    protected final File rootDirectory;

    public DirectoryResourceStorage(String name, File rootDirectory) {
        this.name = name;
        this.rootDirectory = rootDirectory;
    }

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

    @Override
    public boolean containsResource(RelativePath path) {
        File file = getFile(path.toString(), false);
        return (file != null);
    }

    @Override
    public DocStream getResourceDocStream(RelativePath path, MimeTypeResolver mimeTypeResolver) {
        File file = getFile(path.toString(), false);
        if (file == null) {
            return null;
        } else {
            FileDocStream fileDocStream = new FileDocStream(file);
            String mimeType = MimeTypeUtils.getMimeType(mimeTypeResolver, file.getName());
            fileDocStream.setMimeType(mimeType);
            return fileDocStream;
        }
    }

    @Override
    public ResourceFolder getRoot() {
        if ((!rootDirectory.exists()) || (!rootDirectory.isDirectory())) {
            return ResourceUtils.EMPTY_ROOTFOLDER;
        }
        return getResourceFolder(rootDirectory, "");
    }

    @Override
    public ResourceFolder getResourceFolder(RelativePath path) {
        if ((!rootDirectory.exists()) || (!rootDirectory.isDirectory())) {
            return null;
        }
        File dir = new File(rootDirectory, path.toString());
        if ((!dir.exists()) || (!dir.isDirectory())) {
            return null;
        }
        return getResourceFolder(dir, dir.getName());
    }

    protected File getFile(String normalizedPath, boolean create) {
        File resourceFile = new File(rootDirectory, normalizedPath);
        if (create) {
            if ((resourceFile.exists()) && (resourceFile.isDirectory())) {
                return null;
            } else {
                return resourceFile;
            }
        } else {
            if ((resourceFile.exists()) && (!resourceFile.isDirectory())) {
                return resourceFile;
            } else {
                return null;
            }
        }
    }

    private ResourceFolder getResourceFolder(File directory, String folderName) {
        SortedMap<String, ResourceFolder> folderMap = new TreeMap<String, ResourceFolder>();
        SortedSet<String> resourceSet = new TreeSet<String>();
        File[] files = directory.listFiles();
        int length = files.length;
        for (int i = 0; i < length; i++) {
            File f = files[i];
            String fileName = f.getName();
            if (f.isDirectory()) {
                if (ResourceUtils.isValidFolderName(fileName)) {
                    ResourceFolder folder = getResourceFolder(f, fileName);
                    folderMap.put(fileName, folder);
                }
            } else if (!folderName.isEmpty()) {
                if (ResourceUtils.isValidResourceName(fileName)) {
                    resourceSet.add(fileName);
                }
            }
        }
        return ResourceFolderBuilder.build(folderName, folderMap.values(), resourceSet);
    }

}
