/*
 * Decompiled with CFR 0.152.
 */
package org.jivesoftware.smack.packet;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jxmpp.jid.Jid;

public final class Message
extends Stanza
implements Cloneable {
    public static final String ELEMENT = "message";
    public static final String BODY = "body";
    private Type type;
    private String thread = null;
    private final Set<Subject> subjects = new HashSet<Subject>();
    private final Set<Body> bodies = new HashSet<Body>();

    public Message() {
    }

    public Message(Jid to) {
        this.setTo(to);
    }

    public Message(Jid to, Type type) {
        this(to);
        this.setType(type);
    }

    public Message(Jid to, String body) {
        this(to);
        this.setBody(body);
    }

    public Message(Message other) {
        super(other);
        this.type = other.type;
        this.thread = other.thread;
        this.subjects.addAll(other.subjects);
        this.bodies.addAll(other.bodies);
    }

    public Type getType() {
        if (this.type == null) {
            return Type.normal;
        }
        return this.type;
    }

    public void setType(Type type) {
        this.type = type;
    }

    public String getSubject() {
        return this.getSubject(null);
    }

    public String getSubject(String language) {
        Subject subject = this.getMessageSubject(language);
        return subject == null ? null : subject.subject;
    }

    private Subject getMessageSubject(String language) {
        language = this.determineLanguage(language);
        for (Subject subject : this.subjects) {
            if (!language.equals(subject.language)) continue;
            return subject;
        }
        return null;
    }

    public Set<Subject> getSubjects() {
        return Collections.unmodifiableSet(this.subjects);
    }

    public void setSubject(String subject) {
        if (subject == null) {
            this.removeSubject("");
            return;
        }
        this.addSubject(null, subject);
    }

    public Subject addSubject(String language, String subject) {
        language = this.determineLanguage(language);
        Subject messageSubject = new Subject(language, subject);
        this.subjects.add(messageSubject);
        return messageSubject;
    }

    public boolean removeSubject(String language) {
        language = this.determineLanguage(language);
        for (Subject subject : this.subjects) {
            if (!language.equals(subject.language)) continue;
            return this.subjects.remove(subject);
        }
        return false;
    }

    public boolean removeSubject(Subject subject) {
        return this.subjects.remove(subject);
    }

    public List<String> getSubjectLanguages() {
        Subject defaultSubject = this.getMessageSubject(null);
        ArrayList<String> languages = new ArrayList<String>();
        for (Subject subject : this.subjects) {
            if (subject.equals(defaultSubject)) continue;
            languages.add(subject.language);
        }
        return Collections.unmodifiableList(languages);
    }

    public String getBody() {
        return this.getBody(null);
    }

    public String getBody(String language) {
        Body body = this.getMessageBody(language);
        return body == null ? null : body.message;
    }

    private Body getMessageBody(String language) {
        language = this.determineLanguage(language);
        for (Body body : this.bodies) {
            if (!language.equals(body.language)) continue;
            return body;
        }
        return null;
    }

    public Set<Body> getBodies() {
        return Collections.unmodifiableSet(this.bodies);
    }

    public void setBody(String body) {
        if (body == null) {
            this.removeBody("");
            return;
        }
        this.addBody(null, body);
    }

    public Body addBody(String language, String body) {
        language = this.determineLanguage(language);
        Body messageBody = new Body(language, body);
        this.bodies.add(messageBody);
        return messageBody;
    }

    public boolean removeBody(String language) {
        language = this.determineLanguage(language);
        for (Body body : this.bodies) {
            if (!language.equals(body.language)) continue;
            return this.bodies.remove(body);
        }
        return false;
    }

    public boolean removeBody(Body body) {
        return this.bodies.remove(body);
    }

    public List<String> getBodyLanguages() {
        Body defaultBody = this.getMessageBody(null);
        ArrayList<String> languages = new ArrayList<String>();
        for (Body body : this.bodies) {
            if (body.equals(defaultBody)) continue;
            languages.add(body.language);
        }
        return Collections.unmodifiableList(languages);
    }

    public String getThread() {
        return this.thread;
    }

    public void setThread(String thread) {
        this.thread = thread;
    }

    private String determineLanguage(String language) {
        String string = language = "".equals(language) ? null : language;
        if (language == null && this.language != null) {
            return this.language;
        }
        if (language == null) {
            return Message.getDefaultLanguage();
        }
        return language;
    }

    @Override
    public XmlStringBuilder toXML() {
        XmlStringBuilder buf = new XmlStringBuilder();
        buf.halfOpenElement(ELEMENT);
        this.addCommonAttributes(buf);
        buf.optAttribute("type", this.type);
        buf.rightAngleBracket();
        Subject defaultSubject = this.getMessageSubject(null);
        if (defaultSubject != null) {
            buf.element("subject", defaultSubject.subject);
        }
        for (Subject subject : this.getSubjects()) {
            if (subject.equals(defaultSubject)) continue;
            buf.halfOpenElement("subject").xmllangAttribute(subject.language).rightAngleBracket();
            buf.escape(subject.subject);
            buf.closeElement("subject");
        }
        Body defaultBody = this.getMessageBody(null);
        if (defaultBody != null) {
            buf.element(BODY, defaultBody.message);
        }
        for (Body body : this.getBodies()) {
            if (body.equals(defaultBody)) continue;
            buf.halfOpenElement(BODY).xmllangAttribute(body.getLanguage()).rightAngleBracket();
            buf.escape(body.getMessage());
            buf.closeElement(BODY);
        }
        buf.optElement("thread", this.thread);
        if (this.type == Type.error) {
            this.appendErrorIfExists(buf);
        }
        buf.append(this.getExtensionsXML());
        buf.closeElement(ELEMENT);
        return buf;
    }

    public Message clone() {
        return new Message(this);
    }

    public static enum Type {
        normal,
        chat,
        groupchat,
        headline,
        error;


        public static Type fromString(String string) {
            return Type.valueOf(string.toLowerCase(Locale.US));
        }
    }

    public static class Body {
        private final String message;
        private final String language;

        private Body(String language, String message) {
            if (language == null) {
                throw new NullPointerException("Language cannot be null.");
            }
            if (message == null) {
                throw new NullPointerException("Message cannot be null.");
            }
            this.language = language;
            this.message = message;
        }

        public String getLanguage() {
            return this.language;
        }

        public String getMessage() {
            return this.message;
        }

        public int hashCode() {
            int prime = 31;
            int result = 1;
            result = 31 * result + this.language.hashCode();
            result = 31 * result + this.message.hashCode();
            return result;
        }

        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (this.getClass() != obj.getClass()) {
                return false;
            }
            Body other = (Body)obj;
            return this.language.equals(other.language) && this.message.equals(other.message);
        }
    }

    public static class Subject {
        private final String subject;
        private final String language;

        private Subject(String language, String subject) {
            if (language == null) {
                throw new NullPointerException("Language cannot be null.");
            }
            if (subject == null) {
                throw new NullPointerException("Subject cannot be null.");
            }
            this.language = language;
            this.subject = subject;
        }

        public String getLanguage() {
            return this.language;
        }

        public String getSubject() {
            return this.subject;
        }

        public int hashCode() {
            int prime = 31;
            int result = 1;
            result = 31 * result + this.language.hashCode();
            result = 31 * result + this.subject.hashCode();
            return result;
        }

        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (this.getClass() != obj.getClass()) {
                return false;
            }
            Subject other = (Subject)obj;
            return this.language.equals(other.language) && this.subject.equals(other.subject);
        }
    }
}
