contract ERC1155Minter is IERC2981, ERC1155, Ownable {
    using SafeMath for uint256;
    using SafeMath for uint16;
    address private _mediaContract;
    bytes4 private constant _INTERFACE_ID_ERC2981 = 0x2a55205a;

    struct RoyaltyInfo {
        address _royaltyRecipient;
        uint16 _royaltyPercentage;
    }

    mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo;

    mapping(uint256 => string) private _tokenURIs;

    function uri(uint256 tokenId)
        public
        view
        virtual
        override
        returns (string memory)
    {
        return _tokenURIs[tokenId];
    }

    modifier onlyMediaCaller() {
        require(
            msg.sender == _mediaContract,
            "ERC721Minter: Unauthorized Access!"
        );
        _;
    }

    constructor() ERC1155("") Ownable() { }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(IERC165, ERC1155)
        returns (bool)
    {
        return
            interfaceId == type(IERC1155).interfaceId ||
            interfaceId == type(IERC1155MetadataURI).interfaceId ||
            interfaceId == type(IERC2981).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        override
        returns (address receiver, uint256 royaltyAmount)
    {
        receiver = owner();
        royaltyAmount = salePrice
            .mul(_tokenRoyaltyInfo[tokenId]._royaltyPercentage)
            .div(10000);
    }

    /**
     * @notice This method is used to configure Media Contract address
     * @dev Should only be called by contract owner
     * @param mediaContract_ Address of the Media Contract
     */
    function configureMedia(address mediaContract_) external onlyOwner {
        require(
            _mediaContract == address(0),
            "ERC721Minter: Media Already Configured!"
        );
        require(
            mediaContract_ != address(0),
            "ERC721Minter: Invalid Media Contract Address!"
        );
        _mediaContract = mediaContract_;
    }

    function mint(
        uint256 _tokenID,
        address _owner,
        uint256 _totalSupply,
        uint16 _royaltyPoints,
        string memory _uri
    ) external onlyMediaCaller {
        _mint(_owner, _tokenID, _totalSupply, "");
        RoyaltyInfo memory _royaltyInfo = RoyaltyInfo(_owner, _royaltyPoints);
        _tokenRoyaltyInfo[_tokenID] = _royaltyInfo;
        _tokenURIs[_tokenID] = _uri;
    }

    function transferToken(
        address _tokenOwner,
        address _recipient,
        uint256 _tokenID,
        uint256 _amount
    ) external onlyMediaCaller {
        _safeTransferFrom(_tokenOwner, _recipient, _tokenID, _amount, "");
    }
}
function configureMedia(address mediaContract_) external onlyOwner {
    require(
        _mediaContract == address(0),
        "ERC721Minter: Media Already Configured!"
    );
    require(
        mediaContract_ != address(0),
        "ERC721Minter: Invalid Media Contract Address!"
    );
    _mediaContract = mediaContract_;
}

/**
 * @notice This method is used to configure Media Contract address
 * @dev Should only be called by contract owner
 * @param mediaContract_ Address of the Media Contract
 */