/*
 * 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.jackrabbit.oak.segment.file.tar;

import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
import static org.apache.jackrabbit.oak.segment.file.tar.GCGeneration.newGCGeneration;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.internal.util.collections.Sets.newSet;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import org.apache.jackrabbit.oak.segment.spi.monitor.FileStoreMonitorAdapter;
import org.apache.jackrabbit.oak.segment.spi.monitor.IOMonitorAdapter;
import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveEntry;
import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveManager;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

public class TarFileTest {

    protected static GCGeneration generation(int full) {
        return newGCGeneration(full, 0, false);
    }

    @Rule
    public TemporaryFolder folder = new TemporaryFolder(new File("target"));

    protected SegmentArchiveManager archiveManager;

    @Before
    public void setUp() throws IOException {
        archiveManager = new SegmentTarManager(folder.newFolder(), new FileStoreMonitorAdapter(), new IOMonitorAdapter(), false);
    }

    protected long getWriteAndReadExpectedSize() {
        return 5120;
    }

    @Test
    public void testWriteAndRead() throws IOException {
        UUID id = UUID.randomUUID();
        long msb = id.getMostSignificantBits();
        long lsb = id.getLeastSignificantBits() & (-1 >>> 4); // OAK-1672
        byte[] data = "Hello, World!".getBytes(UTF_8);

        try (TarWriter writer = new TarWriter(archiveManager, "data00000a.tar")) {
            writer.writeEntry(msb, lsb, data, 0, data.length, generation(0));
            assertEquals(ByteBuffer.wrap(data), writer.readEntry(msb, lsb));
        }

        try (TarReader reader = TarReader.open("data00000a.tar", archiveManager)) {
            assertEquals(getWriteAndReadExpectedSize(), reader.size());
            assertEquals(ByteBuffer.wrap(data), reader.readEntry(msb, lsb));
        }
    }

    @Test
    public void testGCGeneration() throws Exception {
        UUID id = UUID.randomUUID();
        long msb = id.getMostSignificantBits();
        long lsb = id.getLeastSignificantBits();
        String data = "test";
        byte[] buffer = data.getBytes(UTF_8);

        try (TarWriter writer = new TarWriter(archiveManager, "data00000a.tar")) {
            writer.writeEntry(msb, lsb, buffer, 0, buffer.length, newGCGeneration(1, 2, false));
        }

        try (TarReader reader = TarReader.open("data00000a.tar", archiveManager)) {
            SegmentArchiveEntry[] entries = reader.getEntries();
            assertEquals(newGCGeneration(1, 2, false), newGCGeneration(entries[0]));
        }
    }

    @Test
    public void testGCGenerationIsCompactedFlagNotErased() throws Exception {
        UUID id = UUID.randomUUID();
        long msb = id.getMostSignificantBits();
        long lsb = id.getLeastSignificantBits();
        String data = "test";
        byte[] buffer = data.getBytes(UTF_8);

        try (TarWriter writer = new TarWriter(archiveManager, "data00000a.tar")) {
            writer.writeEntry(msb, lsb, buffer, 0, buffer.length, newGCGeneration(1, 2, true));
        }

        try (TarReader reader = TarReader.open("data00000a.tar", archiveManager)) {
            SegmentArchiveEntry[] entries = reader.getEntries();
            assertEquals(newGCGeneration(1, 2, true), newGCGeneration(entries[0]));
        }
    }

    @Test
    public void testWriteAndReadBinaryReferences() throws Exception {
        try (TarWriter writer = new TarWriter(archiveManager, "data00000a.tar")) {
            writer.writeEntry(0x00, 0x00, new byte[] {0x01, 0x02, 0x3}, 0, 3, generation(0));

            writer.addBinaryReference(generation(1), new UUID(1, 0), "r0");
            writer.addBinaryReference(generation(1), new UUID(1, 1), "r1");
            writer.addBinaryReference(generation(1), new UUID(1, 2), "r2");
            writer.addBinaryReference(generation(1), new UUID(1, 3), "r3");

            writer.addBinaryReference(generation(2), new UUID(2, 0), "r4");
            writer.addBinaryReference(generation(2), new UUID(2, 1), "r5");
            writer.addBinaryReference(generation(2), new UUID(2, 2), "r6");

            writer.addBinaryReference(generation(3), new UUID(3, 0), "r7");
            writer.addBinaryReference(generation(3), new UUID(3, 1), "r8");
        }

        Map<UUID, Set<String>> one = newHashMap();

        one.put(new UUID(1, 0), newSet("r0"));
        one.put(new UUID(1, 1), newSet("r1"));
        one.put(new UUID(1, 2), newSet("r2"));
        one.put(new UUID(1, 3), newSet("r3"));

        Map<UUID, Set<String>> two = newHashMap();

        two.put(new UUID(2, 0), newSet("r4"));
        two.put(new UUID(2, 1), newSet("r5"));
        two.put(new UUID(2, 2), newSet("r6"));

        Map<UUID, Set<String>> three = newHashMap();

        three.put(new UUID(3, 0), newSet("r7"));
        three.put(new UUID(3, 1), newSet("r8"));

        Map<GCGeneration, Map<UUID, Set<String>>> expected = newHashMap();

        expected.put(generation(1), one);
        expected.put(generation(2), two);
        expected.put(generation(3), three);

        try (TarReader reader = TarReader.open("data00000a.tar", archiveManager)) {
            Map<GCGeneration, Map<UUID, Set<String>>> actual = new HashMap<>();

            reader.getBinaryReferences().forEach((generation, full, compacted, id, reference) -> {
                actual
                    .computeIfAbsent(newGCGeneration(generation, full, compacted), x -> new HashMap<>())
                    .computeIfAbsent(id, x -> new HashSet<>())
                    .add(reference);
            });

            assertEquals(expected, actual);
        }
    }

    @Test
    public void binaryReferencesIndexShouldBeTrimmedDownOnSweep() throws Exception {
        try (TarWriter writer = new TarWriter(archiveManager, "data00000a.tar")) {
            writer.writeEntry(1, 1, new byte[] {1}, 0, 1, generation(1));
            writer.writeEntry(1, 2, new byte[] {1}, 0, 1, generation(1));
            writer.writeEntry(2, 1, new byte[] {1}, 0, 1, generation(2));
            writer.writeEntry(2, 2, new byte[] {1}, 0, 1, generation(2));

            writer.addBinaryReference(generation(1), new UUID(1, 1), "a");
            writer.addBinaryReference(generation(1), new UUID(1, 2), "b");

            writer.addBinaryReference(generation(2), new UUID(2, 1), "c");
            writer.addBinaryReference(generation(2), new UUID(2, 2), "d");
        }

        Set<UUID> sweep = newSet(new UUID(1, 1), new UUID(2, 2));

        try (TarReader reader = TarReader.open("data00000a.tar", archiveManager)) {
            try (TarReader swept = reader.sweep(sweep, new HashSet<>())) {
                assertNotNull(swept);

                Map<UUID, Set<String>> one = newHashMap();
                one.put(new UUID(1, 2), newSet("b"));

                Map<UUID, Set<String>> two = newHashMap();
                two.put(new UUID(2, 1), newSet("c"));

                Map<GCGeneration, Map<UUID, Set<String>>> references = newHashMap();
                references.put(generation(1), one);
                references.put(generation(2), two);

                Map<GCGeneration, Map<UUID, Set<String>>> actual = new HashMap<>();
                swept.getBinaryReferences().forEach((generation, full, compacted, uuid, reference) -> {
                    actual
                        .computeIfAbsent(newGCGeneration(generation, full, compacted), x -> new HashMap<>())
                        .computeIfAbsent(uuid, x -> new HashSet<>())
                        .add(reference);
                });

                assertEquals(references, actual);
            }
        }
    }

    @Test
    public void binaryReferencesIndexShouldContainCompleteGCGeneration() throws Exception {
        try (TarWriter writer = new TarWriter(archiveManager, "data00000a.tar")) {
            writer.writeEntry(0x00, 0x00, new byte[] {0x01, 0x02, 0x3}, 0, 3, generation(0));
            writer.addBinaryReference(newGCGeneration(1, 2, false), new UUID(1, 2), "r1");
            writer.addBinaryReference(newGCGeneration(3, 4, true), new UUID(3, 4), "r2");
        }
        try (TarReader reader = TarReader.open("data00000a.tar", archiveManager)) {
            Set<GCGeneration> expected = new HashSet<>();
            expected.add(newGCGeneration(1, 2, false));
            expected.add(newGCGeneration(3, 4, true));
            Set<GCGeneration> actual = new HashSet<>();
            reader.getBinaryReferences().forEach((generation, full, compacted, segment, reference) -> {
                actual.add(newGCGeneration(generation, full, compacted));
            });
            assertEquals(expected, actual);
        }
    }

    @Test
    public void graphShouldBeTrimmedDownOnSweep() throws Exception {
        try (TarWriter writer = new TarWriter(archiveManager, "data00000a.tar")) {
            writer.writeEntry(1, 1, new byte[] {1}, 0, 1, generation(1));
            writer.writeEntry(1, 2, new byte[] {1}, 0, 1, generation(1));
            writer.writeEntry(1, 3, new byte[] {1}, 0, 1, generation(1));
            writer.writeEntry(2, 1, new byte[] {1}, 0, 1, generation(2));
            writer.writeEntry(2, 2, new byte[] {1}, 0, 1, generation(2));
            writer.writeEntry(2, 3, new byte[] {1}, 0, 1, generation(2));

            writer.addGraphEdge(new UUID(1, 1), new UUID(1, 2));
            writer.addGraphEdge(new UUID(1, 2), new UUID(1, 3));
            writer.addGraphEdge(new UUID(2, 1), new UUID(2, 2));
            writer.addGraphEdge(new UUID(2, 2), new UUID(2, 3));
        }

        Set<UUID> sweep = newSet(new UUID(1, 2), new UUID(2, 3));

        try (TarReader reader = TarReader.open("data00000a.tar", archiveManager)) {
            try (TarReader swept = reader.sweep(sweep, new HashSet<UUID>())) {
                assertNotNull(swept);

                Map<UUID, List<UUID>> graph = newHashMap();
                graph.put(new UUID(2, 1), newArrayList(new UUID(2, 2)));

                assertEquals(graph, swept.getGraph());
            }
        }
    }

}
