package org.jivesoftware.smack.util;

import java.util.Collection;
import java.util.Iterator;
import org.jivesoftware.smack.packet.Element;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.NamedElement;

public class XmlStringBuilder implements Appendable, CharSequence {
   public static final String RIGHT_ANGLE_BRACKET = Character.toString('>');
   private final LazyStringBuilder sb;

   public XmlStringBuilder() {
      this.sb = new LazyStringBuilder();
   }

   public XmlStringBuilder(ExtensionElement pe) {
      this();
      this.prelude(pe);
   }

   public XmlStringBuilder(NamedElement e) {
      this();
      this.halfOpenElement(e.getElementName());
   }

   public XmlStringBuilder escapedElement(String name, String escapedContent) {
      assert escapedContent != null;

      this.openElement(name);
      this.append((CharSequence)escapedContent);
      this.closeElement(name);
      return this;
   }

   public XmlStringBuilder element(String name, String content) {
      assert content != null;

      this.openElement(name);
      this.escape(content);
      this.closeElement(name);
      return this;
   }

   public XmlStringBuilder element(String name, CharSequence content) {
      return this.element(name, content.toString());
   }

   public XmlStringBuilder element(String name, Enum<?> content) {
      assert content != null;

      this.element(name, content.name());
      return this;
   }

   public XmlStringBuilder element(Element element) {
      assert element != null;

      return this.append(element.toXML());
   }

   public XmlStringBuilder optElement(String name, String content) {
      if (content != null) {
         this.element(name, content);
      }

      return this;
   }

   public XmlStringBuilder optElement(String name, CharSequence content) {
      if (content != null) {
         this.element(name, content.toString());
      }

      return this;
   }

   public XmlStringBuilder optElement(Element element) {
      if (element != null) {
         this.append(element.toXML());
      }

      return this;
   }

   public XmlStringBuilder optElement(String name, Enum<?> content) {
      if (content != null) {
         this.element(name, content);
      }

      return this;
   }

   public XmlStringBuilder optIntElement(String name, int value) {
      if (value >= 0) {
         this.element(name, String.valueOf(value));
      }

      return this;
   }

   public XmlStringBuilder halfOpenElement(String name) {
      assert StringUtils.isNotEmpty(name);

      this.sb.append('<').append((CharSequence)name);
      return this;
   }

   public XmlStringBuilder halfOpenElement(NamedElement namedElement) {
      return this.halfOpenElement(namedElement.getElementName());
   }

   public XmlStringBuilder openElement(String name) {
      this.halfOpenElement(name).rightAngleBracket();
      return this;
   }

   public XmlStringBuilder closeElement(String name) {
      this.sb.append((CharSequence)"</").append((CharSequence)name);
      this.rightAngleBracket();
      return this;
   }

   public XmlStringBuilder closeElement(NamedElement e) {
      this.closeElement(e.getElementName());
      return this;
   }

   public XmlStringBuilder closeEmptyElement() {
      this.sb.append((CharSequence)"/>");
      return this;
   }

   public XmlStringBuilder rightAngleBracket() {
      this.sb.append((CharSequence)RIGHT_ANGLE_BRACKET);
      return this;
   }

   /** @deprecated */
   @Deprecated
   public XmlStringBuilder rightAngelBracket() {
      return this.rightAngleBracket();
   }

   public XmlStringBuilder attribute(String name, String value) {
      assert value != null;

      this.sb.append(' ').append((CharSequence)name).append((CharSequence)"='");
      this.escape(value);
      this.sb.append('\'');
      return this;
   }

   public XmlStringBuilder attribute(String name, CharSequence value) {
      return this.attribute(name, value.toString());
   }

   public XmlStringBuilder attribute(String name, Enum<?> value) {
      assert value != null;

      this.attribute(name, value.name());
      return this;
   }

   public XmlStringBuilder attribute(String name, int value) {
      assert name != null;

      return this.attribute(name, String.valueOf(value));
   }

   public XmlStringBuilder optAttribute(String name, String value) {
      if (value != null) {
         this.attribute(name, value);
      }

      return this;
   }

