package org.jivesoftware.smackx.signed.xep0285.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.XmlStringBuilder;
import org.jivesoftware.smack.util.stringencoder.Base64;

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

public final class PlainElement implements ExtensionElement {

    public static final String ELEMENT = "plain";
    public static final String NAMESPACE = "urn:xmpp:signed:0";
    public static final String ATTR_TIMESTAMP = "timestamp";

    private final String utf8Content;
    private final String base64Content;
    private final Date timestamp;

    private PlainElement(String utf8Content, String base64Content, Date timestamp) {
        this.utf8Content = utf8Content;
        this.base64Content = base64Content;
        this.timestamp = timestamp;
    }

    public static PlainElement fromExtensionElement(ExtensionElement element) {
        return fromUtf8String(element.toXML().toString(), new Date());
    }

    public static PlainElement fromUtf8String(String utf8, Date timestamp) {
        return new PlainElement(utf8, Base64.encodeToString(utf8.getBytes(StandardCharsets.UTF_8)), timestamp);
    }

    public static PlainElement fromBase64String(String base64, Date timestamp) {
        return new PlainElement(Base64.decodeToString(base64), base64, timestamp);
    }

    public String getBase64Content() {
        return base64Content;
    }

    public String getUtf8Content() {
        return utf8Content;
    }

    public byte[] asUtf8Bytes() {
        return toXML().toString().getBytes(StandardCharsets.UTF_8);
    }

    public Date getTimestamp() {
        return timestamp;
    }

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

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

    @Override
    public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) {
        return new XmlStringBuilder(this)
                .attribute(ATTR_TIMESTAMP, getTimestamp())
                .rightAngleBracket()
                .append(getBase64Content())
                .closeElement(this);
    }

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

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