package peergos.server;

import peergos.server.corenode.*;
import peergos.server.mutable.*;
import peergos.server.storage.*;
import peergos.shared.*;
import peergos.shared.crypto.*;
import peergos.shared.crypto.asymmetric.*;
import peergos.shared.crypto.hash.*;
import peergos.shared.crypto.random.*;
import peergos.shared.mutable.*;
import peergos.shared.storage.*;
import peergos.shared.user.*;
import peergos.shared.user.fs.*;

import java.io.*;
import java.net.*;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;

/**
 *  Use this class to experiment with existing data without committing any changes or writing any data to disk
 */
public class Playground {

    public static void main(String[] args) throws Exception {
        Crypto crypto = Crypto.initJava();
        NetworkAccess source = NetworkAccess.buildJava(new URL("https://demo.peergos.net")).get();

        ContentAddressedStorage nonWriteThroughIpfs = new NonWriteThroughStorage(source.dhtClient);
        NonWriteThroughCoreNode nonWriteThroughCoreNode = new NonWriteThroughCoreNode(source.coreNode, nonWriteThroughIpfs);
        MutablePointers nonWriteThroughPointers = new NonWriteThroughMutablePointers(source.mutable, nonWriteThroughIpfs);
        MutableTreeImpl nonWriteThroughTree = new MutableTreeImpl(nonWriteThroughPointers, nonWriteThroughIpfs);
        NetworkAccess nonWriteThrough = new NetworkAccess(nonWriteThroughCoreNode,
                nonWriteThroughIpfs,
                nonWriteThroughPointers,
                nonWriteThroughTree, source.usernames, false);

        String username = args[0];
        Console console = System.console();
        String password = new String(console.readPassword("Enter password for " + username + ":"));
        UserContext context = UserContext.signIn(username, password, nonWriteThrough, crypto).get();
        // Do something
        Set<PublicKeyHash> ownedKeys = WriterData.getOwnedKeysRecursive(username, nonWriteThroughCoreNode, nonWriteThroughPointers, nonWriteThroughIpfs);
        for (PublicKeyHash ownedKey : ownedKeys) {
            if (ownedKey.equals(context.signer.publicKeyHash))
                continue; // only the writer has a tree
            CommittedWriterData existing = WriterData.getWriterData(ownedKey, nonWriteThroughPointers, nonWriteThroughIpfs).get();
            if (existing.props.tree.isPresent())
                continue;
            SecretSigningKey signingKey = context.getUserRoot().get().getEntryWriterKey().get();
            SigningPrivateKeyAndPublicHash writer = new SigningPrivateKeyAndPublicHash(ownedKey, signingKey);
            // invert the following two lines to actually commit the migration
            existing.props.migrateToChamp(writer, existing.hash, nonWriteThrough, res -> {}).get();
//            existing.props.migrateToChamp(writer, existing.hash, source, res -> {}).get();
        }
        // Can we still log in?
        UserContext context2 = UserContext.signIn(username, password, nonWriteThrough, crypto).get();
        System.out.println(context2.getUserRoot().get().getName());
    }
}

@@ -1025,39 +1025,31 @@
         
-NonWriteThroughCoreNode
+MutablePointers
  nonWrit
@@ -1056,24 +1056,24 @@
 eThrough
-CoreNode
+Pointers
  = new N
@@ -1090,24 +1090,31 @@
 ough
-CoreNode
+MutablePointers
 (source.
 core
@@ -1113,15 +1113,14 @@
 rce.
-coreNod
+mutabl
 e, n
@@ -1144,39 +1144,47 @@
 s);%0A        
-MutablePointers
+NonWriteThroughCoreNode
  nonWriteThr
@@ -1183,32 +1183,32 @@
 WriteThrough
-Pointers
+CoreNode
  = new NonWr
@@ -1217,39 +1217,32 @@
 eThrough
-MutablePointers
+CoreNode
 (source.
 mutable,
@@ -1225,38 +1225,39 @@
 CoreNode(source.
-mutabl
+coreNod
 e, nonWriteThrou
@@ -1887,31 +1887,639 @@
 ();%0A
-        // Do something
+%0A        // invert the following two lines to actually commit the experiment%0A        experiment(username, context, nonWriteThrough);%0A//        experiment(username, context, source);%0A%0A        // Can we still log in?%0A        UserContext context2 = UserContext.signIn(username, password, nonWriteThrough, crypto).get();%0A        System.out.println(context2.getUserRoot().get().getName());%0A    %7D%0A%0A    private static void experiment(String username,%0A                                   UserContext context,%0A                                   NetworkAccess network) throws Exception %7B%0A        // Do something dangerous (you only live once)
 %0A   
@@ -2602,76 +2602,59 @@
 e, n
-onWriteThroughCoreNode, nonWriteThroughPointers, nonWriteThroughIpfs
+etwork.coreNode, network.mutable, network.dhtClient
 );%0A 
@@ -2905,51 +2905,41 @@
 y, n
-onWriteThroughPointers, nonWriteThroughIpfs
+etwork.mutable, network.dhtClient
 ).ge
@@ -3241,479 +3241,97 @@
     
-// invert the following two lines to actually commit the migration%0A            existing.props.migrateToChamp(writer, existing.hash, nonWriteThrough, res -%3E %7B%7D).get();%0A//            existing.props.migrateToChamp(writer, existing.hash, source, res -%3E %7B%7D).get();%0A        %7D%0A        // Can we still log in?%0A        UserContext context2 = UserContext.signIn(username, password, nonWriteThrough, crypto).get();%0A        System.out.println(context2.getUserRoot().get().getName());
+existing.props.migrateToChamp(writer, existing.hash, network, res -%3E %7B%7D).get();%0A        %7D
 %0A   

Make playground clearer