package org.jivesoftware.smackx.ikey.provider;

import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.ikey.element.IkeyElement;
import org.jivesoftware.smackx.ikey.element.ProofElement;
import org.jivesoftware.smackx.ikey.element.SubordinateElement;
import org.jivesoftware.smackx.ikey.element.SubordinateListElement;
import org.jivesoftware.smackx.ikey.element.SuperordinateElement;
import org.jivesoftware.smackx.ikey.mechanism.IkeyType;
import org.jxmpp.jid.EntityBareJid;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class IkeyElementProvider extends ExtensionElementProvider<IkeyElement> {

    public static final IkeyElementProvider INSTANCE = new IkeyElementProvider();

    @Override
    public IkeyElement parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment)
            throws XmlPullParserException, IOException, SmackParsingException {
        String typeString = ParserUtils.getRequiredAttribute(parser, IkeyElement.ATTR_IKEY_TYPE);
        IkeyType type = IkeyType.valueOf(typeString);
        SuperordinateElement superordinate = null;
        List<SubordinateElement> subordinates = new ArrayList<>();
        EntityBareJid jid = null;
        Date timestamp = null;
        ProofElement proofElement = null;

        do {
            switch (parser.nextTag()) {
                case START_ELEMENT:
                    switch (parser.getName()) {

                        case SuperordinateElement.ELEMENT:
                            superordinate = new SuperordinateElement(parser.nextText());
                            break;

                        case SubordinateListElement.ELEMENT:
                            jid = ParserUtils.getBareJidAttribute(parser);
                            timestamp = ParserUtils.getDateFromXep82String(
                                    ParserUtils.getRequiredAttribute(parser, SubordinateListElement.ATTR_STAMP));
                            break;

                        case SubordinateElement.ELEMENT:
                            String uriString = ParserUtils.getRequiredAttribute(parser, SubordinateElement.ATTR_SUB_URI);
                            URI uri = URI.create(uriString);
                            String fingerprint = ParserUtils.getRequiredAttribute(parser, SubordinateElement.ATTR_SUB_FINGERPRINT);
                            subordinates.add(new SubordinateElement(uri, fingerprint));
                            break;

                        case ProofElement.ELEMENT:
                            proofElement = new ProofElement(parser.nextText());
                            break;
                    }
                    break;
                case END_ELEMENT:
                    break;
            }
        } while (parser.getDepth() != initialDepth);
        return new IkeyElement(type, superordinate, new SubordinateListElement(jid, timestamp, subordinates), proofElement);
    }
}
