/* BdfServer_DirectoryStorage - Copyright (c) 2006-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.storage.directory.StorageDirectory;
import fr.exemole.bdfserver.tools.BdfServerUtils;
import fr.exemole.bdfserver.tools.storage.StorageFile;
import java.io.File;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import net.fichotheque.SubsetKey;
import net.fichotheque.junction.JunctionKey;


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

    private BdfdataStorageFileCatalog() {
    }

    public static StorageFile chrono(StorageDirectory bdfdataDirectory, SubsetKey subsetKey) {
        String path = BdfdataConstants.FICHOTHEQUE + File.separator + "chrono" + File.separator + subsetKey + ".xml";
        return bdfdataDirectory.getStorageFile(path);
    }

    public static StorageFile fichothequeMetadata(StorageDirectory bdfdataDirectory) {
        String path = BdfdataConstants.FICHOTHEQUE + File.separator + "metadata.xml";
        return bdfdataDirectory.getStorageFile(path);
    }


    public static StorageFile addendaMetadata(StorageDirectory bdfdataDirectory, SubsetKey addendaKey) {
        String path = BdfdataConstants.FICHOTHEQUE + File.separator + SubsetKey.CATEGORY_ADDENDA_STRING + File.separator + addendaKey.getSubsetName() + ".xml";
        return bdfdataDirectory.getStorageFile(path);
    }

    public static StorageFile albumMetadata(StorageDirectory bdfdataDirectory, SubsetKey albumKey) {
        String path = BdfdataConstants.FICHOTHEQUE + File.separator + SubsetKey.CATEGORY_ALBUM_STRING + File.separator + albumKey.getSubsetName() + ".xml";
        return bdfdataDirectory.getStorageFile(path);
    }

    public static StorageFile corpusMetadata(StorageDirectory bdfdataDirectory, SubsetKey corpusKey, SubsetKey masterSubsetKey) {
        String prefix = getPrefix(masterSubsetKey);
        String path = BdfdataConstants.FICHOTHEQUE + File.separator + SubsetKey.CATEGORY_CORPUS_STRING + File.separator + prefix + corpusKey.getSubsetName() + ".xml";
        return bdfdataDirectory.getStorageFile(path);
    }

    public static StorageFile fiche(StorageDirectory bdfdataDirectory, SubsetKey subsetKey, int id) {
        String path = FicheDirectory.getPath(subsetKey, id) + File.separatorChar + "fiche.xml";
        return bdfdataDirectory.getStorageFile(path);
    }

    public static StorageFile ficheChrono(StorageDirectory bdfdataDirectory, SubsetKey subsetKey, int id) {
        String path = FicheDirectory.getPath(subsetKey, id) + File.separatorChar + "chrono.txt";
        return bdfdataDirectory.getStorageFile(path);
    }

    public static StorageFile ficheAttributes(StorageDirectory bdfdataDirectory, SubsetKey subsetKey, int id) {
        String path = FicheDirectory.getPath(subsetKey, id) + File.separatorChar + "attributes.xml";
        return bdfdataDirectory.getStorageFile(path);
    }

    public static StorageFile sphereMetadata(StorageDirectory bdfdataDirectory, SubsetKey sphereKey) {
        String path = BdfdataConstants.FICHOTHEQUE + File.separator + SubsetKey.CATEGORY_SPHERE_STRING + File.separator + sphereKey.getSubsetName() + ".xml";
        return bdfdataDirectory.getStorageFile(path);
    }

    public static StorageFile sphereList(StorageDirectory bdfdataDirectory, SubsetKey sphereKey) {
        String path = BdfdataConstants.FICHOTHEQUE + File.separator + SubsetKey.CATEGORY_SPHERE_STRING + File.separator + sphereKey.getSubsetName() + File.separator + "list.xml";
        return bdfdataDirectory.getStorageFile(path);
    }

    public static StorageFile thesaurusMetadata(StorageDirectory bdfdataDirectory, SubsetKey thesaurusKey) {
        String path = BdfdataConstants.FICHOTHEQUE + File.separator + SubsetKey.CATEGORY_THESAURUS_STRING + File.separator + thesaurusKey.getSubsetName() + ".xml";
        return bdfdataDirectory.getStorageFile(path);
    }

    public static StorageFile thesaurusTree(StorageDirectory bdfdataDirectory, SubsetKey thesaurusKey) {
        String path = BdfdataConstants.FICHOTHEQUE + File.separator + SubsetKey.CATEGORY_THESAURUS_STRING + File.separator + thesaurusKey.getSubsetName() + File.separator + "tree.xml";
        return bdfdataDirectory.getStorageFile(path);
    }

    public static StorageFile illustration(StorageDirectory bdfdataDirectory, SubsetKey subsetKey, int id) {
        String path = IllustrationDirectory.getPath(subsetKey, id) + File.separatorChar + "illustration.xml";
        return bdfdataDirectory.getStorageFile(path);
    }

    public static StorageFile document(StorageDirectory bdfdataDirectory, SubsetKey subsetKey, int id) {
        String path = DocumentDirectory.getPath(subsetKey, id) + File.separatorChar + "document.xml";
        return bdfdataDirectory.getStorageFile(path);
    }

    public static StorageFile motcle(StorageDirectory bdfdataDirectory, SubsetKey thesaurusKey, int id) {
        if (!thesaurusKey.isThesaurusSubset()) {
            throw new IllegalArgumentException("!thesaurusKey.isThesaurusSubset()");
        }
        if (id < 0) {
            throw new IllegalArgumentException("id < 0");
        }
        StringBuilder buf = new StringBuilder();
        buf.append(BdfdataConstants.FICHOTHEQUE);
        buf.append(File.separatorChar);
        buf.append(SubsetKey.CATEGORY_THESAURUS_STRING);
        buf.append(File.separatorChar);
        buf.append(thesaurusKey.getSubsetName());
        buf.append(File.separatorChar);
        buf.append("m.");
        buf.append(BdfServerUtils.getMillier(id));
        buf.append(File.separatorChar);
        buf.append(id);
        buf.append(".xml");
        return bdfdataDirectory.getStorageFile(buf.toString());
    }

    public static StorageFile redacteur(StorageDirectory bdfdataDirectory, SubsetKey sphereKey, int id) {
        if (!sphereKey.isSphereSubset()) {
            throw new IllegalArgumentException("!sphereKey.isSphereSubset()");
        }
        if (id < 0) {
            throw new IllegalArgumentException("id < 0");
        }
        StringBuilder buf = new StringBuilder();
        buf.append(BdfdataConstants.FICHOTHEQUE);
        buf.append(File.separatorChar);
        buf.append(SubsetKey.CATEGORY_SPHERE_STRING);
        buf.append(File.separatorChar);
        buf.append(sphereKey.getSubsetName());
        buf.append(File.separatorChar);
        buf.append("r.");
        buf.append(BdfServerUtils.getMillier(id));
        buf.append(File.separatorChar);
        buf.append(id);
        buf.append(".xml");
        return bdfdataDirectory.getStorageFile(buf.toString());
    }

    public static StorageFile junction(StorageDirectory bdfdataDirectory, JunctionKey junctionKey) {
        SubsetKey subsetKey1 = junctionKey.getSubsetKey1();
        SubsetKey subsetKey2 = junctionKey.getSubsetKey2();
        int id1 = junctionKey.getId1();
        int id2 = junctionKey.getId2();
        StringBuilder buf = new StringBuilder();
        buf.append(BdfdataConstants.FICHOTHEQUE);
        buf.append(File.separatorChar);
        buf.append(subsetKey1.getCategoryString());
        buf.append("_");
        buf.append(subsetKey2.getCategoryString());
        buf.append(File.separatorChar);
        buf.append(subsetKey1.getSubsetName());
        buf.append("_");
        buf.append(subsetKey2.getSubsetName());
        buf.append(File.separatorChar);
        buf.append("c.");
        buf.append(BdfServerUtils.getMillier(id1));
        buf.append("_");
        buf.append(BdfServerUtils.getMillier(id2));
        buf.append(File.separatorChar);
        buf.append(id1);
        buf.append("_");
        buf.append(id2);
        buf.append(".xml");
        return bdfdataDirectory.getStorageFile(buf.toString());
    }

    public static StorageFile junctionDirectory(StorageDirectory storageDirectory, SubsetKey subsetKey1, SubsetKey subsetKey2) {
        if (subsetKey1.compareTo(subsetKey2) > 0) {
            SubsetKey temp = subsetKey1;
            subsetKey1 = subsetKey2;
            subsetKey2 = temp;
        }
        StringBuilder buf = new StringBuilder();
        buf.append(BdfdataConstants.FICHOTHEQUE);
        buf.append(File.separatorChar);
        buf.append(subsetKey1.getCategoryString());
        buf.append("_");
        buf.append(subsetKey2.getCategoryString());
        buf.append(File.separatorChar);
        buf.append(subsetKey1.getSubsetName());
        buf.append("_");
        buf.append(subsetKey2.getSubsetName());
        return storageDirectory.getStorageFile(buf.toString());
    }

    public static StorageFile password(StorageDirectory bdfdataDirectory) {
        String path = BdfdataConstants.CONF + File.separator + "passwd";
        return bdfdataDirectory.getStorageFile(path);
    }

    public static StorageFile ui(StorageDirectory bdfdataDirectory, String filebasename) {
        String path = BdfdataConstants.CONF + File.separator + "ui" + File.separator + filebasename + ".xml";
        return bdfdataDirectory.getStorageFile(path);
    }

    public static SubsetInfoList getSubsetInfoList(StorageDirectory bdfdataDirectory, short subsetCategory) {
        String rootPath = BdfdataConstants.FICHOTHEQUE + File.separator + SubsetKey.categoryToString(subsetCategory);
        File subsetDirectory = bdfdataDirectory.getDataDir(rootPath);
        InternalSubsetInfoList result = new InternalSubsetInfoList();
        if (!subsetDirectory.exists()) {
            subsetDirectory.mkdirs();
            return result;
        }
        for (File f : subsetDirectory.listFiles()) {
            String name = f.getName();
            if (name.endsWith(".xml")) {
                String basename = name.substring(0, name.length() - 4);
                try {
                    InternalSubsetInfo subsetInfo = new InternalSubsetInfo();
                    subsetInfo.parse(subsetCategory, basename);
                    StorageFile storageFile = bdfdataDirectory.getStorageFile(rootPath + File.separator + name);
                    subsetInfo.setStorageFile(storageFile);
                    result.add(subsetInfo);
                } catch (IllegalArgumentException iae) {
                } catch (ParseException pe) {
                }
            }
        }
        return result;
    }

    public static StorageFile getOldJunctionStorageFile(StorageDirectory bdfdataDirectory, SubsetKey subsetKey1, SubsetKey subsetKey2) {
        if (subsetKey2.compareTo(subsetKey1) < 0) {
            SubsetKey temp = subsetKey1;
            subsetKey1 = subsetKey2;
            subsetKey2 = temp;
        }
        StringBuilder buf = new StringBuilder();
        buf.append(BdfdataConstants.FICHOTHEQUE);
        buf.append(File.separatorChar);
        buf.append(subsetKey1.getCategoryString());
        buf.append("_");
        buf.append(subsetKey2.getCategoryString());
        buf.append(File.separatorChar);
        buf.append(subsetKey1.getSubsetName());
        buf.append("_");
        buf.append(subsetKey2.getSubsetName());
        buf.append(".xml");
        return bdfdataDirectory.getStorageFile(buf.toString());

    }

    private static String getPrefix(SubsetKey masterSubsetKey) {
        if (masterSubsetKey == null) {
            return "";
        }
        String preprefix = "";
        switch (masterSubsetKey.getCategory()) {
            case SubsetKey.CATEGORY_CORPUS:
                preprefix = "_mc_";
                break;
            case SubsetKey.CATEGORY_THESAURUS:
                preprefix = "_mt_";
                break;
            default:
                throw new UnsupportedOperationException("Unkwnown Master Subset category : " + masterSubsetKey.getCategoryString());
        }
        return preprefix + masterSubsetKey.getSubsetName() + "_";
    }


    private static class InternalSubsetInfoList implements SubsetInfoList {

        private final List<InternalSubsetInfo> subsetList = new ArrayList<InternalSubsetInfo>();
        private final List<InternalSubsetInfo> satelliteSubsetList = new ArrayList<InternalSubsetInfo>();

        private InternalSubsetInfoList() {
        }

        @Override
        public int getStandardSubsetCount() {
            return subsetList.size();
        }

        @Override
        public SubsetInfo getStandardSubsetInfo(int i) {
            return subsetList.get(i);
        }

        @Override
        public int getSatelliteSubsetCount() {
            return satelliteSubsetList.size();
        }

        @Override
        public SubsetInfo getSatelliteSubsetInfo(int i) {
            return satelliteSubsetList.get(i);
        }

        void add(InternalSubsetInfo subsetInfo) {
            if (subsetInfo.isSatelliteSubset()) {
                satelliteSubsetList.add(subsetInfo);
            } else {
                subsetList.add(subsetInfo);
            }
        }

        void sort() {
            Collections.sort(subsetList);
            Collections.sort(satelliteSubsetList);
        }

    }


    private static class InternalSubsetInfo implements SubsetInfo, Comparable<InternalSubsetInfo> {

        private SubsetKey subsetKey;
        private StorageFile storageFile;
        private SubsetKey masterSubsetKey;

        private InternalSubsetInfo() {
        }

        @Override
        public SubsetKey getSubsetKey() {
            return subsetKey;
        }

        @Override
        public int compareTo(InternalSubsetInfo other) {
            int result = this.subsetKey.compareTo(other.subsetKey);
            if (result == 0) {
                result = this.masterSubsetKey.compareTo(other.masterSubsetKey);
            }
            return result;
        }

        @Override
        public StorageFile getStorageFile() {
            return storageFile;
        }

        void setStorageFile(StorageFile storageFile) {
            this.storageFile = storageFile;
        }

        @Override
        public SubsetKey getMasterSubsetKey() {
            return masterSubsetKey;
        }

        @Override
        public boolean isSatelliteSubset() {
            return (masterSubsetKey != null);
        }

        void parse(short subsetCategory, String baseName) throws ParseException {
            if (baseName.startsWith("_mc_")) {
                parserSatelliteSubsetId(subsetCategory, baseName.substring(4), SubsetKey.CATEGORY_CORPUS);
            } else if (baseName.startsWith("_mt_")) {
                parserSatelliteSubsetId(subsetCategory, baseName.substring(4), SubsetKey.CATEGORY_THESAURUS);
            } else {
                subsetKey = SubsetKey.parse(subsetCategory, baseName);
                masterSubsetKey = null;
            }
        }

        private void parserSatelliteSubsetId(short subsetCategory, String baseName, short masterSubsetCategory) throws ParseException {
            int idx = baseName.indexOf("_");
            if (idx == -1) {
                throw new ParseException("second _ is missing", 4);
            }
            masterSubsetKey = SubsetKey.parse(masterSubsetCategory, baseName.substring(0, idx));
            subsetKey = SubsetKey.parse(subsetCategory, baseName.substring(idx + 1));
        }

    }

}
