/* BdfServer - Copyright (c) 2012-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.mapeadores.util.logging;

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;


/**
 *
 * @author Vincent Calame
 */
public class LineLogsBuilder implements LineMessageHandler {

    private final SortedMap<Integer, LineLogBuilder> lineLogBuilderMap = new TreeMap<Integer, LineLogBuilder>();

    public LineLogsBuilder() {
    }

    @Override
    public void addMessage(LineMessage message) {
        int lineNumber = message.getLineNumber();
        LineLogBuilder lineLogBuilder = lineLogBuilderMap.get(lineNumber);
        if (lineLogBuilder == null) {
            lineLogBuilder = new LineLogBuilder(lineNumber);
            lineLogBuilderMap.put(lineNumber, lineLogBuilder);
        }
        lineLogBuilder.add(message);
    }

    public boolean hasMessage() {
        return (!lineLogBuilderMap.isEmpty());
    }

    public LineLogs toLineLogs() {
        int size = lineLogBuilderMap.size();
        LineLog[] array = new LineLog[size];
        int p = 0;
        for (LineLogBuilder lineLogBuilder : lineLogBuilderMap.values()) {
            array[p] = lineLogBuilder.toLineLog();
            p++;
        }
        return new InternalLineLogs(array);
    }

    public List<LineMessage> toLineMessageList() {
        List<LineMessage> result = new ArrayList<LineMessage>();
        for (LineLogBuilder lineLogBuilder : lineLogBuilderMap.values()) {
            result.addAll(lineLogBuilder.messageList);
        }
        return result;
    }

    public static LineLogsBuilder init() {
        return new LineLogsBuilder();
    }


    private static class LineLogBuilder {

        private final int lineNumber;
        private final List<LineMessage> messageList = new ArrayList<LineMessage>();

        private LineLogBuilder(int lineNumber) {
            this.lineNumber = lineNumber;
        }

        private void add(LineMessage message) {
            messageList.add(message);
        }

        private LineLog toLineLog() {
            List<LineMessage> finalMessageList = LogUtils.wrap(messageList.toArray(new LineMessage[messageList.size()]));
            return new InternalLineLog(lineNumber, finalMessageList);
        }

    }


    private static class InternalLineLog implements LineLog {

        private final int lineNumber;
        private final List<LineMessage> messageList;

        private InternalLineLog(int lineNumber, List<LineMessage> messageList) {
            this.lineNumber = lineNumber;
            this.messageList = messageList;
        }

        @Override
        public int getLineNumber() {
            return lineNumber;
        }

        @Override
        public List<LineMessage> getLineMessageList() {
            return messageList;
        }

    }


    private static class InternalLineLogs extends AbstractList<LineLog> implements LineLogs {

        private final LineLog[] array;

        private InternalLineLogs(LineLog[] array) {
            this.array = array;
        }

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

        @Override
        public LineLog get(int i) {
            return array[i];
        }

    }

}
