package org.chenyang.http.impl.cookie;

import org.chenyang.http.HeaderElement;
import org.chenyang.http.NameValuePair;
import org.chenyang.http.ParseException;
import org.chenyang.http.annotation.Contract;
import org.chenyang.http.annotation.ThreadingBehavior;
import org.chenyang.http.message.BasicHeaderElement;
import org.chenyang.http.message.BasicNameValuePair;
import org.chenyang.http.message.ParserCursor;
import org.chenyang.http.message.TokenParser;
import org.chenyang.http.util.Args;
import org.chenyang.http.util.CharArrayBuffer;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;

@Contract(
   threading = ThreadingBehavior.IMMUTABLE
)
public class NetscapeDraftHeaderParser {
   public static final NetscapeDraftHeaderParser DEFAULT = new NetscapeDraftHeaderParser();
   private static final char PARAM_DELIMITER = ';';
   private static final BitSet TOKEN_DELIMS = TokenParser.INIT_BITSET(61, 59);
   private static final BitSet VALUE_DELIMS = TokenParser.INIT_BITSET(59);
   private final TokenParser tokenParser;

   public NetscapeDraftHeaderParser() {
      this.tokenParser = TokenParser.INSTANCE;
   }

   public HeaderElement parseHeader(CharArrayBuffer buffer, ParserCursor cursor) throws ParseException {
      Args.notNull(buffer, "Char array buffer");
      Args.notNull(cursor, "Parser cursor");
      NameValuePair nvp = this.parseNameValuePair(buffer, cursor);
      List<NameValuePair> params = new ArrayList();

      while(!cursor.atEnd()) {
         NameValuePair param = this.parseNameValuePair(buffer, cursor);
         params.add(param);
      }

      return new BasicHeaderElement(nvp.getName(), nvp.getValue(), (NameValuePair[])params.toArray(new NameValuePair[params.size()]));
   }

   private NameValuePair parseNameValuePair(CharArrayBuffer buffer, ParserCursor cursor) {
      String name = this.tokenParser.parseToken(buffer, cursor, TOKEN_DELIMS);
      if (cursor.atEnd()) {
         return new BasicNameValuePair(name, null);
      } else {
         int delim = buffer.charAt(cursor.getPos());
         cursor.updatePos(cursor.getPos() + 1);
         if (delim != 61) {
            return new BasicNameValuePair(name, null);
         } else {
            String value = this.tokenParser.parseToken(buffer, cursor, VALUE_DELIMS);
            if (!cursor.atEnd()) {
               cursor.updatePos(cursor.getPos() + 1);
            }

            return new BasicNameValuePair(name, value);
         }
      }
   }
}
