package ru.nbch.credit_tracker.utils.xml;


import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.PropertyException;
import org.eclipse.persistence.internal.oxm.record.CharacterEscapeHandlerWrapper;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.oxm.CharacterEscapeHandler;
//!!! was in <artifactId>eclipselink</artifactId> dependency
//import org.glassfish.jaxb.core.marshaller.DumbEscapeHandler;
//import org.glassfish.jaxb.core.marshaller.MinimumEscapeHandler;

public class EscapeHandlerUtil {
    public static CharacterEscapeHandler createEscapeHandler(Marshaller marshaller) throws PropertyException {
        org.eclipse.persistence.internal.oxm.CharacterEscapeHandler handler = null;
        String encoding = (String) marshaller.getProperty(Marshaller.JAXB_ENCODING);
        Object escapeHandler = marshaller.getProperty(MarshallerProperties.CHARACTER_ESCAPE_HANDLER);
        if (encoding == null) encoding = "UTF-8";
        try {
            if (escapeHandler != null) {
                try {
                    handler = (CharacterEscapeHandler) escapeHandler;
                } catch (Exception ignored) {
                    handler = new CharacterEscapeHandlerWrapper(escapeHandler);
                }
            }
            else {
                handler = new NioEscapeHandler(encoding);
            }
        } catch (Exception ignored) {
            handler = DumbEscapeHandler.theInstance;
        }
        var finalHandler = handler;
        return (ch, start, length, isAttVal, out) -> {
            int limit = start + length;
            int startToWrite = start;
            int endToWrite;
            for (int i = start; i < limit; ++i) {
                if (ch[i] == '<' || ch[i] == '>') {
                    if (i > start) {
                        endToWrite = i;//1;
                        finalHandler.escape(ch, startToWrite, endToWrite - startToWrite, isAttVal, out);
                        startToWrite = i + 1;
                    } else {
                        startToWrite++;
                    }
                    out.write(ch[i]);
                }
            }
            if (startToWrite < limit) {
                endToWrite = limit - startToWrite;
                finalHandler.escape(ch, startToWrite, endToWrite, isAttVal, out);
            }
        };
    }

}

