function addBooking(VisitType _type, uint _unicornCount) payable {
    if (_type == VisitType.Afternoon) {
      return donateUnicorns(availableBalance(msg.sender));
    }
    require(msg.value >= visitCost[uint8(_type)].mul(_unicornCount)); 

    ERC20Token cardboardUnicorns = ERC20Token(cardboardUnicornTokenAddress);
    cardboardUnicorns.transferFrom(msg.sender, address(this), _unicornCount); 
    visitingUnicorns = visitingUnicorns.add(_unicornCount);
    uint expiresBlock = block.number.add(visitLength[uint8(_type)]); 
    
    
    bookings[msg.sender].push(Visit(
      _unicornCount,
      _type,
      block.number,
      expiresBlock,
      VisitState.InProgress
    ));
    uint newIndex = bookings[msg.sender].length - 1;
    bytes32 uniqueKey = keccak256(msg.sender, newIndex); 
    
    
    bookingMetadataForKey[uniqueKey] = VisitMeta(
      msg.sender,
      newIndex
    );
    
    if (groveAddress > 0) {
      
      GroveAPI g = GroveAPI(groveAddress);
      g.insert("bookingExpiration", uniqueKey, int(expiresBlock));
    }
    
    
    NewBooking(msg.sender, newIndex, _type, _unicornCount);
  }