package nl.adaptivity.android.darwin;

import android.support.annotation.NonNull;

import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by pdvrieze on 03/05/16.
 */
public class MyCookieStore implements CookieStore {
  private final ReentrantLock mLock;

  private final Map<String,List<HttpCookie>> cookieMap;
  private final Map<URI,List<HttpCookie>> uriMap;

  public MyCookieStore() {
    mLock = new ReentrantLock();
    cookieMap = new HashMap<>();
    uriMap = new HashMap<>();
  }

  @Override
  public void add(final URI uri, final HttpCookie cookie) {
    if (cookie==null) throw new NullPointerException();
    if (cookie.getMaxAge()==0) { return; }
    mLock.lock();
    try {
      String host = uri.getHost();
      List<HttpCookie> list = cookieMap.get(host);
      if (list == null) {
        list = new ArrayList<>();
        cookieMap.put(host, list);
      }
      list.add(cookie);

      try {
        URI cookieUri = getCookieUri(uri);
        list = uriMap.get(host);
        if (list == null) { list = new ArrayList<>(); uriMap.put(cookieUri, list); }
        list.add(cookie);
      } catch (URISyntaxException e) {
        throw new RuntimeException(e);
      }


    } finally {
      mLock.unlock();
    }
  }

  @NonNull
  private URI getCookieUri(final URI uri) throws URISyntaxException {return new URI("http", uri.getHost(), uri.getPath());}

  @Override
  public List<HttpCookie> get(final URI uri) {
    mLock.lock();
    try {
      String host = uri.getHost();
      final List<HttpCookie> rawList = cookieMap.get(host);
      if (rawList==null|| rawList.isEmpty()) { return Collections.emptyList(); }
      boolean uriIsSecure="https".equals(uri.getScheme());

      List<HttpCookie> result = new ArrayList<>();
      for(Iterator<HttpCookie> it = rawList.iterator(); it.hasNext();) {
        HttpCookie candidate = it.next();
        if (candidate.hasExpired()) { it.remove(); }
        if (!candidate.getSecure()|| uriIsSecure) {
          result.add(candidate);
        }
      }
      return result;
    } finally {
      mLock.unlock();
    }
  }

  @Override
  public List<HttpCookie> getCookies() {
    ArrayList<HttpCookie> result = new ArrayList<>();
    mLock.lock();
    try {
      for (List<HttpCookie> list : cookieMap.values()) {
        for (Iterator<HttpCookie> it = list.iterator(); it.hasNext(); ) {
          HttpCookie cookie = it.next();
          if (cookie.hasExpired()) {
            it.remove();
          } else {
            result.add(cookie);
          }
        }
      }
    } finally {
      mLock.unlock();
    }
    return result;
  }

  @Override
  public List<URI> getURIs() {
    mLock.lock();
    try {
      return new ArrayList<>(uriMap.keySet());
    } finally {
      mLock.unlock();
    }
  }

  @Override
  public boolean remove(final URI uri, final HttpCookie cookie) {
    mLock.lock();
    try {

      return false;
    } finally {
      mLock.unlock();
    }
  }

  @Override
  public boolean removeAll() {

    mLock.lock();
    boolean result = false;
    for(List<HttpCookie> cookieList: cookieMap.values()) {
      if (cookieList.size()>0) {
        result = true;
        break;
      }
    }
    try {
      cookieMap.clear();
      uriMap.clear();
    } finally {
      mLock.unlock();
    }
    return result;
  }
}

@@ -74,16 +74,62 @@
 NonNull;
+%0Aimport android.text.TextUtils.StringSplitter;
 %0A%0Aimport
@@ -1195,24 +1195,70 @@
 t);%0A      %7D%0A
+      removeSameCookieFromList(list, cookie);%0A
       list.a
@@ -1343,36 +1343,41 @@
 st = uriMap.get(
-host
+cookieUri
 );%0A        if (l
@@ -1444,24 +1444,72 @@
 i, list); %7D%0A
+        removeSameCookieFromList(list, cookie);%0A
         list
@@ -1659,16 +1659,903 @@
  %7D%0A  %7D%0A%0A
+  private boolean removeSameCookieFromList(final List%3CHttpCookie%3E list, final HttpCookie cookie) %7B%0A    if (list==null) %7B return false; %7D%0A    boolean removed = false;%0A    for(Iterator%3CHttpCookie%3E iterator = list.iterator(); iterator.hasNext();) %7B%0A      HttpCookie elem = iterator.next();%0A      if (cookie.getName().equals(elem.getName()) &&%0A          isEqual(elem.getDomain(), cookie.getDomain()) &&%0A          isEqualOrNull(elem.getPortlist(), cookie.getPortlist()) &&%0A          isEqual(elem.getPath(), cookie.getPath())) %7B%0A        iterator.remove();%0A        removed=true;%0A      %7D%0A    %7D%0A    return removed;%0A  %7D%0A%0A  private static boolean isEqual(final Object val1, final Object val2) %7B%0A    return val1==null ? val2==null : val1.equals(val2);%0A  %7D%0A%0A  private static boolean isEqualOrNull(final Object val1, final Object val2) %7B%0A    return val1==null %7C%7C val2==null %7C%7C val1.equals(val2);%0A  %7D%0A%0A
   @NonNu
@@ -4192,27 +4192,267 @@
 y %7B%0A
-%0A      return false
+      boolean result = false;%0A      List%3CHttpCookie%3E list = cookieMap.get(uri.getHost());%0A      result = removeSameCookieFromList(list, cookie);%0A      list = uriMap.get(uri);%0A      result = removeSameCookieFromList(list, cookie) %7C%7C result;%0A      return result
 ;%0A  

Fix deletion, don't add overlapping cookies.