package ru.nbch.credit_tracker.service.xml.stax;

import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.events.XMLEvent;
import java.util.List;

public class WriterWrapper {
    private final XMLEventFactory xmlEventFactory;
    private final XMLEventWriter writer;
    private final int batchSize = 2500;

    public WriterWrapper(XMLEventFactory xmlEventFactory, XMLEventWriter writer) {
        this.xmlEventFactory = xmlEventFactory;
        this.writer = writer;
    }

    public void flush() throws Exception {
        writer.flush();
    }


    public void addStartDocument(String charsetName, String version, boolean standalone) throws Exception {
        writer.add(xmlEventFactory.createStartDocument(charsetName, version, standalone));
    }

    public void addStartDocument(String charsetName) throws Exception {
        writer.add(xmlEventFactory.createStartDocument(charsetName));
    }

    public void addDTD(String value) throws Exception {
        writer.add(xmlEventFactory.createDTD(value));
    }

    public void addEndDocument() throws Exception {
        writer.add(xmlEventFactory.createEndDocument());
    }

    public void addStartElement(String name) throws Exception {
        writer.add(createStartElement(name));
    }

    public void addEndElement(String name) throws Exception {
        writer.add(createEndElement(name));
    }

    public void addAttribute(String name, String value) throws Exception {
        if(value != null) {
            writer.add(createAttribute(name, value));
        }
    }

    public void addSimplelement(String name, String value) throws Exception {
        if (value == null) {
            return;
        }
        writer.add(createStartElement(name));
        writer.add(createCharacters(value));
        writer.add(createEndElement(name));
    }

    public void addCharacters(String value) throws Exception {
        if (value == null) {
            return;
        }
        writer.add(createCharacters(value));
    }

    public <T> void writeCollection(String name, List<T> collection, ObjectWriterAction<T> action) throws Exception {
        if (collection == null || collection.isEmpty()) {
            return;
        }

        for (int i = 0; i < collection.size(); i++) {
            T obj = collection.get(i);
            if (obj != null) {
                action.write(obj, name);
            }

            if (i % batchSize == 0) {
                writer.flush();
            }
        }
    }

    public void add(XMLEvent event) throws Exception {
        writer.add(event);
    }

    private XMLEvent createCharacters(String text) {
        return xmlEventFactory.createCharacters(text);
    }

    public XMLEvent createStartElement(String name) {
        return xmlEventFactory.createStartElement("", "", name);
    }

    public XMLEvent createEndElement(String name) {
        return xmlEventFactory.createEndElement("", "", name);
    }

    private XMLEvent createAttribute(String name, String value) {
        return xmlEventFactory.createAttribute(name, value);
    }

    public interface ObjectWriterAction<T> {
        void write(T obj, String name) throws Exception;
    }
}
