/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */
package org.apache.qpid.tests.http.rest.model;

import static java.util.Collections.singletonMap;
import static javax.servlet.http.HttpServletResponse.SC_CREATED;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.oneOf;
import static org.junit.Assume.assumeThat;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

import org.junit.Before;
import org.junit.Test;

import org.apache.qpid.server.logging.logback.VirtualHostFileLogger;
import org.apache.qpid.server.logging.logback.VirtualHostNameAndLevelLogInclusionRule;
import org.apache.qpid.server.model.AbstractConfiguredObject;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.User;
import org.apache.qpid.server.security.NonJavaKeyStore;
import org.apache.qpid.server.security.NonJavaTrustStore;
import org.apache.qpid.server.transport.network.security.ssl.SSLUtil;
import org.apache.qpid.server.transport.network.security.ssl.SSLUtil.KeyCertPair;
import org.apache.qpid.server.util.DataUrlUtils;
import org.apache.qpid.server.util.FileUtils;
import org.apache.qpid.tests.http.HttpRequestConfig;
import org.apache.qpid.tests.http.HttpTestBase;

@HttpRequestConfig
public class ReadTest extends HttpTestBase
{
    private static final String QUEUE1_NAME = "myqueue1";
    private static final String QUEUE2_NAME = "myqueue2";
    private static final String QUEUE1_URL = String.format("queue/%s", QUEUE1_NAME);
    private static final String QUEUE2_URL = String.format("queue/%s", QUEUE2_NAME);

    @Before
    public void setUp()
    {
        getBrokerAdmin().createQueue(QUEUE1_NAME);
        getBrokerAdmin().createQueue(QUEUE2_NAME);
    }

    @Test
    public void readObject() throws Exception
    {
        final Map<String, Object> queue = getHelper().getJsonAsMap(QUEUE1_URL);
        assertThat(queue.get(ConfiguredObject.NAME), is(equalTo(QUEUE1_NAME)));
        assertThat(queue.get(ConfiguredObject.ID), is(notNullValue()));
    }

    @Test
    public void notFound() throws Exception
    {
        getHelper().submitRequest("queue/unknown", "GET", SC_NOT_FOUND);
    }

    @Test
    public void readObjectResponseAsList() throws Exception
    {
        final Map<String, Object> queue = getHelper().getJsonAsSingletonList(QUEUE1_URL + "?singletonModelObjectResponseAsList=true");
        assertThat(queue.get(ConfiguredObject.NAME), is(equalTo(QUEUE1_NAME)));
        assertThat(queue.get(ConfiguredObject.ID), is(notNullValue()));
    }

    @Test
    public void readAll() throws Exception
    {
        List<Map<String, Object>> list = getHelper().getJsonAsList("queue");
        assertThat(list.size(), is(equalTo(2)));
        Set<String> queueNames = list.stream()
                                     .map(map -> (String) map.get(ConfiguredObject.NAME))
                                     .collect(Collectors.toSet());
        assertThat(queueNames, containsInAnyOrder(QUEUE1_NAME, QUEUE2_NAME));
    }

    @Test
    public void readFilter() throws Exception
    {
        final Map<String, Object> queue1 = getHelper().getJsonAsMap(QUEUE1_URL);

        List<Map<String, Object>> list = getHelper().getJsonAsList(String.format("queue/?%s=%s",
                                                                                 ConfiguredObject.ID,
                                                                                 queue1.get(ConfiguredObject.ID)));
        assertThat(list.size(), is(equalTo(1)));
        final Map<String, Object> queue = list.get(0);
        assertThat(queue.get(ConfiguredObject.NAME), is(equalTo(QUEUE1_NAME)));
        assertThat(queue.get(ConfiguredObject.ID), is(notNullValue()));
    }

    @Test
    public void filterNotFound() throws Exception
    {
        List<Map<String, Object>> list = getHelper().getJsonAsList(String.format("queue/?%s=%s",
                                                                                 ConfiguredObject.ID,
                                                                                 UUID.randomUUID()));
        assertThat(list.size(), is(equalTo(0)));
    }

    @Test
    public void readHierarchy() throws Exception
    {
        final Map<String, Object> virtualHost = getHelper().getJsonAsMap("virtualhost?depth=2");
        assertThat(virtualHost.get(ConfiguredObject.ID), is(notNullValue()));
        assertThat(virtualHost.get(ConfiguredObject.NAME), is(equalTo(getVirtualHost())));

        @SuppressWarnings("unchecked")
        List<Map<String, Object>> queues = (List<Map<String, Object>>) virtualHost.get("queues");
        assertThat(queues.size(), is(equalTo(2)));
    }

