package meerkat.comm;

import com.google.protobuf.*;
import meerkat.comm.MessageInputStream.MessageInputStreamFactory;
import meerkat.protobuf.BulletinBoardApi.*;
import meerkat.protobuf.Crypto;
import meerkat.util.BulletinBoardMessageComparator;
import org.junit.Test;

import java.io.*;
import java.lang.reflect.InvocationTargetException;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsEqual.equalTo;

/**
 * Created by Arbel Deutsch Peled on 21-Feb-16.
 * Tests for MessageInputStream and MessageOutputStream classes
 */
public class MessageStreamTest {

    @Test
    public void testWithBulletinBoardMessages() {

        MessageOutputStream<BulletinBoardMessage> out;
        MessageInputStream<BulletinBoardMessage> in;
        ByteArrayOutputStream stream = new ByteArrayOutputStream();

        BulletinBoardMessageComparator comparator = new BulletinBoardMessageComparator();

        byte[] b1 = {(byte) 1, (byte) 2, (byte) 3, (byte) 4};
        byte[] b2 = {(byte) 11, (byte) 12, (byte) 13, (byte) 14};
        byte[] b3 = {(byte) 21, (byte) 22, (byte) 23, (byte) 24};

        try {

            out = new MessageOutputStream<>(stream);

        } catch (IOException e) {

            System.err.println(e.getMessage());
            assertThat("Error creating streams: " + e.getMessage(), false);
            return;

        }



        BulletinBoardMessage message = BulletinBoardMessage.newBuilder()
                .setEntryNum(1)
                .setMsg(UnsignedBulletinBoardMessage.newBuilder()
                        .setData(ByteString.copyFrom(b1))
                        .addTag("Test")
                        .addTag("1234")
                        .setTimestamp(com.google.protobuf.Timestamp.newBuilder()
                                .setSeconds(19823451)
                                .setNanos(2134)
                                .build())
                        .build())
                .addSig(Crypto.Signature.newBuilder()
                        .setSignerId(ByteString.copyFrom(b2))
                        .setData(ByteString.copyFrom(b3))
                        .build())
                .build();

        try {

            out.writeMessage(message);

        } catch (IOException e) {

            System.err.println(e.getMessage());
            assertThat("Error writing message: " + e.getMessage(), false);

        }

        try {

            in = MessageInputStreamFactory.createMessageInputStream(
                    new ByteArrayInputStream(stream.toByteArray()),
                    BulletinBoardMessage.class);

            assertThat("Retrieved message was not identical to send message", comparator.compare(message, in.readMessage(BulletinBoardMessage.class)), is(equalTo(0)));

        } catch (IOException e) {

            System.err.println(e.getMessage());
            assertThat("Error reading message: " + e.getMessage(), false);

        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            System.err.println(e.getMessage());
            assertThat("Error creating input stream " + e.getMessage(), false);
        }

    }

}
