/* BdfServer_DirectoryStorage - Copyright (c) 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 fr.exemole.bdfserver.storage.directory;

import fr.exemole.bdfserver.api.storage.BdfStorageException;
import fr.exemole.bdfserver.conf.ConfConstants;
import fr.exemole.bdfserver.conf.ConfDirs;
import fr.exemole.bdfserver.tools.storage.StorageFile;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import net.fichotheque.EditOrigin;
import net.mapeadores.util.annotation.Nullable;
import net.mapeadores.util.io.IOUtils;


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

    private StorageDirectoryUtils() {

    }

    public static StorageDirectory toStorageDirectory(ConfDirs confDirs, boolean createIfMissing) {
        return toStorageDirectory(confDirs.getDir(ConfConstants.VAR_DATA), confDirs.getDir(ConfConstants.VAR_BACKUP), createIfMissing);
    }

    public static StorageDirectory toStorageDirectory(ConfDirs confDirs, String subPath) {
        return StorageDirectoryUtils.toStorageDirectory(confDirs, subPath, false);
    }

    public static StorageDirectory toStorageDirectory(ConfDirs confDirs, String subPath, boolean createIfMissing) {
        File bdfdataDir = confDirs.getSubPath(ConfConstants.VAR_DATA, subPath);
        File backupDir = confDirs.getSubPath(ConfConstants.VAR_BACKUP, subPath);
        return toStorageDirectory(bdfdataDir, backupDir, createIfMissing);
    }

    public static StorageDirectory toStorageDirectory(File dataDir, @Nullable File backupDir, boolean createIfMissing) {
        if (createIfMissing) {
            testDirectory(dataDir);
            if (backupDir != null) {
                testDirectory(backupDir);
            }
        }
        return new InternalStorageDirectory(dataDir, backupDir);
    }

    public static void testDirectory(File directory) {
        if (!directory.exists()) {
            directory.mkdirs();
        } else if (!directory.isDirectory()) {
            throw new BdfStorageException(directory.getPath() + " is not a directory");
        }
    }

    public static void archiveAndDeleteDirectory(StorageFile dir, EditOrigin editOrigin) {
        if (!dir.isDirectory()) {
            return;
        }
        for (StorageFile subFile : dir.listFiles()) {
            if (subFile.isDirectory()) {
                archiveAndDeleteDirectory(subFile, editOrigin);
            } else {
                subFile.archiveAndDelete(editOrigin);
            }
        }
        dir.delete();
    }

    public static void copyAndArchiveDirectory(File sourceDirectory, StorageFile destinationDir, EditOrigin editOrigin) {
        for (File f : sourceDirectory.listFiles()) {
            StorageFile destinationSubfile = destinationDir.getSubStorageFile(f.getName());
            if (f.isDirectory()) {
                copyAndArchiveDirectory(f, destinationSubfile, editOrigin);
            } else {
                try (InputStream is = new FileInputStream(f); OutputStream os = destinationSubfile.archiveAndGetOutputStream(editOrigin)) {
                    IOUtils.copy(is, os);
                } catch (IOException ioe) {
                    throw new BdfStorageException(ioe);
                }
            }
        }
    }


    private static class InternalStorageDirectory implements StorageDirectory {

        private final File dataDir;
        private final File backupDir;

        private InternalStorageDirectory(File dataDir, File backupDir) {
            this.dataDir = dataDir;
            this.backupDir = backupDir;
        }

        @Override
        public File getDataDir() {
            return dataDir;
        }

        @Override
        public File getBackupDir() {
            return backupDir;
        }

    }

}