    @Test
    public void excludeInheritedContext() throws Exception
    {
        final String hostContextKey = "myvhcontextvar";
        final String hostContextValue = UUID.randomUUID().toString();
        final Map<String, Object> hostUpdateAttrs = singletonMap(ConfiguredObject.CONTEXT,
                                                                 singletonMap(hostContextKey, hostContextValue));
        getHelper().submitRequest("virtualhost", "POST", hostUpdateAttrs, SC_OK);

        final String queueContextKey = "myqueuecontextvar";
        final String queueContextValue = UUID.randomUUID().toString();
        final Map<String, Object> queueUpdateAttrs = singletonMap(ConfiguredObject.CONTEXT,
                                                                  singletonMap(queueContextKey, queueContextValue));
        getHelper().submitRequest(QUEUE1_URL, "POST", queueUpdateAttrs, SC_OK);

        final Map<String, Object> queue = getHelper().getJsonAsMap(QUEUE1_URL);
        @SuppressWarnings("unchecked")
        Map<String, Object> context = (Map<String, Object>) queue.get("context");
        assertThat(context.size(), is(equalTo(1)));
        assertThat(context.get(queueContextKey), is(equalTo(queueContextValue)));

        final Map<String, Object> queue2 = getHelper().getJsonAsMap(QUEUE1_URL + "?excludeInheritedContext=false");
        @SuppressWarnings("unchecked")
        Map<String, Object> context2 = (Map<String, Object>) queue2.get("context");
        assertThat(context2.size(), is(greaterThanOrEqualTo(2)));
        assertThat(context2.get(queueContextKey), is(equalTo(queueContextValue)));
        assertThat(context2.get(hostContextKey), is(equalTo(hostContextValue)));
    }

    @Test
    public void actuals() throws Exception
    {
        final String queueContextKey = "myqueuecontextvar";
        final String queueContextValue = UUID.randomUUID().toString();

        final Map<String, Object> queueUpdateAttrs = new HashMap<>();
        queueUpdateAttrs.put(ConfiguredObject.DESCRIPTION, "${myqueuecontextvar}");
        queueUpdateAttrs.put(ConfiguredObject.CONTEXT, singletonMap(queueContextKey, queueContextValue));
        getHelper().submitRequest(QUEUE1_URL, "POST", queueUpdateAttrs, SC_OK);


        final Map<String, Object> queue = getHelper().getJsonAsMap(QUEUE1_URL);
        assertThat(queue.get(ConfiguredObject.DESCRIPTION), is(equalTo(queueContextValue)));

        final Map<String, Object> queueActuals = getHelper().getJsonAsMap(QUEUE1_URL + "?actuals=true");
        assertThat(queueActuals.get(ConfiguredObject.DESCRIPTION), is(equalTo("${myqueuecontextvar}")));
    }

    @Test
    public void wildcards() throws Exception
    {
        String rule1A = createLoggerAndRule("mylogger1", "myinclusionruleA");
        String rule1B = createLoggerAndRule("mylogger1", "myinclusionruleB");
        String rule2A = createLoggerAndRule("mylogger2", "myinclusionruleA");

        {
            List<Map<String, Object>> rules = getHelper().getJsonAsList("virtualhostloginclusionrule/*");
            assertThat(rules.size(), is(equalTo(3)));

            Set<String> ids = rules.stream().map(ReadTest::getId).collect(Collectors.toSet());
            assertThat(ids, containsInAnyOrder(rule1A, rule1B, rule2A));
        }

        {
            List<Map<String, Object>> rules = getHelper().getJsonAsList("virtualhostloginclusionrule/mylogger1/*");
            assertThat(rules.size(), is(equalTo(2)));

            Set<String> ids = rules.stream().map(ReadTest::getId).collect(Collectors.toSet());
            assertThat(ids, containsInAnyOrder(rule1A, rule1B));
        }

        {
            List<Map<String, Object>> rules = getHelper().getJsonAsList("virtualhostloginclusionrule/*/myinclusionruleA");
            assertThat(rules.size(), is(equalTo(2)));

            Set<String> ids = rules.stream().map(ReadTest::getId).collect(Collectors.toSet());
            assertThat(ids, containsInAnyOrder(rule1A, rule2A));
        }
    }

    @Test
    @HttpRequestConfig(useVirtualHostAsHost = false)
    public void secureAttributes() throws Exception
    {
        final String validUsername = getBrokerAdmin().getValidUsername();
        final Map<String, Object> user = getHelper().getJsonAsMap("user/plain/" + validUsername);
        assertThat(user.get(User.NAME), is(equalTo(validUsername)));
        assertThat(user.get(User.PASSWORD), is(equalTo(AbstractConfiguredObject.SECURED_STRING_VALUE)));
    }

