package org.chenyang.http.impl.cookie;

import org.chenyang.http.HeaderElement;
import org.chenyang.http.NameValuePair;
import org.chenyang.http.annotation.Contract;
import org.chenyang.http.annotation.ThreadingBehavior;
import org.chenyang.http.cookie.CommonCookieAttributeHandler;
import org.chenyang.http.cookie.Cookie;
import org.chenyang.http.cookie.CookieAttributeHandler;
import org.chenyang.http.cookie.CookieOrigin;
import org.chenyang.http.cookie.MalformedCookieException;
import org.chenyang.http.util.Args;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

@Contract(
   threading = ThreadingBehavior.SAFE
)
public abstract class CookieSpecBase extends AbstractCookieSpec {
   public CookieSpecBase() {
   }

   protected CookieSpecBase(HashMap<String, CookieAttributeHandler> map) {
      super(map);
   }

   protected CookieSpecBase(CommonCookieAttributeHandler... handlers) {
      super(handlers);
   }

   protected static String getDefaultPath(CookieOrigin origin) {
      String defaultPath = origin.getPath();
      int lastSlashIndex = defaultPath.lastIndexOf(47);
      if (lastSlashIndex >= 0) {
         if (lastSlashIndex == 0) {
            lastSlashIndex = 1;
         }

         defaultPath = defaultPath.substring(0, lastSlashIndex);
      }

      return defaultPath;
   }

   protected static String getDefaultDomain(CookieOrigin origin) {
      return origin.getHost();
   }

   protected List<Cookie> parse(HeaderElement[] elems, CookieOrigin origin) throws MalformedCookieException {
      List<Cookie> cookies = new ArrayList(elems.length);

      for(HeaderElement headerelement : elems) {
         String name = headerelement.getName();
         String value = headerelement.getValue();
         if (name != null && !name.isEmpty()) {
            BasicClientCookie cookie = new BasicClientCookie(name, value);
            cookie.setPath(getDefaultPath(origin));
            cookie.setDomain(getDefaultDomain(origin));
            NameValuePair[] attribs = headerelement.getParameters();

            for(int j = attribs.length - 1; j >= 0; --j) {
               NameValuePair attrib = attribs[j];
               String s = attrib.getName().toLowerCase(Locale.ROOT);
               cookie.setAttribute(s, attrib.getValue());
               CookieAttributeHandler handler = this.findAttribHandler(s);
               if (handler != null) {
                  handler.parse(cookie, attrib.getValue());
               }
            }

            cookies.add(cookie);
         }
      }

      return cookies;
   }

   public void validate(Cookie cookie, CookieOrigin origin) throws MalformedCookieException {
      Args.notNull(cookie, "Cookie");
      Args.notNull(origin, "Cookie origin");

      for(CookieAttributeHandler handler : this.getAttribHandlers()) {
         handler.validate(cookie, origin);
      }

   }

   public boolean match(Cookie cookie, CookieOrigin origin) {
      Args.notNull(cookie, "Cookie");
      Args.notNull(origin, "Cookie origin");

      for(CookieAttributeHandler handler : this.getAttribHandlers()) {
         if (!handler.match(cookie, origin)) {
            return false;
         }
      }

      return true;
   }
}
