/*
 * This file is part of ***  M y C o R e  ***
 * See http://www.mycore.de/ for details.
 *
 * MyCoRe is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * MyCoRe is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with MyCoRe.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.mycore.frontend.xeditor.tracker;

import java.io.IOException;
import java.io.StringReader;

import org.jdom2.Attribute;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.ProcessingInstruction;
import org.jdom2.Text;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.mycore.common.MCRException;

public class MCRChangeData {

    protected String type;

    protected int pos;

    protected Element context;

    protected String text;

    protected ProcessingInstruction pi;

    private static final XMLOutputter RAW_OUTPUTTER = new XMLOutputter(Format.getRawFormat().setEncoding("UTF-8"));

    public MCRChangeData(String type, String text, int pos, Element context) {
        this.type = type;
        this.text = text;
        this.pos = pos;
        this.context = context;
    }

    public MCRChangeData(String type, Attribute attribute) {
        this(type, attribute2text(attribute), 0, attribute.getParent());
    }

    public MCRChangeData(String type, Element data, int pos, Element context) {
        this(type, element2text(data), pos, context);
    }

    public ProcessingInstruction getProcessingInstruction() {
        if (pi == null) {
            String data = RAW_OUTPUTTER.outputString(new Text(text));
            this.pi = new ProcessingInstruction(type, data);
        }
        return pi;
    }

    public MCRChangeData(ProcessingInstruction pi, String prefix) {
        this.pi = pi;
        this.context = pi.getParentElement();
        this.pos = context.indexOf(pi);
        this.type = pi.getTarget().substring(prefix.length());

        String xml = "<x>" + pi.getData() + "</x>";
        this.text = text2element(xml).getText();
    }

    public String getType() {
        return type;
    }

    public Element getContext() {
        return context;
    }

    public int getPosition() {
        return pos;
    }

    public String getText() {
        return text;
    }

    public Element getElement() {
        return text2element(text);
    }

    public Attribute getAttribute() {
        return text2attribute(text);
    }

    private static String element2text(Element element) {
        return RAW_OUTPUTTER.outputString(element);
    }

    private Element text2element(String text) {
        try {
            return new SAXBuilder().build(new StringReader(text)).detachRootElement();
        } catch (JDOMException | IOException ex) {
            throw new MCRException("Exception in text2element: " + text, ex);
        }
    }

    private static String attribute2text(Attribute attribute) {
        Element x = new Element("x").setAttribute(attribute.clone());
        String text = element2text(x);
        return text.substring(3, text.length() - 2).trim();
    }

    public Attribute text2attribute(String text) {
        String xtext = "<x " + text + " />";
        return text2element(xtext).getAttributes().get(0).detach();
    }
}
