package org.gnunet.mesh;

import org.gnunet.core.Core;
import org.gnunet.core.PeerIdentityContinuation;
import org.gnunet.testing.TestingFixture;
import org.gnunet.testing.TestingSubsystem;
import org.gnunet.util.*;
import org.junit.Test;

/**
 * ...
 *
 * @author Florian Dold
 */
public class MeshTest extends TestingFixture {
    public static class MessageHandler1 extends MeshRunabout {
        public Mesh m1;
        public Mesh m2;
        public void visit(TestMessage m) {
            System.out.println("got test message");
            m1.destroy();
            m2.destroy();
        }
    }

    public static class MyChannelEndHandler implements ChannelEndHandler {
        Mesh mesh1;
        PeerIdentity peerIdentity;
        @Override
        public void onChannelEnd(Mesh.Channel channel) {
            Mesh.Channel myChannel = mesh1.createChannel(peerIdentity, 42, false, true);
            myChannel.send(new TestMessage());
        }
    }

    /**
     * Send a message locally, to our own peer.
     */
    @Test (timeout = 5000)
    public void test_mesh_send() {
        Program.configureLogging("DEBUG");
        // we want the full arm here (starts both mesh and core)
        final TestingSubsystem ts = new TestingSubsystem("arm");
        final Configuration cfg = ts.getConfiguration();

        final MessageHandler1 mh = new MessageHandler1();
        // FIXME: use CryptoEcc instead of Core once available and compatible
        Core.withPeerIdentity(cfg, new PeerIdentityContinuation() {
            @Override
            public void cont(PeerIdentity peerIdentity) {
                System.out.println("got peer identity from core");
                //
                MyChannelEndHandler teh = new MyChannelEndHandler();
                // first mesh handle, used to send the message
                final Mesh mesh1 = new Mesh(cfg, teh);
                teh.mesh1 = mesh1;
                teh.peerIdentity = peerIdentity;
                // second mesh handle, used to receive the message
                final Mesh mesh2 = new Mesh(cfg, new InboundChannelHandler() {
                    @Override
                    public void onInboundChannel(Mesh.Channel tunnel, PeerIdentity initiator) {
                        System.out.println("got inbound channel " + initiator);
                    }
                }, new ChannelEndHandler() {
                    @Override
                    public void onChannelEnd(Mesh.Channel tunnel) {
                        System.out.println("channel end handler called");
                    }
                }, mh, 42);
                mh.m1 = mesh1;
                mh.m2 = mesh2;
                Mesh.Channel channel = mesh1.createChannel(peerIdentity, 42, false, true);
                channel.send(new TestMessage());
            }
        });
        Scheduler.run();
    }
}
