package BFTSmartBlockchain;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.codec.binary.Hex;

public class Blockchain {

	public Map<String, Block> blocksByHash;
	public Block head;
	
	public Blockchain() {
		blocksByHash = new HashMap<String, Block>();
		head = null;
	}
	
	public void AddBlock(Block b) {
		// the block must be verified
		if (b.Verify() == true) {
			// we must have the previous block, if there is one
			if (b.prevBlockHash == null || blocksByHash.containsKey(Hex.encodeHexString(b.prevBlockHash))) {
				// put the block into our map
				blocksByHash.put(Hex.encodeHexString(b.blockHash), b);
				/// if we do not have a head, or if this block is successor to the head 
				if (head == null || Arrays.equals(b.prevBlockHash,  head.blockHash)) {
					// this block is the new head
					head = b;
				}
			}
		}
	}
	
	public boolean Verify(Block b) {
		// the block must verify
		return b.Verify() && 
				// if there is a previous block, it must be in the blockchain
				(b.prevBlockHash == null || blocksByHash.containsKey(Hex.encodeHexString(b.prevBlockHash))) &&
				// and if there is a previous block, it must verify like this one
				(b.prevBlockHash == null || Verify(blocksByHash.get(Hex.encodeHexString(b.prevBlockHash))));
	}
	
	public boolean VerifyChain() {
		if (head == null) return true;
		return Verify(head);
	}
	
	public String toString() {
		String result = "Blockchain: \n";
		for (Block b : blocksByHash.values()) {
			result += b.toString() + "\n";
		}
		return result;
	}
}
