/* FichothequeLib_Tools - Copyright (c) 2013-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;

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.RandomAccess;
import java.util.Set;
import net.fichotheque.importation.TiesImport;
import net.fichotheque.include.IncludeKey;
import net.fichotheque.utils.FichothequeUtils;


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

    private final Set<IncludeKey> removedIncludeKeySet = new HashSet<IncludeKey>();
    private final Set<IncludeKey> replaceIncludeKeySet = new HashSet<IncludeKey>();
    private final List<TiesImport.TieImport> replaceList = new ArrayList<TiesImport.TieImport>();
    private final List<TiesImport.TieImport> appendList = new ArrayList<TiesImport.TieImport>();

    public TiesImportBuilder() {

    }

    public void addRemovedIncludeKey(IncludeKey includeKey) {
        if (!replaceIncludeKeySet.contains(includeKey)) {
            removedIncludeKeySet.add(includeKey);
        }
    }

    public void addReplaceTieImport(TiesImport.TieImport tieImport) {
        IncludeKey includeKey = tieImport.getIncludeKey();
        removedIncludeKeySet.remove(includeKey);
        replaceIncludeKeySet.add(includeKey);
        replaceList.add(tieImport);
    }

    public void addAppendTieImport(TiesImport.TieImport tieImport) {
        appendList.add(tieImport);
    }

    public void merge(TiesImportBuilder otherTiesImportBuilder) {
        for (IncludeKey otherIncludeKey : otherTiesImportBuilder.removedIncludeKeySet) {
            addRemovedIncludeKey(otherIncludeKey);
        }
        for (TiesImport.TieImport tieImport : otherTiesImportBuilder.replaceList) {
            addReplaceTieImport(tieImport);
        }
        for (TiesImport.TieImport tieImport : otherTiesImportBuilder.appendList) {
            addAppendTieImport(tieImport);
        }
    }

    public TiesImport toTiesImport() {
        List<IncludeKey> removedIncludeKeyList = FichothequeUtils.wrap(removedIncludeKeySet.toArray(new IncludeKey[removedIncludeKeySet.size()]));
        return new InternalTiesImport(removedIncludeKeyList, wrap(replaceList), wrap(appendList));
    }

    private static List<TiesImport.TieImport> wrap(List<TiesImport.TieImport> list) {
        return new TieImportList(list.toArray(new TiesImport.TieImport[list.size()]));
    }


    private static class InternalTiesImport implements TiesImport {

        private final List<IncludeKey> removedIncludeKeyList;
        private final List<TiesImport.TieImport> replaceList;
        private final List<TiesImport.TieImport> appendList;

        private InternalTiesImport(List<IncludeKey> removedIncludeKeyList, List<TiesImport.TieImport> replaceList, List<TiesImport.TieImport> appendList) {
            this.removedIncludeKeyList = removedIncludeKeyList;
            this.replaceList = replaceList;
            this.appendList = appendList;
        }

        @Override
        public List<IncludeKey> getRemovedIncludeKeyList() {
            return removedIncludeKeyList;
        }

        @Override
        public List<TiesImport.TieImport> getReplaceTieImportList() {
            return replaceList;
        }

        @Override
        public List<TiesImport.TieImport> getAppendTieImportList() {
            return appendList;
        }

    }


    private static class TieImportList extends AbstractList<TiesImport.TieImport> implements RandomAccess {

        private final TiesImport.TieImport[] array;

        private TieImportList(TiesImport.TieImport[] array) {
            this.array = array;
        }

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

        @Override
        public TiesImport.TieImport get(int index) {
            return array[index];
        }

    }

}
