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

import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.stream.Location;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import java.io.IOException;
import java.io.Writer;

public class IndentingXMLEventWriter implements XMLEventWriter {
    private final XMLEventWriter core;
    private String indent = "    ";
    private final Characters indentEvent = new CharactersImpl() {
        public String getData() {
            return IndentingXMLEventWriter.this.indent;
        }
    };
    private String newLine;
    private final Characters newLineEvent = new CharactersImpl() {
        public String getData() {
            return IndentingXMLEventWriter.this.newLine;
        }
    };
    private int depth = 0;
    private boolean hasText;
    private boolean hasEndTag;

    public IndentingXMLEventWriter(XMLEventWriter core) {
        if (core == null) {
            throw new IllegalArgumentException();
        } else {
            this.core = core;

            try {
                this.newLine = System.getProperty("line.separator");
            } catch (SecurityException var3) {
                this.newLine = "\n";
            }

        }
    }

    public String getIndent() {
        return this.indent;
    }

    public void setIndent(String indent) {
        if (indent == null) {
            throw new IllegalArgumentException();
        } else {
            this.indent = indent;
        }
    }

    public String getNewLine() {
        return this.newLine;
    }

    public void setNewLine(String newLine) {
        if (newLine == null) {
            throw new IllegalArgumentException();
        } else {
            this.newLine = newLine;
        }
    }

    public void add(XMLEvent event) throws XMLStreamException {
        switch (event.getEventType()) {
            case 1:
                this.newLine();
                this.core.add(event);
                this.hasText = false;
                this.hasEndTag = false;
                ++this.depth;
                return;
            case 2:
                --this.depth;
                if (!this.hasText && this.hasEndTag) {
                    this.newLine();
                }

                this.core.add(event);
                this.hasText = false;
                this.hasEndTag = true;
                return;
            case 3:
            case 5:
            case 11:
                if (!this.hasText) {
                    this.newLine();
                }

                this.core.add(event);
                return;
            case 4:
            case 6:
            case 12:
                if (event.asCharacters().isWhiteSpace()) {
                    return;
                }

                this.hasText = true;
                this.core.add(event);
                return;
            case 7:
            case 9:
            case 10:
            default:
                this.core.add(event);
                return;
            case 8:
                this.core.add(event);
                this.flush();
        }
    }

    private void newLine() throws XMLStreamException {
        this.core.add(this.newLineEvent);

        for (int i = 0; i < this.depth; ++i) {
            this.core.add(this.indentEvent);
        }

    }

    public void add(XMLEventReader reader) throws XMLStreamException {
        if (reader == null) {
            throw new IllegalArgumentException();
        } else {
            while (reader.hasNext()) {
                this.add(reader.nextEvent());
            }

        }
    }

    public void close() throws XMLStreamException {
        this.core.close();
    }

    public void flush() throws XMLStreamException {
        this.core.flush();
    }

    public NamespaceContext getNamespaceContext() {
        return this.core.getNamespaceContext();
    }

    public void setNamespaceContext(NamespaceContext context) throws XMLStreamException {
        this.core.setNamespaceContext(context);
    }

    public String getPrefix(String uri) throws XMLStreamException {
        return this.core.getPrefix(uri);
    }

    public void setDefaultNamespace(String uri) throws XMLStreamException {
        this.core.setDefaultNamespace(uri);
    }

    public void setPrefix(String prefix, String uri) throws XMLStreamException {
        this.core.setPrefix(prefix, uri);
    }

    private abstract static class CharactersImpl implements Characters {
        private CharactersImpl() {
        }

        public boolean isWhiteSpace() {
            return true;
        }

        public boolean isCData() {
            return false;
        }

        public boolean isIgnorableWhiteSpace() {
            return true;
        }

        public int getEventType() {
            return 4;
        }

        public Location getLocation() {
            return null;
        }

        public boolean isStartElement() {
            return false;
        }

        public boolean isAttribute() {
            return false;
        }

        public boolean isNamespace() {
            return false;
        }

        public boolean isEndElement() {
            return false;
        }

        public boolean isEntityReference() {
            return false;
        }

        public boolean isProcessingInstruction() {
            return false;
        }

        public boolean isCharacters() {
            return true;
        }

        public boolean isStartDocument() {
            return false;
        }

        public boolean isEndDocument() {
            return false;
        }

        public StartElement asStartElement() {
            return null;
        }

        public EndElement asEndElement() {
            return null;
        }

        public Characters asCharacters() {
            return this;
        }

        public QName getSchemaType() {
            return null;
        }

        public void writeAsEncodedUnicode(Writer writer) throws XMLStreamException {
            try {
                writer.write(this.getData());
            } catch (IOException var3) {
                throw new XMLStreamException(var3);
            }
        }
    }
}
