package meerkat.bulletinboard;

import com.google.protobuf.ByteString;
import meerkat.crypto.Digest;
import meerkat.protobuf.BulletinBoardApi.*;

import java.util.Collection;

/**
 * Created by Arbel Deutsch Peled on 01-Mar-16.
 * Implementation of Checksum via bitwise XOR of the bytes of message IDs
 */
public class SimpleChecksum implements Checksum {

    private Digest digest;
    private long checksum;

    public SimpleChecksum() {
        digest = null;
        reset();
    }

    @Override
    public void setDigest(Digest digest) {
        this.digest = digest;
    }

    @Override
    public void reset() {
        checksum = 0;
    }

    @Override
    public void update(MessageID messageID) {
        ByteString messageIDByteString = messageID.getID();
        update(messageIDByteString);
    }

    @Override
    public void update(Collection<MessageID> messageIDs) {

        for (MessageID messageID : messageIDs){
            update(messageID);
        }

    }

    @Override
    public void update(ByteString messageID) {
        for (int i = 0 ; i < messageID.size() ; i++){
            checksum &= messageID.byteAt(i);
        }
    }

    @Override
    public void update(byte[] messageID) {
        for (int i = 0 ; i < messageID.length ; i++){
            checksum &= messageID[i];
        }
    }

    private void checkDigest() throws IllegalStateException {

        if (digest == null){
            throw new IllegalStateException("Digest method not set. Use setDigest method before calling digestAndUpdate.");
        }

    }

    @Override
    public void digestAndUpdate(BulletinBoardMessage bulletinBoardMessage) throws IllegalStateException {

        checkDigest();

        digest.reset();
        digest.update(bulletinBoardMessage);
        update(digest.digest());

    }

    @Override
    public void digestAndUpdate(Collection<BulletinBoardMessage> bulletinBoardMessages) throws IllegalStateException {

        for (BulletinBoardMessage bulletinBoardMessage : bulletinBoardMessages){
            digestAndUpdate(bulletinBoardMessage);
        }

    }

    @Override
    public long getChecksum() {
        return checksum;
    }

    @Override
    public long getChecksum(MessageID messageID) {
        update(messageID);
        return getChecksum();
    }

    @Override
    public long getChecksum(ByteString messageID) {
        update(messageID);
        return getChecksum();
    }

    @Override
    public long getChecksum(byte[] messageID) {
        update(messageID);
        return getChecksum();
    }

    @Override
    public long getChecksum(Collection<MessageID> messageIDs) {
        update(messageIDs);
        return getChecksum();
    }

    @Override
    public long digestAndGetChecksum(BulletinBoardMessage bulletinBoardMessage) throws IllegalStateException {
        digestAndUpdate(bulletinBoardMessage);
        return getChecksum();
    }

    @Override
    public long digestAndGetChecksum(Collection<BulletinBoardMessage> bulletinBoardMessages) throws IllegalStateException {
        digestAndUpdate(bulletinBoardMessages);
        return getChecksum();
    }
}
