package peergos.server.tests;

import org.junit.*;
import peergos.server.*;
import peergos.server.storage.*;
import peergos.server.util.*;
import peergos.shared.*;
import peergos.shared.social.*;
import peergos.shared.storage.*;
import peergos.shared.user.*;
import peergos.shared.user.fs.*;
import peergos.shared.user.fs.cryptree.*;

import java.nio.file.*;
import java.util.*;

import static peergos.server.tests.PeergosNetworkUtils.*;

public class RequestCountTests {

    private static final Crypto crypto = Main.initCrypto();
    private static Args args = UserTests.buildArgs();
    private static UserService service;
    private Random random = new Random();
    private final NetworkAccess network;
    private final RequestCountingStorage storageCounter;

    public RequestCountTests() {
        WriteSynchronizer synchronizer = new WriteSynchronizer(service.mutable, service.storage, crypto.hasher);
        MutableTree mutableTree = new MutableTreeImpl(service.mutable, service.storage, crypto.hasher, synchronizer);
        RequestCountingStorage requestCounter = new RequestCountingStorage(service.storage);
        this.storageCounter = requestCounter;
        CachingStorage dhtClient = new CachingStorage(requestCounter, 1_000, 50 * 1024);
        this.network = new NetworkAccess(service.coreNode, service.social, dhtClient,
                service.mutable, mutableTree, synchronizer, service.controller, service.usage, service.serverMessages,
                crypto.hasher, Arrays.asList("peergos"), false);
    }

    @BeforeClass
    public static void init() {
        service = Main.PKI_INIT.main(args);
    }

    @Test
    public void socialFeedRequestCount() {
        CryptreeNode.setMaxChildLinkPerBlob(10);
        String password = "notagoodone";

        storageCounter.reset();
        UserContext sharer = PeergosNetworkUtils.ensureSignedUp(generateUsername(random), password, network, crypto);
        Assert.assertTrue("signup request count", storageCounter.requestTotal() <= 37);

        storageCounter.reset();
        PeergosNetworkUtils.ensureSignedUp(sharer.username, password, network, crypto);
        Assert.assertTrue("login request count", storageCounter.requestTotal() <= 5);

        List<UserContext> shareeUsers = getUserContextsForNode(network, random, 1, Arrays.asList(password, password));
        UserContext a = shareeUsers.get(0);

        // friend sharer with other user
        storageCounter.reset();
        friendBetweenGroups(Arrays.asList(sharer), shareeUsers);
        Assert.assertTrue(storageCounter.requestTotal() <= 500);

        // friends are now connected
        // share a file from u1 to u2
        byte[] fileData = sharer.crypto.random.randomBytes(1*1024*1024);
        Path file1 = Paths.get(sharer.username, "first-file.txt");
        uploadAndShare(fileData, file1, sharer, a.username);

        // check 'a' can see the shared file in their social feed
        storageCounter.reset();
        SocialFeed feed = a.getSocialFeed().join();
        Assert.assertTrue(storageCounter.requestTotal() <= 82);
        int feedSize = 2;

        storageCounter.reset();
        List<SharedItem> items = feed.getShared(feedSize, feedSize + 1, a.crypto, a.network).join();
        Assert.assertTrue(storageCounter.requestTotal() <= 1);

        storageCounter.reset();
        a.getFiles(items).join();
        Assert.assertTrue(storageCounter.requestTotal() <= 1);

        // share more items
        for (int i=0; i < 5; i++) {
            byte[] data = sharer.crypto.random.randomBytes(1*1024*1024);
            Path file = Paths.get(sharer.username, random.nextInt() + "first-file.txt");
            uploadAndShare(data, file, sharer, a.username);
        }

        storageCounter.reset();
        SocialFeed feed2 = a.getSocialFeed().join().update().join();
        Assert.assertTrue(storageCounter.requestTotal() <= 39);

        storageCounter.reset();
        List<SharedItem> items2 = feed2.getShared(feedSize + 1, feedSize + 6, a.crypto, a.network).join();
        Assert.assertTrue(storageCounter.requestTotal() <= 1);
    }

    private static void uploadAndShare(byte[] data, Path file, UserContext sharer, String sharee) {
        String filename = file.getFileName().toString();
        sharer.getByPath(file.getParent()).join().get()
                .uploadOrReplaceFile(filename, AsyncReader.build(data), data.length,
                        sharer.network, crypto, l -> {}, crypto.random.randomBytes(32)).join();
        sharer.shareReadAccessWith(file, Set.of(sharee)).join();
    }
}

@@ -2215,17 +2215,17 @@
 al() %3C= 
-5
+8
 );%0A%0A    
@@ -2582,18 +2582,18 @@
 l() %3C= 5
-00
+28
 );%0A%0A    
@@ -3075,17 +3075,17 @@
 l() %3C= 8
-2
+5
 );%0A     
@@ -3420,33 +3420,33 @@
 questTotal() %3C= 
-1
+0
 );%0A%0A        // s
@@ -3894,10 +3894,10 @@
  %3C= 
-39
+42
 );%0A%0A

Update request count test numbers