contract CryptovoxelsProperty is ERC721Token, Ownable {
  struct BoundingBox {
    uint x1;
    uint y1;
    uint z1;
    uint x2;
    uint y2;
    uint z2;
  }

  mapping(uint256 => BoundingBox) internal boundingBoxes;
  mapping(uint256 => string) internal contentURIs;
  mapping(uint256 => uint256) public tokenPrice;
  address public creator;

  function CryptovoxelsProperty (string name, string symbol) public
    ERC721Token(name, symbol)
  { 
    creator = msg.sender;
  }

  function mint(address _to, uint256 _tokenId, string _uri, uint x1, uint y1, uint z1, uint x2, uint y2, uint z2) public onlyOwner {
    super._mint(_to, _tokenId);
    super._setTokenURI(_tokenId, _uri);
    boundingBoxes[_tokenId] = BoundingBox(x1, y1, z1, x2, y2, z2);
  }

  function setTokenURI(uint256 _tokenId, string _uri) public onlyOwner {
    super._setTokenURI(_tokenId, _uri);
  }

  function burn(uint256 _tokenId) public onlyOwner {
    super._burn(ownerOf(_tokenId), _tokenId);

    // Delete bounding box metadata
    delete boundingBoxes[_tokenId];

    // Delete content uri metadata
    if (bytes(contentURIs[_tokenId]).length != 0) {
      delete contentURIs[_tokenId];
    }
  }

  // Set the price of the token
  function setPrice (uint256 _tokenId, uint256 _price) public onlyOwner {
    // Token must exist
    require(exists(_tokenId));

    // Must be owned by the creator
    address tokenOwner = ownerOf(_tokenId);
    require(tokenOwner == creator);

    // Set price
    tokenPrice[_tokenId] = _price;
  }

  // Get the price of the token
  function getPrice (uint256 _tokenId) public view returns (uint256) {
    require(exists(_tokenId));

    return tokenPrice[_tokenId];
  }

  // Buy the token from the owner
  function buy (uint256 _tokenId) public payable {
    // Token must exist
    require(exists(_tokenId));

    // Token must be owned by creator
    address tokenOwner = ownerOf(_tokenId);
    require(tokenOwner == creator);

    // Price must be non zero
    uint256 price = tokenPrice[_tokenId];
    require(price > 0);
    require(msg.value == price);

    // Do transfer
    address _from = tokenOwner;
    address _to = msg.sender;

    // From #transferFrom
    clearApproval(_from, _tokenId);
    removeTokenFrom(_from, _tokenId);
    addTokenTo(_to, _tokenId);
    emit Transfer(tokenOwner, _to, _tokenId);

    // Check transfer worked
    require(checkAndCallSafeTransfer(_from, _to, _tokenId, ""));

    // Set price to 0
    tokenPrice[_tokenId] = 0;
  }

  // Get the bounding box (in metres) of this property
  function getBoundingBox(uint256 _tokenId) public view returns (uint, uint, uint, uint, uint, uint) {
    require(exists(_tokenId));

    return (
      boundingBoxes[_tokenId].x1, 
      boundingBoxes[_tokenId].y1, 
      boundingBoxes[_tokenId].z1,
      boundingBoxes[_tokenId].x2, 
      boundingBoxes[_tokenId].y2, 
      boundingBoxes[_tokenId].z2
    );
  }

  // Set a URL to load this scene from. Is normally empty for loading
  // from the cryptovoxels.com servers.
  function setContentURI(uint256 _tokenId, string _uri) public {
    require(exists(_tokenId));
    require(ownerOf(_tokenId) == msg.sender);
    contentURIs[_tokenId] = _uri;
  }

  function contentURI(uint256 _tokenId) public view returns (string) {
    require(exists(_tokenId));
    return contentURIs[_tokenId];
  }
}
function getPrice (uint256 _tokenId) public view returns (uint256) {
  require(exists(_tokenId));

  return tokenPrice[_tokenId];
}

// Get the price of the token