    @Test
    @HttpRequestConfig(useVirtualHostAsHost = false)
    public void valueFilteredSecureAttributes() throws Exception
    {
        assumeThat(SSLUtil.canGenerateCerts(), is(equalTo(true)));

        final KeyCertPair keyCertPair = generateCertKeyPair();
        final byte[] privateKey = keyCertPair.getPrivateKey().getEncoded();
        final byte[] cert = keyCertPair.getCertificate().getEncoded();
        final String privateKeyUrl = DataUrlUtils.getDataUrlForBytes(privateKey);
        final String certUrl = DataUrlUtils.getDataUrlForBytes(cert);

        final File privateKeyFile = File.createTempFile("foo" + System.currentTimeMillis(), "key");
        privateKeyFile.deleteOnExit();
        FileUtils.copy(new ByteArrayInputStream(privateKey), privateKeyFile);

        Map<String, Object> base = new HashMap<>();
        base.put(NonJavaKeyStore.TYPE, "NonJavaKeyStore");
        base.put(NonJavaKeyStore.CERTIFICATE_URL, certUrl);

        try
        {
            {
                final String storeUrl = "keystore/mystoreDataUrl";
                final Map<String, Object> attrs = new HashMap<>(base);
                attrs.put(NonJavaKeyStore.PRIVATE_KEY_URL, privateKeyUrl);
                getHelper().submitRequest(storeUrl, "PUT", attrs, SC_CREATED);

                final Map<String, Object> store = getHelper().getJsonAsMap(storeUrl);
                assertThat(store.get(NonJavaKeyStore.PRIVATE_KEY_URL),
                           is(equalTo(AbstractConfiguredObject.SECURED_STRING_VALUE)));

                getHelper().submitRequest(storeUrl, "DELETE", SC_OK);
            }

            {
                final String privateKeyFileUrl = privateKeyFile.toURI().toString();
                final String storeUrl = "keystore/mystoreFileUrl";
                final Map<String, Object> attrs = new HashMap<>(base);
                attrs.put(NonJavaKeyStore.TYPE, "NonJavaKeyStore");
                attrs.put(NonJavaKeyStore.PRIVATE_KEY_URL, privateKeyFileUrl);
                getHelper().submitRequest(storeUrl, "PUT", attrs, SC_CREATED);

                final Map<String, Object> store = getHelper().getJsonAsMap(String.format("%s?oversize=%d", storeUrl, privateKeyFileUrl.length()));
                assertThat(store.get(NonJavaKeyStore.PRIVATE_KEY_URL), is(equalTo(privateKeyFileUrl)));

                getHelper().submitRequest(storeUrl, "DELETE", SC_OK);
            }
        }
        finally
        {
            privateKeyFile.delete();
        }
    }

    @Test
    @HttpRequestConfig(useVirtualHostAsHost = false)
    public void oversizeAttribute() throws Exception
    {
        assumeThat(SSLUtil.canGenerateCerts(), is(equalTo(true)));

        final byte[] encodedCert = generateCertKeyPair().getCertificate().getEncoded();
        final String dataUrl = DataUrlUtils.getDataUrlForBytes(encodedCert);

        final String storeUrl = "truststore/mystore";
        final Map<String, Object> attrs = new HashMap<>();
        attrs.put(NonJavaTrustStore.TYPE, "NonJavaTrustStore");
        attrs.put(NonJavaTrustStore.CERTIFICATES_URL, dataUrl);
        getHelper().submitRequest(storeUrl, "PUT", attrs, SC_CREATED);

        final Map<String, Object> store = getHelper().getJsonAsMap(storeUrl);
        assertThat(store.get(NonJavaTrustStore.CERTIFICATES_URL), is(equalTo(AbstractConfiguredObject.OVER_SIZED_ATTRIBUTE_ALTERNATIVE_TEXT)));

        final Map<String, Object> full = getHelper().getJsonAsMap(storeUrl +  String.format("?oversize=%d", dataUrl.length()));
        assertThat(full.get(NonJavaTrustStore.CERTIFICATES_URL), is(equalTo(dataUrl)));

        getHelper().submitRequest(storeUrl, "DELETE", SC_OK);
    }

    private String createLoggerAndRule(final String loggerName, final String inclusionRuleName) throws Exception
    {
        final String parentUrl = String.format("virtualhostlogger/%s", loggerName);
        Map<String, Object> parentAttrs = Collections.singletonMap(ConfiguredObject.TYPE, VirtualHostFileLogger.TYPE);

        int response = getHelper().submitRequest(parentUrl, "PUT", parentAttrs);
        assertThat(response, is(oneOf(SC_CREATED, SC_OK)));

        final String childUrl = String.format("virtualhostloginclusionrule/%s/%s", loggerName, inclusionRuleName);
        Map<String, Object> childAttrs = Collections.singletonMap(ConfiguredObject.TYPE, VirtualHostNameAndLevelLogInclusionRule.TYPE);
        getHelper().submitRequest(childUrl, "PUT", childAttrs, SC_CREATED);

        final Map<String, Object> child = getHelper().getJsonAsMap(childUrl);
        return (String) child.get(ConfiguredObject.ID);

    }

    private static String getId(Map<String, Object> object)
    {
        return ((String) object.get(ConfiguredObject.ID));
    }

    private KeyCertPair generateCertKeyPair() throws Exception
    {
        return SSLUtil.generateSelfSignedCertificate("RSA", "SHA256WithRSA",
                                                     2048, Instant.now().toEpochMilli(),
                                                     Duration.of(365, ChronoUnit.DAYS).getSeconds(),
                                                     "CN=foo",
                                                     Collections.emptySet(),
                                                     Collections.emptySet());
    }
}
