/* BdfServer - Copyright (c) 2018-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 fr.exemole.bdfserver.conf;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import net.mapeadores.util.exceptions.InternalResourceException;
import net.mapeadores.util.io.IOUtils;
import net.mapeadores.util.text.StringUtils;


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

    private static final int BUFFER = 1024;
    private final static Set<String> RESERVED_WORDS = new HashSet<String>();
    private static final String VAR_PREFIX = "var/";

    static {
        try (InputStream is = ConfUtils.class.getResourceAsStream("reserved-words.txt")) {
            List<String> lines = IOUtils.readLines(is);
            for (String line : lines) {
                line = line.trim();
                if ((line.length() > 0) && (!line.startsWith("#"))) {
                    RESERVED_WORDS.add(line);
                }
            }
        } catch (IOException ioe) {
            throw new InternalResourceException(ioe);
        }
    }

    private ConfUtils() {

    }

    public static boolean isValidMultiName(String s) {
        try {
            StringUtils.checkTechnicalName(s, true);
        } catch (ParseException pe) {
            return false;
        }
        return !isReservedWord(s);
    }

    public static boolean isReservedWord(String s) {
        return RESERVED_WORDS.contains(s);
    }

    public static SortedSet<String> getExistingNameSet(WebappDirs webappDirs) {
        SortedSet<String> existingNameSet = new TreeSet<String>();
        File varDataRootDir = webappDirs.getDir(ConfConstants.VAR_DATA);
        for (File file : varDataRootDir.listFiles()) {
            if (file.isDirectory()) {
                String name = file.getName();
                if (ConfUtils.isValidMultiName(name)) {
                    existingNameSet.add(name.intern());
                }
            }
        }
        return existingNameSet;
    }

    public static boolean isExistingName(WebappDirs webappDirs, String name) {
        if (!ConfUtils.isValidMultiName(name)) {
            return false;
        }
        File varDataRootDir = webappDirs.getDir(ConfConstants.VAR_DATA);
        File existingDir = new File(varDataRootDir, name);
        if ((existingDir.exists()) && (existingDir.isDirectory())) {
            return true;
        } else {
            return false;
        }
    }

    public static File getMultiIniFile(WebappDirs webappDirs) {
        return new File(webappDirs.getDir(ConfConstants.VAR_DATA), "multi.ini");
    }

    public static void copyZippedFiles(BdfServerDirs dirs, File zipFile) throws IOException {
        try (ZipInputStream is = new ZipInputStream(new FileInputStream(zipFile))) {
            ZipEntry zipEntry;
            while ((zipEntry = is.getNextEntry()) != null) {
                String name = zipEntry.getName();
                if (name.startsWith(VAR_PREFIX)) {
                    int idx = name.indexOf('/', VAR_PREFIX.length());
                    if (idx != -1) {
                        String subdirName = name.substring(VAR_PREFIX.length(), idx);
                        String path = name.substring(idx + 1);
                        File rootDir = dirs.getSubPath(ConfConstants.VAR_DATA, subdirName);
                        File destination = new File(rootDir, path);
                        destination.getParentFile().mkdirs();
                        unzipFile(destination, is);
                    }
                }
            }
        }
    }

    private static void unzipFile(File f, ZipInputStream zipStream) throws IOException {
        int count;
        byte data[] = new byte[BUFFER];
        try (BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(f), BUFFER)) {
            while ((count = zipStream.read(data, 0, BUFFER)) != -1) {
                os.write(data, 0, count);
            }
        }
    }

}
