/* FichothequeLib_Tools - Copyright (c) 2014-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 net.fichotheque.tools.importation.directory;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.ParseException;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;
import java.util.RandomAccess;
import java.util.SortedSet;
import java.util.TreeSet;
import net.fichotheque.Fichotheque;
import net.fichotheque.SubsetKey;
import net.fichotheque.corpus.Corpus;
import net.fichotheque.importation.CorpusImport;
import net.fichotheque.importation.ImportationContext;
import net.fichotheque.tools.importation.corpus.EditFicheImportBuilder;
import net.fichotheque.tools.importation.dom.FicheImportDOMReader;
import net.mapeadores.util.exceptions.NestedIOException;
import net.mapeadores.util.xml.DOMUtils;
import org.w3c.dom.Element;


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

    private static final CorpusImport.FicheImport NULL_FICHEIMPORT = new NullFicheImport();

    private CorpusImportLoad() {
    }

    public static CorpusImport load(Fichotheque fichotheque, File dir, ImportationContext importationContext) {
        File initFile = new File(dir, "init.txt");
        if (!initFile.exists()) {
            return null;
        }
        Corpus corpus;
        String type;
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(initFile), "UTF-8"))) {
            String corpusString = reader.readLine();
            try {
                SubsetKey corpusKey = SubsetKey.parse(corpusString);
                corpus = (Corpus) fichotheque.getSubset(corpusKey);
            } catch (ParseException pe) {
                return null;
            }
            type = reader.readLine();
            try {
                type = CorpusImport.checkType(type);
            } catch (IllegalArgumentException iae) {
                return null;
            }
        } catch (IOException ioe) {
            throw new NestedIOException(ioe);
        }
        switch (type) {
            case CorpusImport.EDIT_TYPE:
                return loadEdit(corpus, dir, importationContext);
            default:
                return null;
        }
    }

    private static CorpusImport loadEdit(Corpus corpus, File dir, ImportationContext importationContext) {
        File[] files = dir.listFiles();
        SortedSet<String> sortedSet = new TreeSet<String>();
        for (File f : dir.listFiles()) {
            if (f.isDirectory()) {
                continue;
            }
            String name = f.getName();
            if ((name.length() > 4) && (name.endsWith(".xml"))) {
                sortedSet.add(name);
            }
        }
        List<String> fileNameList = new ArrayList<String>(sortedSet);
        return new DirCorpusImport(corpus, dir, fileNameList, importationContext);
    }


    private static class DirCorpusImport implements CorpusImport {

        private final Corpus corpus;
        private final ImportationContext importationContext;
        private final File dir;
        private final List<String> fileNameList;
        private final FicheImportList ficheImportList = new FicheImportList();

        private DirCorpusImport(Corpus corpus, File dir, List<String> fileNameList, ImportationContext importationContext) {
            this.corpus = corpus;
            this.importationContext = importationContext;
            this.dir = dir;
            this.fileNameList = fileNameList;
        }

        @Override
        public Corpus getCorpus() {
            return corpus;
        }

        @Override
        public String getType() {
            return CorpusImport.EDIT_TYPE;
        }

        @Override
        public List<FicheImport> getFicheImportList() {
            return ficheImportList;
        }


        private class FicheImportList extends AbstractList<CorpusImport.FicheImport> implements RandomAccess {

            private FicheImportList() {

            }

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

            @Override
            public CorpusImport.FicheImport get(int index) {
                String fileName = fileNameList.get(index);
                File f = new File(dir, fileName);
                Element rootElement = DOMUtils.readDocument(f).getDocumentElement();
                String idString = rootElement.getAttribute("id");
                if (idString.isEmpty()) {
                    return getEdit(-1, rootElement);
                } else {
                    try {
                        int id = Integer.parseInt(idString);
                        return getEdit(id, rootElement);
                    } catch (NumberFormatException nfe) {
                        return NULL_FICHEIMPORT;
                    }
                }
            }

            private CorpusImport.EditFicheImport getEdit(int ficheId, Element rootElement) {
                EditFicheImportBuilder ficheImportBuilder = new EditFicheImportBuilder(ficheId);
                FicheImportDOMReader.init(ficheImportBuilder, corpus.getFichotheque(), importationContext).read(rootElement);
                return ficheImportBuilder.toEditFicheImport();
            }

        }

    }


    private static class NullFicheImport implements CorpusImport.FicheImport {

        private NullFicheImport() {

        }

        @Override
        public int getFicheId() {
            return -999;
        }

    }


}
