package org.jivesoftware.smackx.ikey.element;

import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.util.EqualsUtil;
import org.jivesoftware.smack.util.HashCode;
import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smack.util.stringencoder.Base64;
import org.jivesoftware.smackx.ikey.util.IkeyConstants;
import org.jxmpp.jid.EntityBareJid;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;

public class SubordinateListElement implements ExtensionElement {

    public static final String NAMESPACE = IkeyConstants.NAMESPACE;
    public static final String ELEMENT = "subordinates";
    public static final String ATTR_JID = "jid";
    public static final String ATTR_STAMP = "stamp";

    private final List<SubordinateElement> subordinates;
    private final EntityBareJid jid;
    private final Date timestamp;

    public SubordinateListElement(EntityBareJid jid, Date timestamp, List<SubordinateElement> subordinates) {
        this.jid = jid;
        this.timestamp = timestamp;
        this.subordinates = Objects.requireNonNullNorEmpty(subordinates, "List of subordinates MUST NOT be null nor empty.");
    }

    public EntityBareJid getJid() {
        return jid;
    }

    public Date getTimestamp() {
        return timestamp;
    }

    public List<SubordinateElement> getSubordinates() {
        return subordinates;
    }

    public String toBase64EncodedString() {
        return Base64.encodeToString(toXML().toString().getBytes(StandardCharsets.UTF_8));
    }

    @Override
    public String getElementName() {
        return ELEMENT;
    }

    @Override
    public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) {
        return new XmlStringBuilder(this)
                .attribute(ATTR_JID, getJid())
                .attribute(ATTR_STAMP, getTimestamp())
                .rightAngleBracket()
                .append(getSubordinates())
                .closeElement(this);
    }

    @Override
    public int hashCode() {
        return HashCode.builder()
                .append(getElementName())
                .append(getJid())
                .append(getTimestamp())
                .append(getSubordinates())
                .build();
    }

    @Override
    public boolean equals(Object other) {
        return EqualsUtil.equals(this, other, (e, o) -> e
                .append(getElementName(), o.getElementName())
                .append(getJid(), o.getJid())
                .append(getTimestamp(), o.getTimestamp())
                .append(getSubordinates(), o.getSubordinates()));
    }

    @Override
    public String getNamespace() {
        return NAMESPACE;
    }
}
