/* BdfServer - 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.parsers.handlers;

import java.util.ArrayList;
import java.util.List;
import net.fichotheque.corpus.metadata.CorpusField;
import net.fichotheque.corpus.metadata.FieldKey;
import net.fichotheque.corpus.metadata.SubfieldKey;
import net.fichotheque.tools.importation.parsers.Row;
import net.fichotheque.tools.parsers.FicheParser;


/**
 *
 * @author Vincent Calame
 */
public abstract class FicheHandler {

    final CorpusField corpusField;
    int uniqueIndex = -1;
    List<Integer> indexList;

    private FicheHandler(CorpusField corpusField) {
        this.corpusField = corpusField;
    }

    public CorpusField getCorpusField() {
        return corpusField;
    }

    public boolean addIndex(int index) {
        if (index == - 1) {
            this.uniqueIndex = index;
        } else {
            this.uniqueIndex = -2;
            if (indexList == null) {
                indexList = new ArrayList<Integer>();
            }
            indexList.add(index);
        }
        return true;
    }

    public abstract void handle(Row row, FicheParser ficheParser);

    public static FicheHandler fromCorpusField(CorpusField corpusField) {
        switch (getHandlerType(corpusField)) {
            case 1:
                return new UniqueCorpusField(corpusField);
            case 2:
                return new MultiCorpusField(corpusField);
            default:
                return new NoDoublonCorpusField(corpusField);

        }
    }

    public static FicheHandler fromSubfield(CorpusField corpusField, SubfieldKey subfieldKey) {
        return new Subfield(corpusField, subfieldKey);
    }

    private static int getHandlerType(CorpusField corpusField) {
        switch (corpusField.getCategory()) {
            case FieldKey.PROP_CATEGORY:
                return 1;
            case FieldKey.INFO_CATEGORY:
            case FieldKey.SECTION_CATEGORY:
                return 2;
            case FieldKey.SPECIAL_CATEGORY:
                switch (corpusField.getFieldString()) {
                    case FieldKey.SPECIAL_TITLE:
                    case FieldKey.SPECIAL_SUBTITLE:
                        return 1;
                    case FieldKey.SPECIAL_OWNERS:
                        return 2;
                }
            default:
                return 0;
        }
    }


    private static class MultiCorpusField extends FicheHandler {

        private MultiCorpusField(CorpusField corpusField) {
            super(corpusField);
        }

        @Override
        public void handle(Row row, FicheParser ficheParser) {
            int columnCount = row.getColumnCount();
            if (uniqueIndex > -1) {
                if (uniqueIndex < columnCount) {
                    ficheParser.parseCorpusField(corpusField, row.getColumnValue(uniqueIndex));
                }
            } else {
                int indexCount = indexList.size();
                for (int i = 0; i < indexCount; i++) {
                    int index = indexList.get(i);
                    if (index < columnCount) {
                        ficheParser.parseCorpusField(corpusField, row.getColumnValue(index));
                    }
                }
            }
        }

    }


    private static class UniqueCorpusField extends FicheHandler {

        private UniqueCorpusField(CorpusField corpusField) {
            super(corpusField);
        }

        @Override
        public void handle(Row row, FicheParser ficheParser) {
            int columnCount = row.getColumnCount();
            if (uniqueIndex > -1) {
                if (uniqueIndex < columnCount) {
                    ficheParser.parseCorpusField(corpusField, row.getColumnValue(uniqueIndex));
                }
            } else {
                StringBuilder buf = new StringBuilder();
                int indexCount = indexList.size();
                for (int i = 0; i < indexCount; i++) {
                    int index = indexList.get(i);
                    if (index < columnCount) {
                        String value = row.getColumnValue(index);
                        if (value != null) {
                            buf.append(value);
                        }
                    }
                }
                ficheParser.parseCorpusField(corpusField, buf.toString());
            }
        }

    }


    private static class NoDoublonCorpusField extends FicheHandler {

        private NoDoublonCorpusField(CorpusField corpusField) {
            super(corpusField);
        }

        @Override
        public boolean addIndex(int index) {
            if (uniqueIndex > - 1) {
                return false;
            }
            uniqueIndex = index;
            return true;
        }

        @Override
        public void handle(Row row, FicheParser ficheParser) {
            int columnCount = row.getColumnCount();
            if (uniqueIndex > -1) {
                if (uniqueIndex < columnCount) {
                    ficheParser.parseCorpusField(corpusField, row.getColumnValue(uniqueIndex));
                }
            }
        }

    }


    private static class Subfield extends FicheHandler {

        private final SubfieldKey subfieldKey;

        private Subfield(CorpusField corpusField, SubfieldKey subfieldKey) {
            super(corpusField);
            this.subfieldKey = subfieldKey;
        }

        @Override
        public boolean addIndex(int index) {
            if (uniqueIndex > - 1) {
                return false;
            }
            uniqueIndex = index;
            return true;
        }

        @Override
        public void handle(Row row, FicheParser ficheParser) {
            int columnCount = row.getColumnCount();
            if (uniqueIndex > -1) {
                if (uniqueIndex < columnCount) {
                    ficheParser.parseSubfield(corpusField, subfieldKey, row.getColumnValue(uniqueIndex));
                }
            }
        }

    }

}
