package be.iminds.ilabt.jfed.rspec.parser.extensions;

import be.iminds.ilabt.jfed.lowlevel.api.user_spec.UserSpec;
import javanet.staxutils.IndentingXMLEventWriter;

import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import java.io.StringWriter;
import java.util.List;
import java.util.concurrent.Callable;

import static be.iminds.ilabt.jfed.rspec.parser.RspecXmlConstants.*;

/**
 * User: twalcari
 * Date: 3/9/2015
 * Time: 15:00
 */
public class UserSpecWriter implements Callable<String> {

    private final List<UserSpec> userSpecs;

    public UserSpecWriter(List<UserSpec> userSpecs) {
        this.userSpecs = userSpecs;
    }

    @Override
    public String call() throws Exception {
        try {
            //note: this requires woodstox, or namespaces get mesXMLsed up. This is due to a strange bug related to attribute namespaces.
            // see for some info: http://stackoverflow.com/questions/3068901/xmloutputstream-repairing-namespaces-and-attributes-without-namespaces
            //                    not that the solution there does not work for XMLEventWriter

            XMLEventFactory eventFactory = XMLEventFactory.newInstance();

            XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
            outputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
            StringWriter sw = new StringWriter();

            for (UserSpec userSpec : userSpecs) {
                XMLEventWriter innerEventWriter = outputFactory.createXMLEventWriter(sw);
                XMLEventWriter eventWriter = new IndentingXMLEventWriter(innerEventWriter);
                eventWriter.setDefaultNamespace(NAMESPACE_JFED_SSH);

                writeUserSpec(eventFactory, eventWriter, userSpec);
                
                eventWriter.add(eventFactory.createEndDocument());
                eventWriter.close();

                sw.append('\n');
            }

            return sw.toString();
        } catch (XMLStreamException e) {
            throw new RuntimeException("Problem writing RSpec", e);
        }
    }

    public static void writeUserSpec(XMLEventFactory eventFactory, XMLEventWriter eventWriter, UserSpec userSpec) throws XMLStreamException {

        eventWriter.add(eventFactory.createStartElement(Q_JFEDSSH_USER_SSH_KEYS, null, null));

        if (userSpec.getUrn() != null)
            eventWriter.add(eventFactory.createAttribute(Q_JFEDSSH_USER, userSpec.getUrn()));


        for (String userKey : userSpec.getSshKey()) {
            eventWriter.add(eventFactory.createStartElement(Q_JFEDSSH_KEY, null, null));
            eventWriter.add(eventFactory.createCharacters(trimSshKey(userKey)));
            eventWriter.add(eventFactory.createEndElement(Q_JFEDSSH_KEY, null));
        }

        eventWriter.add(eventFactory.createEndElement(Q_JFEDSSH_USER_SSH_KEYS, null));
    }

    public static String trimSshKey(String input) {
        return input.replace("\n", "").replace("\r", "").trim();
    }
}
