/* 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.bdfdata;

import fr.exemole.bdfserver.api.storage.BdfStorageException;
import fr.exemole.bdfserver.conf.BdfServerDirs;
import fr.exemole.bdfserver.conf.ConfConstants;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.text.ParseException;
import net.mapeadores.util.exceptions.InternalResourceException;
import net.mapeadores.util.io.FileUtils;
import net.mapeadores.util.io.IOUtils;
import net.mapeadores.util.security.PasswordChecker;


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

    private final static FileInfo[] FILES = new FileInfo[2];
    private final static FileInfo[] FILES_SPHERE = new FileInfo[3];
    private final BdfServerDirs dirs;
    private final StartValues startValues;
    private final File bdfdataDir;

    static {
        FILES[0] = new FileInfo("fichotheque-metadata.xml", BdfdataConstants.FICHOTHEQUE, "", "metadata.xml");
        FILES[1] = new FileInfo("lang-configuration.xml", BdfdataConstants.CONF, "", "lang-configuration.xml");
        FILES_SPHERE[0] = new FileInfo("admin.xml", BdfdataConstants.CONF, "redacteurlists", "admin.xml");
        FILES_SPHERE[1] = new FileInfo("sphere-metadata.xml", BdfdataConstants.FICHOTHEQUE, "sphere", "{spherename}.xml");
        FILES_SPHERE[2] = new FileInfo("sphere-list.xml", BdfdataConstants.FICHOTHEQUE, "sphere/{spherename}", "list.xml");
    }


    private StartEngine(BdfServerDirs dirs, StartValues startValues, File bdfdataDir) {
        this.dirs = dirs;
        this.startValues = startValues;
        this.bdfdataDir = bdfdataDir;
    }

    private void start() {
        for (FileInfo fileInfo : FILES) {
            writeStartFile(fileInfo);
        }
    }

    public StartEngine addFirstSphere() {
        for (FileInfo fileInfo : FILES_SPHERE) {
            writeStartFile(fileInfo);
        }
        writePassword();
        return this;
    }

    public StartEngine addCentralSpheres() {
        for (String sphereName : startValues.centralSpheres()) {
            writeStartFile(new FileInfo("sphere-metadata.xml", BdfdataConstants.FICHOTHEQUE, "sphere", sphereName + ".xml"));
        }
        return this;
    }

    private void writeStartFile(FileInfo fileInfo) {
        String fileContent;
        try (InputStream is = BdfdataDirectory.class.getResourceAsStream("defaultfiles/" + fileInfo.getOriginName())) {
            fileContent = IOUtils.toString(is, "UTF-8");
        } catch (IOException ioe) {
            throw new BdfStorageException(ioe);
        }
        File destFile;
        try {
            fileContent = startValues.replaceInText(fileContent);
            File destDir = new File(bdfdataDir, fileInfo.getRoot());
            String path = fileInfo.getPath();
            if (path.length() > 0) {
                path = startValues.replaceInText(path);
                destDir = new File(destDir, path);
            }
            destDir.mkdirs();
            destFile = new File(destDir, startValues.replaceInText(fileInfo.getDestinationName()));
        } catch (ParseException pe) {
            throw new InternalResourceException(pe);
        }
        try {
            FileUtils.writeStringToFile(destFile, fileContent, "UTF-8");
        } catch (IOException ioe) {
            throw new BdfStorageException(ioe);
        }
    }

    private void writePassword() {
        File confDir = new File(bdfdataDir, BdfdataConstants.CONF);
        File passwdFile = new File(confDir, "passwd");
        try (BufferedWriter buf = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(passwdFile), "UTF-8"))) {
            buf.append(startValues.spherename());
            buf.append("/1:");
            buf.append(PasswordChecker.getHash(PasswordChecker.PBKDF2, startValues.firstpassword()));
            buf.append('\n');
        } catch (IOException ioe) {
            throw new BdfStorageException(ioe);
        }
    }

    public static StartEngine start(BdfServerDirs dirs, StartValues startValues) {
        File bdfdataDir = dirs.getSubPath(ConfConstants.VAR_DATA, BdfdataConstants.ROOT);
        bdfdataDir.mkdirs();
        StartEngine startEngine = new StartEngine(dirs, startValues, bdfdataDir);
        startEngine.start();
        return startEngine;
    }


    private static class FileInfo {

        private final String name;
        private final String root;
        private final String path;
        private final String destinationName;

        private FileInfo(String name, String root, String path, String destinationName) {
            this.name = name;
            this.root = root;
            this.path = path;
            this.destinationName = destinationName;
        }

        private String getOriginName() {
            return name;
        }

        private String getRoot() {
            return root;
        }

        private String getPath() {
            return path;
        }

        private String getDestinationName() {
            return destinationName;
        }

    }

}
