contract Delineation is ERC721, Ownable {
  
  bytes4 private constant _INTERFACE_ID_ROYALTIES_EIP2981 = 0x2a55205a;

  using Counters for Counters.Counter;
  Counters.Counter private _tokenIds;

  mapping(uint256 => uint256) internal _tokenRoyaltyBPS;
  mapping(uint256 => Text) public texts;
  address public royaltiesAddress = 0x9256f200735dA96435A312F42230A3b0fdEF9C0b; 

  struct Text {
    string title;
    string body;
    string author;
  }

  event TokenMinted(
    uint256 mintedTokenID,
    string title,
    string body,
    string author
  );

  constructor() ERC721("Delineation", "WNG") {
      _registerInterface(_INTERFACE_ID_ROYALTIES_EIP2981);
  }

  function mint(
    address to,
    string memory tokenURI,
    string memory title,
    string memory body,
    string memory author
  ) external payable onlyOwner {
    uint256 newItemId = _tokenIds.current();
    // save text on chain
    texts[newItemId].body = body;
    texts[newItemId].title = title;
    texts[newItemId].author = author;
    _safeMint(to, newItemId);
    _setTokenURI(newItemId, tokenURI);
    // set royalties to 10% by default
    _tokenRoyaltyBPS[newItemId] = 1000;
    emit TokenMinted(newItemId, title, body, author);
    _tokenIds.increment();
  }

  function setTokenURI(uint256 tokenId, string memory URI) public onlyOwner {
      _setTokenURI(tokenId, URI);
  }

  function getBody(uint256 _tokenID) public view returns (string memory) {
    require(_tokenID <= _tokenIds.current());
    return (texts[_tokenID].body);
  }

  function getTitle(uint256 _tokenID) public view returns (string memory) {
    require(_tokenID <= _tokenIds.current());
    return (texts[_tokenID].title);
  }

  function getAuthor(uint256 _tokenID) public view returns (string memory) {
    require(_tokenID <= _tokenIds.current());
    return (texts[_tokenID].author);
  }
  
  function withdraw() public payable onlyOwner {
    uint256 balance = address(this).balance;
    msg.sender.transfer(balance);
  }

  // EIP2981 functions
  function royaltyInfo(uint256 _tokenId, uint256 _salePrice) external view virtual returns (address receiver, uint256 royaltyAmount) {
    return (royaltiesAddress, _tokenRoyaltyBPS[_tokenId]*_salePrice/10000);
  }

  function setRoyalties(uint256 _tokenID, uint256 basisPoints) public onlyOwner {
    require(_tokenID <= _tokenIds.current());
    require(basisPoints < 10000, "Invalid royalties");
    _tokenRoyaltyBPS[_tokenID] = basisPoints;
  }

  function setRoyaltiesAddress(address _royaltiesAddress) public onlyOwner {
    royaltiesAddress = _royaltiesAddress;
  }

  receive() external payable {}
}
function royaltyInfo(uint256 _tokenId, uint256 _salePrice) external view virtual returns (address receiver, uint256 royaltyAmount) {
  return (royaltiesAddress, _tokenRoyaltyBPS[_tokenId]*_salePrice/10000);
}

// EIP2981 functions