package meerkat.bulletinboard;


import com.google.protobuf.BoolValue;
import com.google.protobuf.ByteString;
import com.google.protobuf.TextFormat;

import com.google.protobuf.Timestamp;
import meerkat.comm.MessageInputStream;
import meerkat.protobuf.Crypto.*;
import meerkat.protobuf.BulletinBoardApi.*;
import meerkat.protobuf.Comm.*;
import static meerkat.bulletinboard.BulletinBoardConstants.*;
import meerkat.rest.Constants;
import meerkat.rest.ProtobufMessageBodyReader;
import meerkat.rest.ProtobufMessageBodyWriter;

import org.junit.Before;
import org.junit.Test;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
import java.io.InputStream;
import java.util.List;

public class BulletinBoardSQLServerIntegrationTest {

    private static String PROP_GETTY_URL = "gretty.httpBaseURI";
    private static String DEFAULT_BASE_URL = "http://localhost:8081";
    private static String BASE_URL =  System.getProperty(PROP_GETTY_URL, DEFAULT_BASE_URL);

    Client client;

    @Before
    public void setup() throws Exception {
    	System.err.println("Registering client");
        client = ClientBuilder.newClient();
        client.register(ProtobufMessageBodyReader.class);
        client.register(ProtobufMessageBodyWriter.class);

    }

    @Test
    public void testPost() throws Exception {
        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};
        byte[] b4 = {(byte) 4, (byte) 5, (byte) 100, (byte) -50, (byte) 0};

        Timestamp t1 = Timestamp.newBuilder()
                .setSeconds(8276482)
                .setNanos(4314)
                .build();

        Timestamp t2 = Timestamp.newBuilder()
                .setSeconds(987591)
                .setNanos(1513)
                .build();

        WebTarget webTarget;
        Response response;
        BoolValue bool;
        
        BulletinBoardMessage msg;
        
        MessageFilterList filterList; 
        List<BulletinBoardMessage> msgList;
        
        // Test writing mechanism
        
        System.err.println("******** Testing: " + POST_MESSAGE_PATH);
        webTarget = client.target(BASE_URL).path(BULLETIN_BOARD_SERVER_PATH).path(POST_MESSAGE_PATH);
        System.err.println(webTarget.getUri());
        
        msg = BulletinBoardMessage.newBuilder()
                .setMsg(UnsignedBulletinBoardMessage.newBuilder()
                        .addTag("Signature")
                        .addTag("Trustee")
                        .setData(ByteString.copyFrom(b1))
                        .setTimestamp(t1)
                        .build())
                .addSig(Signature.newBuilder()
                        .setType(SignatureType.DSA)
                        .setData(ByteString.copyFrom(b2))
                        .setSignerId(ByteString.copyFrom(b3))
                        .build())
                .addSig(Signature.newBuilder()
                        .setType(SignatureType.ECDSA)
                        .setData(ByteString.copyFrom(b3))
                        .setSignerId(ByteString.copyFrom(b2))
                        .build())
                .build();

        response = webTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(msg, Constants.MEDIATYPE_PROTOBUF));
        System.err.println(response);
        bool = response.readEntity(BoolValue.class);
    	assert bool.getValue();
        
    	msg = BulletinBoardMessage.newBuilder()
                .setMsg(UnsignedBulletinBoardMessage.newBuilder()
                        .addTag("Vote")
                        .addTag("Trustee")
                        .setData(ByteString.copyFrom(b4))
                        .setTimestamp(t2)
                        .build())
                .addSig(Signature.newBuilder()
                        .setType(SignatureType.ECDSA)
                        .setData(ByteString.copyFrom(b4))
                        .setSignerId(ByteString.copyFrom(b2))
                        .build())
                .build();
    	
    	response = webTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(msg, Constants.MEDIATYPE_PROTOBUF));
        System.err.println(response);
        bool = response.readEntity(BoolValue.class);
    	assert bool.getValue();
    	
    	// Test reading mechanism
    	
    	System.err.println("******** Testing: " + READ_MESSAGES_PATH);
    	webTarget = client.target(BASE_URL).path(BULLETIN_BOARD_SERVER_PATH).path(READ_MESSAGES_PATH);
    	filterList = MessageFilterList.newBuilder()
    					.addFilter(
    							MessageFilter.newBuilder()
    							.setType(FilterType.TAG)
    							.setTag("Vote")
    							.build()
    							)
    					.build();

    	InputStream in = webTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(filterList, Constants.MEDIATYPE_PROTOBUF), InputStream.class);

        MessageInputStream<BulletinBoardMessage> inputStream =
                MessageInputStream.MessageInputStreamFactory.createMessageInputStream(in, BulletinBoardMessage.class);

    	msgList = inputStream.asList();
    	System.err.println("List size: " + msgList.size());
    	System.err.println("This is the list:");

        for (BulletinBoardMessage message : msgList) {
            System.err.println(TextFormat.printToString(message));
        }

    	assert msgList.size() == 1;
    }

}
