/**
 * Copyright (C) 2009 eXo Platform SAS.
 * 
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 * 
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.exoplatform.upload;

import java.util.HashMap;
import java.util.Map;

/**
 *
 * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
 */

class ParameterParser
{

   private char[] chars_ = null;

   private int pos = 0;

   private int len = 0;

   private int i1 = 0, i2 = 0;

   private boolean lowerCaseNames = false;

   private boolean hasChar()
   {
      return this.pos < this.len;
   }

   private String getToken(boolean quoted)
   {
      while ((i1 < i2) && (Character.isWhitespace(chars_[i1])))
         i1++;

      while ((i2 > i1) && (Character.isWhitespace(chars_[i2 - 1])))
         i2--;

      if (quoted && ((i2 - i1) >= 2) && (chars_[i1] == '"') && (chars_[i2 - 1] == '"'))
      {
         i1++;
         i2--;
      }
      if (i2 > i1)
         return new String(chars_, i1, i2 - i1);

      return null;
   }

   private boolean isOneOf(char ch, final char[] charray)
   {
      for (int i = 0; i < charray.length; i++)
      {
         if (ch != charray[i])
            continue;
         return true;
      }
      return false;
   }

   private String parseToken(final char[] terminators)
   {
      char ch;
      i1 = pos;
      i2 = pos;
      while (hasChar())
      {
         ch = chars_[pos];
         if (isOneOf(ch, terminators))
            break;
         i2++;
         pos++;
      }
      return getToken(false);
   }

   private String parseQuotedToken(final char[] terminators)
   {
      char ch;
      i1 = pos;
      i2 = pos;
      boolean quoted = false;
      boolean charEscaped = false;
      while (hasChar())
      {
         ch = chars_[pos];
         if (!quoted && isOneOf(ch, terminators))
            break;
         if (!charEscaped && ch == '"')
            quoted = !quoted;
         charEscaped = (!charEscaped && ch == '\\');
         i2++;
         pos++;
      }
      return getToken(true);
   }

   public void setLowerCaseNames(boolean b)
   {
      this.lowerCaseNames = b;
   }

   public Map<String, String> parse(final String str, char separator)
   {
      if (str == null)
         return new HashMap<String, String>();

      chars_ = str.toCharArray();
      int offset = 0;
      int length = chars_.length;

      HashMap<String, String> params = new HashMap<String, String>();
      this.pos = offset;
      this.len = length;

      String paramName = null;
      String paramValue = null;
      while (hasChar())
      {
         paramName = parseToken(new char[]{'=', separator});
         paramValue = null;

         if (hasChar() && (chars_[pos] == '='))
         {
            pos++;
            paramValue = parseQuotedToken(new char[]{separator});
         }

         if (hasChar() && (chars_[pos] == separator))
            pos++;

         if ((paramName != null) && (paramName.length() > 0))
         {
            if (this.lowerCaseNames)
               paramName = paramName.toLowerCase();
            params.put(paramName, paramValue);
         }
      }
      return params;
   }
}
