package io.corbel.lib.ws.filter;

import io.corbel.lib.token.exception.TokenVerificationException;
import io.corbel.lib.token.parser.TokenParser;
import io.corbel.lib.token.reader.TokenReader;
import io.corbel.lib.ws.auth.priority.CorbelPriorities;

import java.net.URI;
import java.util.regex.Pattern;

import javax.annotation.Priority;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.PreMatching;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Alberto J. Rubio
 */
@PreMatching @Priority(CorbelPriorities.ALLOW_REQUEST_WITHOUT_DOMAIN_IN_URI_FILTER) public class AllowRequestWithoutDomainInUriFilter
        extends OptionalContainerRequestFilter {

    private static final Logger LOG = LoggerFactory.getLogger(AllowRequestWithoutDomainInUriFilter.class);
    private static final String AUTHORIZATION_HEADER = "Authorization";
    private static final String UNAUTHENTICATED = "unauthenticated";
    private static final String TOKEN_PREFIX = "Bearer ";
    private static final String EMPTY_STRING = "";

    private final TokenParser tokenParser;
    private final String unAuthenticatedPathPattern;
    private final Pattern requestWithDomainPattern;

    public AllowRequestWithoutDomainInUriFilter(boolean enabled, TokenParser tokenParser, String unAuthenticatedPathPattern,
                                                String endpoints) {
        super(enabled);
        this.tokenParser = tokenParser;
        this.unAuthenticatedPathPattern = unAuthenticatedPathPattern;
        this.requestWithDomainPattern = Pattern.compile("v[0-9]+\\.[0-9]+/[\\w\\-:\\.]+/(" + endpoints.replace(",", "|") + ")(/.*)?");
    }

    @Override
    public void filter(ContainerRequestContext request) {
        try {
            String path = request.getUriInfo().getPath();
            if (!path.matches(unAuthenticatedPathPattern) && !requestWithDomainPattern.matcher(path).matches()) {
                String domain = extractRequestDomain(request);
                int slashIndex = path.indexOf("/");
                if (domain != null && slashIndex != -1) {
                    String version = path.substring(0, slashIndex);
                    String versionAndDomainPath = version + "/" + domain;
                    String pathWithoutVersion = path.replace(version, EMPTY_STRING);
                    String pathWithDomain = versionAndDomainPath + pathWithoutVersion;
                    URI requestUriWithDomain = request.getUriInfo().getRequestUriBuilder().replacePath(pathWithDomain).build();
                    request.setRequestUri(requestUriWithDomain);
                }
            }
        } catch (TokenVerificationException ignored) {
            LOG.debug("Cannot parse authorization token");
        }
    }

    private String extractRequestDomain(ContainerRequestContext request) throws TokenVerificationException {
        String domain = UNAUTHENTICATED;
        String authorizationHeader = request.getHeaderString(AUTHORIZATION_HEADER);
        if (authorizationHeader != null && authorizationHeader.startsWith(TOKEN_PREFIX)) {
            TokenReader tokenReader = tokenParser.parseAndVerify(authorizationHeader.substring(TOKEN_PREFIX.length()));
            domain = tokenReader.getInfo().getDomainId();
        }
        return domain;
    }
}
@@ -671,16 +671,28 @@
  extends
+%0A           
  Optiona
@@ -717,16 +717,16 @@
 ilter %7B%0A
-
 %0A    pri
@@ -1223,16 +1223,71 @@
 Pattern;
+%0A    private final Pattern requestWithoutDomainPattern;
 %0A%0A    pu
@@ -1409,44 +1409,8 @@
 rn,%0A
-                                    
     
@@ -1433,24 +1433,24 @@
 ndpoints) %7B%0A
+
         supe
@@ -1702,24 +1702,148 @@
 %22)(/.*)?%22);%0A
+        this.requestWithoutDomainPattern = Pattern.compile(%22v%5B0-9%5D+%5C%5C.%5B0-9%5D+/(%22 + endpoints.replace(%22,%22, %22%7C%22) + %22)(/.*)?%22);%0A
     %7D%0A%0A    @
@@ -2046,56 +2046,31 @@
  && 
-!requestWithDomainPattern.matcher(path).matches(
+includeDomainInUri(path
 )) %7B
@@ -2892,24 +2892,24 @@
 on token%22);%0A
-
         %7D%0A  
@@ -2909,24 +2909,206 @@
    %7D%0A    %7D%0A%0A
+    private boolean includeDomainInUri(String path) %7B%0A        return !requestWithDomainPattern.matcher(path).matches() && requestWithoutDomainPattern.matcher(path).matches();%0A    %7D%0A%0A
     private 

Fix problems with /oauth/token/upgrade endpoint.