/*
 * Copyright (c) 2025 Rostock University Library
 * Licensed under the MIT License. See LICENSE file in the project root.
 */
package de.uni.rostock.ub.wsrb.edition.webapp.service;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;

import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import de.uni.rostock.ub.wsrb.edition.webapp.util.WSRBUtil;
import jakarta.annotation.PostConstruct;

@Service
public class DataService {
    private static final Logger LOGGER = LoggerFactory.getLogger(DataService.class);

    private static final QName QNAME_ATTR_XML_ID = new QName(XMLConstants.XML_NS_URI, "id");

    @Value("${wsrb.folder.teixml}")
    private String teixmlFolder;

    @Value("${wsrb.transkription.ids}")
    private List<String> transkriptionIds;

    @Value("${wsrb.edition.id}")
    private String editionId;

    private Map<String, Long> lineNrById = new ConcurrentHashMap<>();

    private XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();

    @PostConstruct
    private void init() {
        Stream<String> resources = Stream.concat(
            List.of(teixmlFolder + "edition/" + editionId + WSRBUtil.TEI_FILE_EXTENSION).stream(),
            transkriptionIds.stream()
                .map(trid -> teixmlFolder + "transkriptionen/" + trid + WSRBUtil.TEI_FILE_EXTENSION));
        resources.forEach(rp -> {
            initLineNumbers(xmlInputFactory, rp);
        });
    }

    private void initLineNumbers(XMLInputFactory xmlInputFactory, String rp) {
        try (InputStream is = getClass().getResourceAsStream(rp)) {
            XMLEventReader reader = xmlInputFactory.createXMLEventReader(is);
            while (reader.hasNext()) {
                XMLEvent nextEvent = reader.nextEvent();
                processElementForLineNumbers(nextEvent, rp);

            }
        } catch (IOException | XMLStreamException e1) {
            LOGGER.error("Error parsing line numbers", e1);
        }
    }

    private void processElementForLineNumbers(XMLEvent nextEvent, String rp) {
        if (nextEvent.isStartElement()) {
            StartElement startElement = nextEvent.asStartElement();
            if (startElement.getAttributeByName(QNAME_ATTR_XML_ID) != null) {
                String id = startElement.getAttributeByName(QNAME_ATTR_XML_ID).getValue();
                if (id.startsWith("tax.") || id.startsWith("facs")) {
                    return;
                }
                if (!id.startsWith("wsrb")) {
                    id = rp.substring(rp.lastIndexOf('/') + 1, rp.lastIndexOf(WSRBUtil.TEI_FILE_EXTENSION)) + "__" + id;
                }
                long linenr = startElement.getLocation().getLineNumber();
                lineNrById.put(id, linenr);
            }
        }

    }

    /**
     * return a JSONString from an object with key = xml:id + value = lineNumber in the given resource
     * xml:id attribute must be unique between all sources
     */
    public Map<String, Long> retrieveIdToLineMap() {
        return lineNrById;
    }

}
