package org.jivesoftware.smack.packet;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.util.XmlStringBuilder;

public class XMPPError extends AbstractError {
   public static final String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-stanzas";
   public static final String ERROR = "error";
   private static final Logger LOGGER = Logger.getLogger(XMPPError.class.getName());
   private static final Map<XMPPError.Condition, XMPPError.Type> CONDITION_TO_TYPE = new HashMap();
   private final XMPPError.Condition condition;
   private final String conditionText;
   private final String errorGenerator;
   private final XMPPError.Type type;

   public XMPPError(XMPPError.Condition condition) {
      this(condition, (String)null, (String)null, (XMPPError.Type)null, (Map)null, (List)null);
   }

   public XMPPError(XMPPError.Condition condition, ExtensionElement applicationSpecificCondition) {
      this(condition, (String)null, (String)null, (XMPPError.Type)null, (Map)null, Arrays.asList(applicationSpecificCondition));
   }

   public XMPPError(XMPPError.Condition condition, String conditionText, String errorGenerator, XMPPError.Type type, Map<String, String> descriptiveTexts, List<ExtensionElement> extensions) {
      super(descriptiveTexts, "urn:ietf:params:xml:ns:xmpp-stanzas", extensions);
      this.condition = condition;
      if (StringUtils.isNullOrEmpty(conditionText)) {
         conditionText = null;
      }

      if (conditionText != null) {
         switch(condition) {
         case gone:
         case redirect:
            break;
         default:
            throw new IllegalArgumentException("Condition text can only be set with condtion types 'gone' and 'redirect', not " + condition);
         }
      }

      this.conditionText = conditionText;
      this.errorGenerator = errorGenerator;
      if (type == null) {
         XMPPError.Type determinedType = (XMPPError.Type)CONDITION_TO_TYPE.get(condition);
         if (determinedType == null) {
            LOGGER.warning("Could not determine type for condition: " + condition);
            determinedType = XMPPError.Type.CANCEL;
         }

         this.type = determinedType;
      } else {
         this.type = type;
      }

   }

   public XMPPError.Condition getCondition() {
      return this.condition;
   }

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

   public String getErrorGenerator() {
      return this.errorGenerator;
   }

   public String getConditionText() {
      return this.conditionText;
   }

   public String toString() {
      StringBuilder sb = new StringBuilder("XMPPError: ");
      sb.append(this.condition.toString()).append(" - ").append(this.type.toString());
      if (this.errorGenerator != null) {
         sb.append(". Generated by ").append(this.errorGenerator);
      }

      return sb.toString();
   }

   public XmlStringBuilder toXML() {
      XmlStringBuilder xml = new XmlStringBuilder();
      xml.halfOpenElement("error");
      xml.attribute("type", this.type.toString());
      xml.optAttribute("by", this.errorGenerator);
      xml.rightAngleBracket();
      xml.halfOpenElement(this.condition.toString());
      xml.xmlnsAttribute("urn:ietf:params:xml:ns:xmpp-stanzas");
      if (this.conditionText != null) {
         xml.rightAngleBracket();
         xml.escape(this.conditionText);
         xml.closeElement(this.condition.toString());
      } else {
         xml.closeEmptyElement();
      }

      this.addDescriptiveTextsAndExtensions(xml);
      xml.closeElement("error");
      return xml;
   }

   public static XMPPError from(XMPPError.Condition condition, String descriptiveText) {
      Map<String, String> descriptiveTexts = new HashMap();
      descriptiveTexts.put("en", descriptiveText);
      return new XMPPError(condition, (String)null, (String)null, (XMPPError.Type)null, descriptiveTexts, (List)null);
   }

   static {
      CONDITION_TO_TYPE.put(XMPPError.Condition.bad_request, XMPPError.Type.MODIFY);
      CONDITION_TO_TYPE.put(XMPPError.Condition.conflict, XMPPError.Type.CANCEL);
      CONDITION_TO_TYPE.put(XMPPError.Condition.feature_not_implemented, XMPPError.Type.CANCEL);
      CONDITION_TO_TYPE.put(XMPPError.Condition.forbidden, XMPPError.Type.AUTH);
      CONDITION_TO_TYPE.put(XMPPError.Condition.gone, XMPPError.Type.CANCEL);
      CONDITION_TO_TYPE.put(XMPPError.Condition.internal_server_error, XMPPError.Type.CANCEL);
      CONDITION_TO_TYPE.put(XMPPError.Condition.item_not_found, XMPPError.Type.CANCEL);
      CONDITION_TO_TYPE.put(XMPPError.Condition.jid_malformed, XMPPError.Type.MODIFY);
      CONDITION_TO_TYPE.put(XMPPError.Condition.not_acceptable, XMPPError.Type.MODIFY);
      CONDITION_TO_TYPE.put(XMPPError.Condition.not_allowed, XMPPError.Type.CANCEL);
      CONDITION_TO_TYPE.put(XMPPError.Condition.not_authorized, XMPPError.Type.AUTH);
      CONDITION_TO_TYPE.put(XMPPError.Condition.policy_violation, XMPPError.Type.MODIFY);
      CONDITION_TO_TYPE.put(XMPPError.Condition.recipient_unavailable, XMPPError.Type.WAIT);
      CONDITION_TO_TYPE.put(XMPPError.Condition.redirect, XMPPError.Type.MODIFY);
      CONDITION_TO_TYPE.put(XMPPError.Condition.registration_required, XMPPError.Type.AUTH);
      CONDITION_TO_TYPE.put(XMPPError.Condition.remote_server_not_found, XMPPError.Type.CANCEL);
      CONDITION_TO_TYPE.put(XMPPError.Condition.remote_server_timeout, XMPPError.Type.WAIT);
      CONDITION_TO_TYPE.put(XMPPError.Condition.resource_constraint, XMPPError.Type.WAIT);
      CONDITION_TO_TYPE.put(XMPPError.Condition.service_unavailable, XMPPError.Type.WAIT);
      CONDITION_TO_TYPE.put(XMPPError.Condition.subscription_required, XMPPError.Type.WAIT);
      CONDITION_TO_TYPE.put(XMPPError.Condition.unexpected_request, XMPPError.Type.MODIFY);
   }

   public static enum Condition {
      bad_request,
      conflict,
      feature_not_implemented,
      forbidden,
      gone,
      internal_server_error,
      item_not_found,
      jid_malformed,
      not_acceptable,
      not_allowed,
      not_authorized,
      policy_violation,
      recipient_unavailable,
      redirect,
      registration_required,
      remote_server_not_found,
      remote_server_timeout,
      resource_constraint,
      service_unavailable,
      subscription_required,
      undefined_condition,
      unexpected_request;

      public String toString() {
         return this.name().replace('_', '-');
      }

      public static XMPPError.Condition fromString(String string) {
         if ("xml-not-well-formed".equals(string)) {
            string = "not-well-formed";
         }

         string = string.replace('-', '_');
         XMPPError.Condition condition = null;

         try {
            condition = valueOf(string);
            return condition;
         } catch (Exception var3) {
            throw new IllegalStateException("Could not transform string '" + string + "' to XMPPErrorCondition", var3);
         }
      }
   }

   public static enum Type {
      WAIT,
      CANCEL,
      MODIFY,
      AUTH,
      CONTINUE;

      public String toString() {
         return this.name().toLowerCase();
      }

      public static XMPPError.Type fromString(String string) {
         string = string.toUpperCase();
         return valueOf(string);
      }
   }
}
