//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//

package org.eclipse.jetty.http.pathmap;

import java.util.List;

import org.junit.jupiter.api.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.jupiter.api.Assertions.assertNull;

public class WebSocketUriMappingTest
{
    private PathMappings<String> mapping = new PathMappings<>();

    private String getBestMatch(String uriPath)
    {
        List<MappedResource<String>> resources = mapping.getMatches(uriPath);
        assertThat("Matches on " + uriPath, resources, is(not(nullValue())));
        if (resources.isEmpty())
            return null;
        return resources.get(0).getResource();
    }

    @Test
    public void testJsrExampleI()
    {
        mapping.put("/a/b", "endpointA");

        assertThat(getBestMatch("/a/b"), is("endpointA"));
        assertNull(getBestMatch("/a/c"));
    }

    @Test
    public void testJsrExampleII()
    {
        mapping.put(new UriTemplatePathSpec("/a/{var}"), "endpointA");

        assertThat(getBestMatch("/a/b"), is("endpointA"));
        assertThat(getBestMatch("/a/apple"), is("endpointA"));
        assertNull(getBestMatch("/a"));
        assertNull(getBestMatch("/a/b/c"));
    }

    @Test
    public void testJsrExampleIII()
    {
        mapping.put(new UriTemplatePathSpec("/a/{var}/c"), "endpointA");
        mapping.put(new UriTemplatePathSpec("/a/b/c"), "endpointB");
        mapping.put(new UriTemplatePathSpec("/a/{var1}/{var2}"), "endpointC");

        assertThat(getBestMatch("/a/b/c"), is("endpointB"));
        assertThat(getBestMatch("/a/d/c"), is("endpointA"));
        assertThat(getBestMatch("/a/x/y"), is("endpointC"));
    }

    @Test
    public void testJsrExampleIV()
    {
        mapping.put(new UriTemplatePathSpec("/{var1}/d"), "endpointA");
        mapping.put(new UriTemplatePathSpec("/b/{var2}"), "endpointB");

        assertThat(getBestMatch("/b/d"), is("endpointB"));
    }

    @Test
    public void testPrefixVsSuffix()
    {
        mapping.put(new UriTemplatePathSpec("/{a}/b"), "suffix");
        mapping.put(new UriTemplatePathSpec("/{a}/{b}"), "prefix");

        List<MappedResource<String>> matches = mapping.getMatches("/a/b");

        assertThat(getBestMatch("/a/b"), is("suffix"));
    }

    @Test
    public void testMiddleVsSuffix()
    {
        mapping.put(new UriTemplatePathSpec("/a/{b}/c"), "middle");
        mapping.put(new UriTemplatePathSpec("/a/b/{c}"), "suffix");

        assertThat(getBestMatch("/a/b/c"), is("suffix"));
    }

    @Test
    public void testMiddleVsSuffix2()
    {
        mapping.put(new UriTemplatePathSpec("/{a}/b/{c}"), "middle");
        mapping.put(new UriTemplatePathSpec("/{a}/b/c"), "suffix");

        assertThat(getBestMatch("/a/b/c"), is("suffix"));
    }

    @Test
    public void testMiddleVsPrefix()
    {
        mapping.put(new UriTemplatePathSpec("/a/{b}/{c}/d"), "middle");
        mapping.put(new UriTemplatePathSpec("/a/b/c/{d}"), "prefix");

        assertThat(getBestMatch("/a/b/c/d"), is("prefix"));
    }

    @Test
    public void testMiddleVsMiddle()
    {
        // This works but only because its an alphabetical check and '{' > 'c'.
        mapping.put(new UriTemplatePathSpec("/a/{b}/{c}/d"), "middle1");
        mapping.put(new UriTemplatePathSpec("/a/{b}/c/d"), "middle2");

        assertThat(getBestMatch("/a/b/c/d"), is("middle2"));
    }

    @Test
    public void testMiddleVsMiddle2()
    {
        mapping.put(new UriTemplatePathSpec("/{a}/{bz}/c/{d}"), "middle1");
        mapping.put(new UriTemplatePathSpec("/{a}/{ba}/{c}/d"), "middle2");

        assertThat(getBestMatch("/a/b/c/d"), is("middle1"));
    }

    @Test
    public void testMiddleVsMiddle3()
    {
        mapping.put(new UriTemplatePathSpec("/{a}/{ba}/c/{d}"), "middle1");
        mapping.put(new UriTemplatePathSpec("/{a}/{bz}/{c}/d"), "middle2");

        assertThat(getBestMatch("/a/b/c/d"), is("middle1"));
    }

    @Test
    public void testPrefixVsPrefix()
    {
        // This works but only because its an alphabetical check and '{' > 'b'.
        mapping.put(new UriTemplatePathSpec("/a/{b}/{c}"), "prefix1");
        mapping.put(new UriTemplatePathSpec("/a/b/{c}"), "prefix2");

        assertThat(getBestMatch("/a/b/c"), is("prefix2"));
    }

    @Test
    public void testSuffixVsSuffix()
    {
        // This works but only because its an alphabetical check and '{' > 'b'.
        mapping.put(new UriTemplatePathSpec("/{a}/{b}/c"), "suffix1");
        mapping.put(new UriTemplatePathSpec("/{a}/b/c"), "suffix2");

        assertThat(getBestMatch("/a/b/c"), is("suffix2"));
    }

    @Test
    public void testDifferentLengths()
    {
        mapping.put(new UriTemplatePathSpec("/a/{var}/c"), "endpointA");
        mapping.put(new UriTemplatePathSpec("/a/{var}/c/d"), "endpointB");
        mapping.put(new UriTemplatePathSpec("/a/{var1}/{var2}/d/e"), "endpointC");

        assertThat(getBestMatch("/a/b/c"), is("endpointA"));
        assertThat(getBestMatch("/a/d/c/d"), is("endpointB"));
        assertThat(getBestMatch("/a/x/y/d/e"), is("endpointC"));
    }
}