   public XmlStringBuilder optAttribute(String name, CharSequence value) {
      if (value != null) {
         this.attribute(name, value.toString());
      }

      return this;
   }

   public XmlStringBuilder optAttribute(String name, Enum<?> value) {
      if (value != null) {
         this.attribute(name, value.toString());
      }

      return this;
   }

   public XmlStringBuilder optIntAttribute(String name, int value) {
      if (value >= 0) {
         this.attribute(name, Integer.toString(value));
      }

      return this;
   }

   public XmlStringBuilder optLongAttribute(String name, Long value) {
      if (value != null && value >= 0L) {
         this.attribute(name, Long.toString(value));
      }

      return this;
   }

   public XmlStringBuilder optBooleanAttribute(String name, boolean bool) {
      if (bool) {
         this.sb.append(' ').append((CharSequence)name).append((CharSequence)"='true'");
      }

      return this;
   }

   public XmlStringBuilder xmlnsAttribute(String value) {
      this.optAttribute("xmlns", value);
      return this;
   }

   public XmlStringBuilder xmllangAttribute(String value) {
      this.optAttribute("xml:lang", value);
      return this;
   }

   public XmlStringBuilder escape(String text) {
      assert text != null;

      this.sb.append(StringUtils.escapeForXML(text));
      return this;
   }

   public XmlStringBuilder escape(CharSequence text) {
      return this.escape(text.toString());
   }

   public XmlStringBuilder prelude(ExtensionElement pe) {
      return this.prelude(pe.getElementName(), pe.getNamespace());
   }

   public XmlStringBuilder prelude(String elementName, String namespace) {
      this.halfOpenElement(elementName);
      this.xmlnsAttribute(namespace);
      return this;
   }

   public XmlStringBuilder optAppend(CharSequence csq) {
      if (csq != null) {
         this.append(csq);
      }

      return this;
   }

   public XmlStringBuilder optAppend(Element element) {
      if (element != null) {
         this.append(element.toXML());
      }

      return this;
   }

   public XmlStringBuilder append(XmlStringBuilder xsb) {
      assert xsb != null;

      this.sb.append(xsb.sb);
      return this;
   }

   public XmlStringBuilder append(Collection<? extends Element> elements) {
      Iterator i$ = elements.iterator();

      while(i$.hasNext()) {
         Element element = (Element)i$.next();
         this.append(element.toXML());
      }

      return this;
   }

   public XmlStringBuilder emptyElement(Enum<?> element) {
      return this.emptyElement(element.name());
   }

   public XmlStringBuilder emptyElement(String element) {
      this.halfOpenElement(element);
      return this.closeEmptyElement();
   }

   public XmlStringBuilder condEmptyElement(boolean condition, String element) {
      if (condition) {
         this.emptyElement(element);
      }

      return this;
   }

   public XmlStringBuilder condAttribute(boolean condition, String name, String value) {
      if (condition) {
         this.attribute(name, value);
      }

      return this;
   }

   public XmlStringBuilder append(CharSequence csq) {
      assert csq != null;

      this.sb.append(csq);
      return this;
   }

   public XmlStringBuilder append(CharSequence csq, int start, int end) {
      assert csq != null;

      this.sb.append(csq, start, end);
      return this;
   }

   public XmlStringBuilder append(char c) {
      this.sb.append(c);
      return this;
   }

   public int length() {
      return this.sb.length();
   }

   public char charAt(int index) {
      return this.sb.charAt(index);
   }

   public CharSequence subSequence(int start, int end) {
      return this.sb.subSequence(start, end);
   }

   public String toString() {
      return this.sb.toString();
   }

   public boolean equals(Object other) {
      if (!(other instanceof CharSequence)) {
         return false;
      } else {
         CharSequence otherCharSequenceBuilder = (CharSequence)other;
         return this.toString().equals(otherCharSequenceBuilder.toString());
      }
   }

   public int hashCode() {
      return this.toString().hashCode();
   }
}
