//SPDX-License-Identifier: CC0-1.0

pragma solidity ^0.8.0;

/// @title smartNFT: Hardblock - ERC-721 Non-Fungible Token Standard-based
interface smartNFT{
    /// @dev This emits when an user of a NFT changes
    ///  This event emits when the user of a token is assigned
    ///  (`_addressUser` == 0) when a user is unassigned
    event UserAssigned(uint256 indexed tokenID, address indexed _addressUser);
    
    /// @dev This emits when an user of a NFT verifies a device
    ///  This event emits when the user of a device finishes the assignment process
    event UserEngaged(uint256 indexed tokenID);
    
    /// @dev This emits when an owner of a NFT verifies a device
    ///  This event emits when the owner of a device finishes the transfer process
    event OwnerEngaged(uint256 indexed tokenID);
    
    //TODO: Describe new functions and events
    event TimeoutAlarm(uint256 indexed tokenID);

    /// @notice This function defines how the smart device is bound to a new token
    /// @dev Only the manufacturer of the smart device account can create a token and will be the first owner of the token
    ///  The initial state of the token is "waitingForOwner" until verified by the new owner
    /// @param _addressSD An address generated by the smart device. Only de smart device can generate this account. _addressOwner is the first owner of the Smart Device
    /// @return The tokenID of the token bound to the smart device
    function createToken(address _addressSD, address _addressOwner) external returns (uint256);

    /// @notice This function defines the transference of use of a smart device
    /// @dev Only the owner of the token account can transfer a token provided that the state of the token is "engagedWithOwner","waitingForUser" or "engagedWithUser".
    ///  The state of the token must change to "waitingForUser" and the parameter addressUser of the token defined by _tokenID must change to _addressUser
    /// @param _tokenId The tokenID of the smart device
    /// @param _addressUser The address of the new user
    function setUser(uint256 _tokenId, address _addressUser) external; 

    //TODO: Describe new functions and events

    function startOwnerEngagement(uint256 _tokenId, uint256 _dataEngage, uint256 _hashK_O) external;
    function ownerEngagement(uint256 _hashK_D) external; 
    function startUserEngagement(uint256 _tokenId, uint256 _dataEngage, uint256 _hashK_U) external;
    function userEngagement(uint256 _hashK_D) external; 
    function checkTimeout(uint256 _tokenId) external returns (bool);
    function setTimeout(uint256 _tokenId, uint256 _timeout) external; 
    function updateTimestamp() external; 
    
    /// @notice This function let us obtain the tokenID from an address of smart device 
    /// @dev Everybody can call this function. It does not execute any code on blockchain, only reads
    /// @param _addressSD The address to obtain its token ID
    /// @return The token ID of the token bound to _addressSD
    function tokenFromBCA(address _addressSD) external view returns (uint256);
    
    /// @notice This function let us know who is the owner of the token from the address of the smart device
    /// @dev Everybody can call this function. It does not execute any code on blockchain, only reads
    /// @param _addressSD The address to obtain its owner
    /// @return The owner of the token bound to _addressSD
    function ownerOfFromBCA(address _addressSD) external view returns (address);
    
    /// @notice This function let us know who is the user of the token from the tokenId
    /// @dev Everybody can call this function. It does not execute any code on blockchain, only reads
    /// @param _tokenId of the token to obtain its user
    /// @return The user of the token with _tokenId
    function userOf(uint256 _tokenId) external view returns (address);
    
    /// @notice This function let us know who is the user of the token from the address of the smart device
    /// @dev Everybody can call this function. It does not execute any code on blockchain, only reads
    /// @param _addressSD The address to obtain its user.
    /// @return The user of the token bound to _addressSD.
    function userOfFromBCA(address _addressSD) external view returns (address);
    
    /// @notice This function let us know how many tokens an user has
    /// @dev Everybody can call this function. It does not execute any code on blockchain, only reads
    /// @param _addressUser The address of the user to know the number of tokens
    /// @return The number of tokens of the user
    function userBalanceOf(address _addressUser) external view returns (uint256);
    
    /// @notice This function let us know how many tokens of an owner an user has
    /// @dev Everybody can call this function. It does not execute any code on blockchain, only reads
    /// @param _addressUser The address of the user to know the number of tokens
    /// @param _addressOwner The address of the owner of the tokens
    /// @return The number of tokens of an owner that an user can use
    function userBalanceOfAnOwner(address _addressUser, address _addressOwner) external view returns (uint256);
}
