package org.jxmpp.util;

import org.jxmpp.util.cache.LruCache;

public class XmppStringUtils {
   private static final LruCache<String, String> LOCALPART_ESACPE_CACHE = new LruCache(100);
   private static final LruCache<String, String> LOCALPART_UNESCAPE_CACHE = new LruCache(100);

   public static String parseLocalpart(String jid) {
      int atIndex = jid.indexOf(64);
      if (atIndex <= 0) {
         return "";
      } else {
         int slashIndex = jid.indexOf(47);
         return slashIndex >= 0 && slashIndex < atIndex ? "" : jid.substring(0, atIndex);
      }
   }

   public static String parseDomain(String jid) {
      int atIndex = jid.indexOf(64);
      if (atIndex + 1 > jid.length()) {
         return "";
      } else {
         int slashIndex = jid.indexOf(47);
         if (slashIndex > 0) {
            return slashIndex > atIndex ? jid.substring(atIndex + 1, slashIndex) : jid.substring(0, slashIndex);
         } else {
            return jid.substring(atIndex + 1);
         }
      }
   }

   public static String parseResource(String jid) {
      int slashIndex = jid.indexOf(47);
      return slashIndex + 1 <= jid.length() && slashIndex >= 0 ? jid.substring(slashIndex + 1) : "";
   }

   /** @deprecated */
   @Deprecated
   public static String parseBareAddress(String jid) {
      return parseBareJid(jid);
   }

   public static String parseBareJid(String jid) {
      int slashIndex = jid.indexOf(47);
      if (slashIndex < 0) {
         return jid;
      } else {
         return slashIndex == 0 ? "" : jid.substring(0, slashIndex);
      }
   }

   public static boolean isFullJID(String jid) {
      return parseLocalpart(jid).length() > 0 && parseDomain(jid).length() > 0 && parseResource(jid).length() > 0;
   }

   public static boolean isBareJid(String jid) {
      return parseLocalpart(jid).length() > 0 && parseDomain(jid).length() > 0 && parseResource(jid).length() == 0;
   }

   public static String escapeLocalpart(String localpart) {
      if (localpart == null) {
         return null;
      } else {
         String res = (String)LOCALPART_ESACPE_CACHE.get(localpart);
         if (res != null) {
            return res;
         } else {
            StringBuilder buf = new StringBuilder(localpart.length() + 8);
            int i = 0;

            for(int n = localpart.length(); i < n; ++i) {
               char c = localpart.charAt(i);
               switch(c) {
               case '"':
                  buf.append("\\22");
                  break;
               case '&':
                  buf.append("\\26");
                  break;
               case '\'':
                  buf.append("\\27");
                  break;
               case '/':
                  buf.append("\\2f");
                  break;
               case ':':
                  buf.append("\\3a");
                  break;
               case '<':
                  buf.append("\\3c");
                  break;
               case '>':
                  buf.append("\\3e");
                  break;
               case '@':
                  buf.append("\\40");
                  break;
               case '\\':
                  buf.append("\\5c");
                  break;
               default:
                  if (Character.isWhitespace(c)) {
                     buf.append("\\20");
                  } else {
                     buf.append(c);
                  }
               }
            }

            res = buf.toString();
            LOCALPART_ESACPE_CACHE.put(localpart, res);
            return res;
         }
      }
   }

   public static String unescapeLocalpart(String localpart) {
      if (localpart == null) {
         return null;
      } else {
         String res = (String)LOCALPART_UNESCAPE_CACHE.get(localpart);
         if (res != null) {
            return res;
         } else {
            char[] localpartChars = localpart.toCharArray();
            StringBuilder buf = new StringBuilder(localpartChars.length);
            int i = 0;

            for(int n = localpartChars.length; i < n; ++i) {
               char c = localpart.charAt(i);
               if (c == '\\' && i + 2 < n) {
                  char c2 = localpartChars[i + 1];
                  char c3 = localpartChars[i + 2];
                  label46:
                  switch(c2) {
                  case '2':
                     switch(c3) {
                     case '0':
                        buf.append(' ');
                        i += 2;
                        continue;
                     case '2':
                        buf.append('"');
                        i += 2;
                        continue;
                     case '6':
                        buf.append('&');
                        i += 2;
                        continue;
                     case '7':
                        buf.append('\'');
                        i += 2;
                        continue;
                     case 'f':
                        buf.append('/');
                        i += 2;
                        continue;
                     default:
                        break label46;
                     }
                  case '3':
                     switch(c3) {
                     case 'a':
                        buf.append(':');
                        i += 2;
                        continue;
                     case 'b':
                     case 'd':
                     default:
                        break label46;
                     case 'c':
                        buf.append('<');
                        i += 2;
                        continue;
                     case 'e':
                        buf.append('>');
                        i += 2;
                        continue;
                     }
                  case '4':
                     if (c3 == '0') {
                        buf.append("@");
                        i += 2;
                        continue;
                     }
                     break;
                  case '5':
                     if (c3 == 'c') {
                        buf.append("\\");
                        i += 2;
                        continue;
                     }
                  }
               }

               buf.append(c);
            }

            res = buf.toString();
            LOCALPART_UNESCAPE_CACHE.put(localpart, res);
            return res;
         }
      }
   }

   public static String completeJidFrom(CharSequence localpart, CharSequence domainpart) {
      return completeJidFrom(localpart != null ? localpart.toString() : null, domainpart.toString());
   }

   public static String completeJidFrom(String localpart, String domainpart) {
      return completeJidFrom((String)localpart, (String)domainpart, (String)null);
   }

   public static String completeJidFrom(CharSequence localpart, CharSequence domainpart, CharSequence resource) {
      return completeJidFrom(localpart != null ? localpart.toString() : null, domainpart.toString(), resource != null ? resource.toString() : null);
   }

   public static String completeJidFrom(String localpart, String domainpart, String resource) {
      if (domainpart == null) {
         throw new IllegalArgumentException("domainpart must not be null");
      } else {
         int localpartLength = localpart != null ? localpart.length() : 0;
         int domainpartLength = domainpart.length();
         int resourceLength = resource != null ? resource.length() : 0;
         int maxResLength = localpartLength + domainpartLength + resourceLength + 2;
         StringBuilder sb = new StringBuilder(maxResLength);
         if (localpartLength > 0) {
            sb.append(localpart).append('@');
         }

         sb.append(domainpart);
         if (resourceLength > 0) {
            sb.append('/').append(resource);
         }

         return sb.toString();
      }
   }

   public static String generateKey(String element, String namespace) {
      return element + '\t' + namespace;
   }
}
