/*
 * ====================================================================
 * 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 */
package org.apache.hc.client5.http.impl.cache;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.hc.client5.http.cache.HttpCacheEntry;
import org.apache.hc.client5.http.cache.HttpCacheStorageEntry;
import org.apache.hc.client5.http.cache.HttpCacheUpdateException;
import org.apache.hc.client5.http.cache.ResourceIOException;
import org.apache.hc.core5.concurrent.Cancellable;
import org.apache.hc.core5.concurrent.FutureCallback;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;

public class TestAbstractSerializingAsyncCacheStorage {

    @Mock
    private Cancellable cancellable;
    @Mock
    private FutureCallback<Boolean> operationCallback;
    @Mock
    private FutureCallback<HttpCacheEntry> cacheEntryCallback;
    @Mock
    private FutureCallback<Map<String, HttpCacheEntry>> bulkCacheEntryCallback;

    private AbstractBinaryAsyncCacheStorage<String> impl;

    public static byte[] serialize(final String key, final HttpCacheEntry value) throws ResourceIOException {
        return HttpByteArrayCacheEntrySerializer.INSTANCE.serialize(new HttpCacheStorageEntry(key, value));
    }

    @BeforeEach
    @SuppressWarnings("unchecked")
    public void setUp() {
        MockitoAnnotations.openMocks(this);
        impl = Mockito.mock(AbstractBinaryAsyncCacheStorage.class,
                Mockito.withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS).useConstructor(3));
    }

    @Test
    public void testCachePut() throws Exception {
        final String key = "foo";
        final HttpCacheEntry value = HttpTestUtils.makeCacheEntry();

        Mockito.when(impl.digestToStorageKey(key)).thenReturn("bar");
        Mockito.when(impl.store(
                ArgumentMatchers.eq("bar"),
                ArgumentMatchers.any(),
                ArgumentMatchers.any())).thenAnswer((Answer<Cancellable>) invocation -> {
                    final FutureCallback<Boolean> callback = invocation.getArgument(2);
                    callback.completed(true);
                    return cancellable;
                });

        impl.putEntry(key, value, operationCallback);

        final ArgumentCaptor<byte[]> argumentCaptor = ArgumentCaptor.forClass(byte[].class);
        Mockito.verify(impl).store(ArgumentMatchers.eq("bar"), argumentCaptor.capture(), ArgumentMatchers.any());
        Assertions.assertArrayEquals(serialize(key, value), argumentCaptor.getValue());
        Mockito.verify(operationCallback).completed(Boolean.TRUE);
    }

    @Test
    public void testCacheGetNullEntry() throws Exception {
        final String key = "foo";

        Mockito.when(impl.digestToStorageKey(key)).thenReturn("bar");
        Mockito.when(impl.restore(ArgumentMatchers.eq("bar"), ArgumentMatchers.any())).thenAnswer((Answer<Cancellable>) invocation -> {
            final FutureCallback<byte[]> callback = invocation.getArgument(1);
            callback.completed(null);
            return cancellable;
        });

        impl.getEntry(key, cacheEntryCallback);
        final ArgumentCaptor<HttpCacheEntry> argumentCaptor = ArgumentCaptor.forClass(HttpCacheEntry.class);
        Mockito.verify(cacheEntryCallback).completed(argumentCaptor.capture());
        assertThat(argumentCaptor.getValue(), CoreMatchers.nullValue());
        Mockito.verify(impl).restore(ArgumentMatchers.eq("bar"), ArgumentMatchers.any());
    }

    @Test
    public void testCacheGet() throws Exception {
        final String key = "foo";
        final HttpCacheEntry value = HttpTestUtils.makeCacheEntry();

        Mockito.when(impl.digestToStorageKey(key)).thenReturn("bar");
        Mockito.when(impl.restore(ArgumentMatchers.eq("bar"), ArgumentMatchers.any())).thenAnswer((Answer<Cancellable>) invocation -> {
            final FutureCallback<byte[]> callback = invocation.getArgument(1);
            callback.completed(serialize(key, value));
            return cancellable;
        });

        impl.getEntry(key, cacheEntryCallback);
        final ArgumentCaptor<HttpCacheEntry> argumentCaptor = ArgumentCaptor.forClass(HttpCacheEntry.class);
        Mockito.verify(cacheEntryCallback).completed(argumentCaptor.capture());
        final HttpCacheEntry resultingEntry = argumentCaptor.getValue();
        assertThat(resultingEntry, HttpCacheEntryMatcher.equivalent(value));
        Mockito.verify(impl).restore(ArgumentMatchers.eq("bar"), ArgumentMatchers.any());
    }

    @Test
    public void testCacheGetKeyMismatch() throws Exception {
        final String key = "foo";
        final HttpCacheEntry value = HttpTestUtils.makeCacheEntry();
        Mockito.when(impl.digestToStorageKey(key)).thenReturn("bar");
        Mockito.when(impl.restore(ArgumentMatchers.eq("bar"), ArgumentMatchers.any())).thenAnswer((Answer<Cancellable>) invocation -> {
            final FutureCallback<byte[]> callback = invocation.getArgument(1);
            callback.completed(serialize("not-foo", value));
            return cancellable;
        });

        impl.getEntry(key, cacheEntryCallback);
        final ArgumentCaptor<HttpCacheEntry> argumentCaptor = ArgumentCaptor.forClass(HttpCacheEntry.class);
        Mockito.verify(cacheEntryCallback).completed(argumentCaptor.capture());
        assertThat(argumentCaptor.getValue(), CoreMatchers.nullValue());
        Mockito.verify(impl).restore(ArgumentMatchers.eq("bar"), ArgumentMatchers.any());
    }

    @Test
    public void testCacheRemove()  throws Exception{
        final String key = "foo";

        Mockito.when(impl.digestToStorageKey(key)).thenReturn("bar");
        Mockito.when(impl.delete(
                ArgumentMatchers.eq("bar"),
                ArgumentMatchers.any())).thenAnswer((Answer<Cancellable>) invocation -> {
                    final FutureCallback<Boolean> callback = invocation.getArgument(1);
                    callback.completed(true);
                    return cancellable;
                });
        impl.removeEntry(key, operationCallback);

        Mockito.verify(impl).delete("bar", operationCallback);
        Mockito.verify(operationCallback).completed(Boolean.TRUE);
    }

    @Test
    public void testCacheUpdateNullEntry() throws Exception {
        final String key = "foo";
        final HttpCacheEntry updatedValue = HttpTestUtils.makeCacheEntry();

        Mockito.when(impl.digestToStorageKey(key)).thenReturn("bar");
        Mockito.when(impl.getForUpdateCAS(ArgumentMatchers.eq("bar"), ArgumentMatchers.any())).thenAnswer((Answer<Cancellable>) invocation -> {
            final FutureCallback<byte[]> callback = invocation.getArgument(1);
            callback.completed(null);
            return cancellable;
        });
        Mockito.when(impl.store(
                ArgumentMatchers.eq("bar"),
                ArgumentMatchers.any(),
                ArgumentMatchers.any())).thenAnswer((Answer<Cancellable>) invocation -> {
                    final FutureCallback<Boolean> callback = invocation.getArgument(2);
                    callback.completed(true);
                    return cancellable;
                });

        impl.updateEntry(key, existing -> {
            assertThat(existing, CoreMatchers.nullValue());
            return updatedValue;
        }, operationCallback);

        Mockito.verify(impl).getForUpdateCAS(ArgumentMatchers.eq("bar"), ArgumentMatchers.any());
        Mockito.verify(impl).store(ArgumentMatchers.eq("bar"), ArgumentMatchers.any(), ArgumentMatchers.any());
        Mockito.verify(operationCallback).completed(Boolean.TRUE);
    }

    @Test
    public void testCacheCASUpdate() throws Exception {
        final String key = "foo";
        final HttpCacheEntry existingValue = HttpTestUtils.makeCacheEntry();
        final HttpCacheEntry updatedValue = HttpTestUtils.makeCacheEntry();

        Mockito.when(impl.digestToStorageKey(key)).thenReturn("bar");
        Mockito.when(impl.getForUpdateCAS(ArgumentMatchers.eq("bar"), ArgumentMatchers.any())).thenAnswer((Answer<Cancellable>) invocation -> {
            final FutureCallback<String> callback = invocation.getArgument(1);
            callback.completed("stuff");
            return cancellable;
        });
        Mockito.when(impl.getStorageObject("stuff")).thenReturn(serialize(key, existingValue));
        Mockito.when(impl.updateCAS(
                ArgumentMatchers.eq("bar"),
                ArgumentMatchers.eq("stuff"),
                ArgumentMatchers.any(),
                ArgumentMatchers.any())).thenAnswer((Answer<Cancellable>) invocation -> {
                    final FutureCallback<Boolean> callback = invocation.getArgument(3);
                    callback.completed(true);
                    return cancellable;
                });

        impl.updateEntry(key, existing -> updatedValue, operationCallback);

        Mockito.verify(impl).getForUpdateCAS(ArgumentMatchers.eq("bar"), ArgumentMatchers.any());
        Mockito.verify(impl).getStorageObject("stuff");
        Mockito.verify(impl).updateCAS(ArgumentMatchers.eq("bar"), ArgumentMatchers.eq("stuff"), ArgumentMatchers.any(), ArgumentMatchers.any());
        Mockito.verify(operationCallback).completed(Boolean.TRUE);
    }

    @Test
    public void testCacheCASUpdateKeyMismatch() throws Exception {
        final String key = "foo";
        final HttpCacheEntry existingValue = HttpTestUtils.makeCacheEntry();
        final HttpCacheEntry updatedValue = HttpTestUtils.makeCacheEntry();

        Mockito.when(impl.digestToStorageKey(key)).thenReturn("bar");
        Mockito.when(impl.getForUpdateCAS(ArgumentMatchers.eq("bar"), ArgumentMatchers.any())).thenAnswer(
                (Answer<Cancellable>) invocation -> {
                    final FutureCallback<String> callback = invocation.getArgument(1);
                    callback.completed("stuff");
                    return cancellable;
                });
        Mockito.when(impl.getStorageObject("stuff")).thenReturn(serialize("not-foo", existingValue));
        Mockito.when(impl.store(
                ArgumentMatchers.eq("bar"),
                ArgumentMatchers.any(),
                ArgumentMatchers.any())).thenAnswer((Answer<Cancellable>) invocation -> {
                    final FutureCallback<Boolean> callback = invocation.getArgument(2);
                    callback.completed(true);
                    return cancellable;
                });

        impl.updateEntry(key, existing -> {
            assertThat(existing, CoreMatchers.nullValue());
            return updatedValue;
        }, operationCallback);

        Mockito.verify(impl).getForUpdateCAS(ArgumentMatchers.eq("bar"), ArgumentMatchers.any());
        Mockito.verify(impl).getStorageObject("stuff");
        Mockito.verify(impl, Mockito.never()).updateCAS(
                ArgumentMatchers.eq("bar"), ArgumentMatchers.eq("stuff"), ArgumentMatchers.any(), ArgumentMatchers.any());
        Mockito.verify(impl).store(ArgumentMatchers.eq("bar"), ArgumentMatchers.any(), ArgumentMatchers.any());
        Mockito.verify(operationCallback).completed(Boolean.TRUE);
    }

    @Test
    public void testSingleCacheUpdateRetry() throws Exception {
        final String key = "foo";
        final HttpCacheEntry existingValue = HttpTestUtils.makeCacheEntry();
        final HttpCacheEntry updatedValue = HttpTestUtils.makeCacheEntry();

        Mockito.when(impl.digestToStorageKey(key)).thenReturn("bar");
        Mockito.when(impl.getForUpdateCAS(ArgumentMatchers.eq("bar"), ArgumentMatchers.any())).thenAnswer(
                (Answer<Cancellable>) invocation -> {
                    final FutureCallback<String> callback = invocation.getArgument(1);
                    callback.completed("stuff");
                    return cancellable;
                });
        Mockito.when(impl.getStorageObject("stuff")).thenReturn(serialize(key, existingValue));
        final AtomicInteger count = new AtomicInteger(0);
        Mockito.when(impl.updateCAS(
                ArgumentMatchers.eq("bar"),
                ArgumentMatchers.eq("stuff"),
                ArgumentMatchers.any(),
                ArgumentMatchers.any())).thenAnswer((Answer<Cancellable>) invocation -> {
                    final FutureCallback<Boolean> callback = invocation.getArgument(3);
                    if (count.incrementAndGet() == 1) {
                        callback.completed(false);
                    } else {
                        callback.completed(true);
                    }
                    return cancellable;
                });

        impl.updateEntry(key, existing -> updatedValue, operationCallback);

        Mockito.verify(impl, Mockito.times(2)).getForUpdateCAS(ArgumentMatchers.eq("bar"), ArgumentMatchers.any());
        Mockito.verify(impl, Mockito.times(2)).getStorageObject("stuff");
        Mockito.verify(impl, Mockito.times(2)).updateCAS(
                ArgumentMatchers.eq("bar"), ArgumentMatchers.eq("stuff"), ArgumentMatchers.any(), ArgumentMatchers.any());
        Mockito.verify(operationCallback).completed(Boolean.TRUE);
    }

    @Test
    public void testCacheUpdateFail() throws Exception {
        final String key = "foo";
        final HttpCacheEntry existingValue = HttpTestUtils.makeCacheEntry();
        final HttpCacheEntry updatedValue = HttpTestUtils.makeCacheEntry();

        Mockito.when(impl.digestToStorageKey(key)).thenReturn("bar");
        Mockito.when(impl.getForUpdateCAS(ArgumentMatchers.eq("bar"), ArgumentMatchers.any())).thenAnswer(
                (Answer<Cancellable>) invocation -> {
                    final FutureCallback<String> callback = invocation.getArgument(1);
                    callback.completed("stuff");
                    return cancellable;
                });
        Mockito.when(impl.getStorageObject("stuff")).thenReturn(serialize(key, existingValue));
        final AtomicInteger count = new AtomicInteger(0);
        Mockito.when(impl.updateCAS(
                ArgumentMatchers.eq("bar"),
                ArgumentMatchers.eq("stuff"),
                ArgumentMatchers.any(),
                ArgumentMatchers.any())).thenAnswer((Answer<Cancellable>) invocation -> {
                    final FutureCallback<Boolean> callback = invocation.getArgument(3);
                    if (count.incrementAndGet() <= 3) {
                        callback.completed(false);
                    } else {
                        callback.completed(true);
                    }
                    return cancellable;
                });

        impl.updateEntry(key, existing -> updatedValue, operationCallback);

        Mockito.verify(impl, Mockito.times(3)).getForUpdateCAS(ArgumentMatchers.eq("bar"), ArgumentMatchers.any());
        Mockito.verify(impl, Mockito.times(3)).getStorageObject("stuff");
        Mockito.verify(impl, Mockito.times(3)).updateCAS(
                ArgumentMatchers.eq("bar"), ArgumentMatchers.eq("stuff"), ArgumentMatchers.any(), ArgumentMatchers.any());
        Mockito.verify(operationCallback).failed(ArgumentMatchers.<HttpCacheUpdateException>any());
    }

    @Test
    @SuppressWarnings("unchecked")
    public void testBulkGet() throws Exception {
        final String key1 = "foo this";
        final String key2 = "foo that";
        final String storageKey1 = "bar this";
        final String storageKey2 = "bar that";
        final HttpCacheEntry value1 = HttpTestUtils.makeCacheEntry();
        final HttpCacheEntry value2 = HttpTestUtils.makeCacheEntry();

        when(impl.digestToStorageKey(key1)).thenReturn(storageKey1);
        when(impl.digestToStorageKey(key2)).thenReturn(storageKey2);

        when(impl.bulkRestore(
                ArgumentMatchers.anyCollection(),
                ArgumentMatchers.any())).thenAnswer((Answer<Cancellable>) invocation -> {
                    final Collection<String> keys = invocation.getArgument(0);
                    final FutureCallback<Map<String, byte[]>> callback = invocation.getArgument(1);
                    final Map<String, byte[]> resultMap = new HashMap<>();
                    if (keys.contains(storageKey1)) {
                        resultMap.put(storageKey1, serialize(key1, value1));
                    }
                    if (keys.contains(storageKey2)) {
                        resultMap.put(storageKey2, serialize(key2, value2));
                    }
                    callback.completed(resultMap);
                    return cancellable;
                });

        impl.getEntries(Arrays.asList(key1, key2), bulkCacheEntryCallback);
        final ArgumentCaptor<Map<String, HttpCacheEntry>> argumentCaptor = ArgumentCaptor.forClass(Map.class);
        Mockito.verify(bulkCacheEntryCallback).completed(argumentCaptor.capture());

        final Map<String, HttpCacheEntry> entryMap = argumentCaptor.getValue();
        assertThat(entryMap, CoreMatchers.notNullValue());
        assertThat(entryMap.get(key1), HttpCacheEntryMatcher.equivalent(value1));
        assertThat(entryMap.get(key2), HttpCacheEntryMatcher.equivalent(value2));

        verify(impl, Mockito.times(2)).digestToStorageKey(key1);
        verify(impl, Mockito.times(2)).digestToStorageKey(key2);
        verify(impl).bulkRestore(
                ArgumentMatchers.eq(Arrays.asList(storageKey1, storageKey2)),
                ArgumentMatchers.any());
    }

    @Test
    @SuppressWarnings("unchecked")
    public void testBulkGetKeyMismatch() throws Exception {
        final String key1 = "foo this";
        final String key2 = "foo that";
        final String storageKey1 = "bar this";
        final String storageKey2 = "bar that";
        final HttpCacheEntry value1 = HttpTestUtils.makeCacheEntry();
        final HttpCacheEntry value2 = HttpTestUtils.makeCacheEntry();

        when(impl.digestToStorageKey(key1)).thenReturn(storageKey1);
        when(impl.digestToStorageKey(key2)).thenReturn(storageKey2);

        when(impl.bulkRestore(
                ArgumentMatchers.anyCollection(),
                ArgumentMatchers.any())).thenAnswer((Answer<Cancellable>) invocation -> {
                    final Collection<String> keys = invocation.getArgument(0);
                    final FutureCallback<Map<String, byte[]>> callback = invocation.getArgument(1);
                    final Map<String, byte[]> resultMap = new HashMap<>();
                    if (keys.contains(storageKey1)) {
                        resultMap.put(storageKey1, serialize(key1, value1));
                    }
                    if (keys.contains(storageKey2)) {
                        resultMap.put(storageKey2, serialize("not foo", value2));
                    }
                    callback.completed(resultMap);
                    return cancellable;
                });

        impl.getEntries(Arrays.asList(key1, key2), bulkCacheEntryCallback);
        final ArgumentCaptor<Map<String, HttpCacheEntry>> argumentCaptor = ArgumentCaptor.forClass(Map.class);
        Mockito.verify(bulkCacheEntryCallback).completed(argumentCaptor.capture());

        final Map<String, HttpCacheEntry> entryMap = argumentCaptor.getValue();
        assertThat(entryMap, CoreMatchers.notNullValue());
        assertThat(entryMap.get(key1), HttpCacheEntryMatcher.equivalent(value1));
        assertThat(entryMap.get(key2), CoreMatchers.nullValue());

        verify(impl, Mockito.times(2)).digestToStorageKey(key1);
        verify(impl, Mockito.times(2)).digestToStorageKey(key2);
        verify(impl).bulkRestore(
                ArgumentMatchers.eq(Arrays.asList(storageKey1, storageKey2)),
                ArgumentMatchers.any());
    }

}
