package meerkat.bulletinboard.workers.singleserver;

import meerkat.bulletinboard.SingleServerWorker;
import meerkat.comm.CommunicationException;
import meerkat.comm.MessageInputStream;
import meerkat.protobuf.BulletinBoardApi.*;
import meerkat.rest.Constants;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.List;

import static meerkat.bulletinboard.BulletinBoardConstants.BULLETIN_BOARD_SERVER_PATH;
import static meerkat.bulletinboard.BulletinBoardConstants.READ_BATCH_PATH;

/**
 * Created by Arbel Deutsch Peled on 27-Dec-15.
 */
public class SingleServerReadBatchWorker extends SingleServerWorker<BatchQuery, List<BatchChunk>> {

    public SingleServerReadBatchWorker(String serverAddress, BatchQuery payload, int maxRetry) {
        super(serverAddress, payload, maxRetry);
    }

    /**
     * This method carries out the actual communication with the server via HTTP Post
     * Upon successful retrieval from the server the method returns the received values
     * @return the complete batch as read from the server
     * @throws CommunicationException if the server's response is invalid
     */
    public List<BatchChunk> call() throws CommunicationException{

        Client client = clientLocal.get();

        WebTarget webTarget;

        // Get the batch data

        webTarget = client.target(serverAddress).path(BULLETIN_BOARD_SERVER_PATH).path(READ_BATCH_PATH);
        InputStream in = webTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(payload, Constants.MEDIATYPE_PROTOBUF), InputStream.class);

        MessageInputStream<BatchChunk> inputStream = null;

        try {

            inputStream = MessageInputStream.MessageInputStreamFactory.createMessageInputStream(in, BatchChunk.class);

            return inputStream.asList();

        } catch (IOException | InvocationTargetException e) {

            // Read failed
            throw new CommunicationException("Could not contact the server or server returned illegal result");

        } catch (NoSuchMethodException | IllegalAccessException e) {

            throw new CommunicationException("MessageInputStream error");

        } finally {
            try {
                inputStream.close();
            } catch (IOException ignored) {}
        }

    }

}
