/* FichothequeLib_Tools - Copyright (c) 2016-2021 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.corpus;

import java.text.ParseException;
import java.util.AbstractList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.RandomAccess;
import net.fichotheque.corpus.metadata.FieldGeneration;
import net.fichotheque.corpus.metadata.FieldKey;
import net.fichotheque.exportation.table.FormatColDef;
import net.fichotheque.exportation.table.TableDef;
import net.fichotheque.exportation.table.TableDefItem;
import net.fichotheque.format.FichothequeFormatDef;
import net.fichotheque.tools.exportation.table.TableDefParser;
import net.mapeadores.util.logging.LineMessageHandler;


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

    private final String rawString;
    private final Map<FieldKey, InternalFieldGenerationEntry> map = new LinkedHashMap<FieldKey, InternalFieldGenerationEntry>();

    private FieldGenerationParser(String rawString) {
        this.rawString = rawString;
    }

    private void run(LineMessageHandler lineMessageHandler) {
        TableDef tableDef = TableDefParser.parse(rawString, lineMessageHandler, 0);
        for (TableDefItem defItem : tableDef.getDefItemList()) {
            if (defItem instanceof FormatColDef) {
                FormatColDef colDef = (FormatColDef) defItem;
                String colName = colDef.getColName();
                try {
                    FieldKey fieldKey = FieldKey.parse(colName);
                    if (!map.containsKey(fieldKey)) {
                        map.put(fieldKey, new InternalFieldGenerationEntry(fieldKey, colDef.getFichothequeFormatDef()));
                    }
                } catch (ParseException pe) {

                }
            }
        }
    }

    private FieldGeneration toFiedGeneration() {
        FieldGeneration.Entry[] array = map.values().toArray(new FieldGeneration.Entry[map.size()]);
        return new InternalFieldGeneration(rawString, new EntryList(array));
    }

    public static FieldGeneration parse(String rawString, LineMessageHandler lineMessageHandler) {
        FieldGenerationParser parser = new FieldGenerationParser(rawString);
        parser.run(lineMessageHandler);
        return parser.toFiedGeneration();
    }


    private static class InternalFieldGeneration implements FieldGeneration {

        private final String rawString;
        private final List<FieldGeneration.Entry> entryList;

        private InternalFieldGeneration(String rawString, List<FieldGeneration.Entry> entryList) {
            this.rawString = rawString;
            this.entryList = entryList;
        }

        @Override
        public String getRawString() {
            return rawString;
        }

        @Override
        public List<Entry> getEntryList() {
            return entryList;
        }

    }


    private static class InternalFieldGenerationEntry implements FieldGeneration.Entry {

        private final FieldKey fieldKey;
        private final FichothequeFormatDef fichothequeFormatDef;

        private InternalFieldGenerationEntry(FieldKey fieldKey, FichothequeFormatDef fichothequeFormatDef) {
            this.fieldKey = fieldKey;
            this.fichothequeFormatDef = fichothequeFormatDef;
        }

        @Override
        public FieldKey getFieldKey() {
            return fieldKey;
        }

        @Override
        public FichothequeFormatDef getFormatDef() {
            return fichothequeFormatDef;
        }

    }


    private static class EntryList extends AbstractList<FieldGeneration.Entry> implements RandomAccess {

        private final FieldGeneration.Entry[] array;

        private EntryList(FieldGeneration.Entry[] array) {
            this.array = array;
        }

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

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

    }

}
