package org.jivesoftware.smack.packet;

import java.util.Locale;
import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.util.XmlStringBuilder;

public abstract class IQ extends Stanza {
   public static final String IQ_ELEMENT = "iq";
   public static final String QUERY_ELEMENT = "query";
   private final String childElementName;
   private final String childElementNamespace;
   private IQ.Type type;

   public IQ(IQ iq) {
      super((Stanza)iq);
      this.type = IQ.Type.get;
      this.type = iq.getType();
      this.childElementName = iq.childElementName;
      this.childElementNamespace = iq.childElementNamespace;
   }

   protected IQ(String childElementName) {
      this(childElementName, (String)null);
   }

   protected IQ(String childElementName, String childElementNamespace) {
      this.type = IQ.Type.get;
      this.childElementName = childElementName;
      this.childElementNamespace = childElementNamespace;
   }

   public IQ.Type getType() {
      return this.type;
   }

   public void setType(IQ.Type type) {
      this.type = (IQ.Type)Objects.requireNonNull(type, "type must not be null");
   }

   public boolean isRequestIQ() {
      switch(this.type) {
      case get:
      case set:
         return true;
      default:
         return false;
      }
   }

   public final String getChildElementName() {
      return this.childElementName;
   }

   public final String getChildElementNamespace() {
      return this.childElementNamespace;
   }

   public final XmlStringBuilder toXML() {
      XmlStringBuilder buf = new XmlStringBuilder();
      buf.halfOpenElement("iq");
      this.addCommonAttributes(buf);
      if (this.type == null) {
         buf.attribute("type", "get");
      } else {
         buf.attribute("type", this.type.toString());
      }

      buf.rightAngleBracket();
      buf.append(this.getChildElementXML());
      buf.closeElement("iq");
      return buf;
   }

   public final XmlStringBuilder getChildElementXML() {
      XmlStringBuilder xml = new XmlStringBuilder();
      if (this.type == IQ.Type.error) {
         this.appendErrorIfExists(xml);
      } else if (this.childElementName != null) {
         IQ.IQChildElementXmlStringBuilder iqChildElement = this.getIQChildElementBuilder(new IQ.IQChildElementXmlStringBuilder(this));
         if (iqChildElement != null) {
            xml.append((XmlStringBuilder)iqChildElement);
            XmlStringBuilder extensionsXml = this.getExtensionsXML();
            if (iqChildElement.isEmptyElement) {
               if (extensionsXml.length() == 0) {
                  xml.closeEmptyElement();
                  return xml;
               }

               xml.rightAngleBracket();
            }

            xml.append(extensionsXml);
            xml.closeElement(iqChildElement.element);
         }
      }

      return xml;
   }

   protected abstract IQ.IQChildElementXmlStringBuilder getIQChildElementBuilder(IQ.IQChildElementXmlStringBuilder var1);

   public static IQ createResultIQ(IQ request) {
      return new EmptyResultIQ(request);
   }

   public static ErrorIQ createErrorResponse(IQ request, XMPPError error) {
      if (request.getType() != IQ.Type.get && request.getType() != IQ.Type.set) {
         throw new IllegalArgumentException("IQ must be of type 'set' or 'get'. Original IQ: " + request.toXML());
      } else {
         ErrorIQ result = new ErrorIQ(error);
         result.setStanzaId(request.getStanzaId());
         result.setFrom(request.getTo());
         result.setTo(request.getFrom());
         return result;
      }
   }

   public static class IQChildElementXmlStringBuilder extends XmlStringBuilder {
      private final String element;
      private boolean isEmptyElement;

      private IQChildElementXmlStringBuilder(IQ iq) {
         this(iq.getChildElementName(), iq.getChildElementNamespace());
      }

      public IQChildElementXmlStringBuilder(ExtensionElement pe) {
         this(pe.getElementName(), pe.getNamespace());
      }

      private IQChildElementXmlStringBuilder(String element, String namespace) {
         this.prelude(element, namespace);
         this.element = element;
      }

      public void setEmptyElement() {
         this.isEmptyElement = true;
      }

      // $FF: synthetic method
      IQChildElementXmlStringBuilder(IQ x0, Object x1) {
         this(x0);
      }
   }

   public static enum Type {
      get,
      set,
      result,
      error;

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