contract ToyInterface is ToyCreation {
    // URL Containing TOY Token metadata
    string metadataUrl = "http://52.9.230.48:8090/toy_token/";

    //-------------------------------------------------------------------------
    /// @notice Change old metadata URL to `_newUrl`
    /// @dev Throws if new URL is empty
    /// @param _newUrl The new URL containing TOY Token metadata
    //-------------------------------------------------------------------------
    function updateMetadataUrl(string _newUrl)
        external 
        onlyOwner 
        notZero(bytes(_newUrl).length)
    {
        metadataUrl = _newUrl;
    }

    //-------------------------------------------------------------------------
    /// @notice Gets all public info for TOY Token #`_uid`.
    /// @dev Throws if TOY Token #`_uid` does not exist.
    /// @param _uid the UID of the TOY Token to view.
    /// @return TOY Token owner, TOY Token UID, Creation Timestamp, Experience,
    ///  and Public Data.
    //-------------------------------------------------------------------------
    function changeToyData(uint _uid, bytes _data) 
        external 
        mustExist(_uid)
        canOperate(_uid)
        returns (address, uint, uint, uint, bytes) 
    {
        require(_uid < UID_MAX, "TOY Token must be linked");
        toyArray[uidToToyIndex[_uid]].toyData = _data;
    }

    //-------------------------------------------------------------------------
    /// @notice Gets all public info for TOY Token #`_uid`.
    /// @dev Throws if TOY Token #`_uid` does not exist.
    /// @param _uid the UID of the TOY Token to view.
    /// @return TOY Token owner, TOY Token UID, Creation Timestamp, Experience,
    ///  and Public Data.
    //-------------------------------------------------------------------------
    function getToy(uint _uid) 
        external
        view 
        mustExist(_uid) 
        returns (address, uint, uint, uint, bytes) 
    {
        ToyToken memory toy = toyArray[uidToToyIndex[_uid]];
        return(toy.owner, toy.uid, toy.timestamp, toy.exp, toy.toyData);
    }

    //-------------------------------------------------------------------------
    /// @notice Gets all info for TOY Token #`_uid`'s linked NFT.
    /// @dev Throws if TOY Token #`_uid` does not exist.
    /// @param _uid the UID of the TOY Token to view.
    /// @return NFT contract address, External NFT ID.
    //-------------------------------------------------------------------------
    function getLinkedNft(uint _uid) 
        external
        view 
        mustExist(_uid) 
        returns (address, uint) 
    {
        ExternalNft memory nft = uidToExternalNft[_uid];
        return (nft.nftContractAddress, nft.nftId);
    }

    //-------------------------------------------------------------------------
    /// @notice Gets whether NFT #`_externalId` is linked to a TOY Token.
    /// @param _externalAddress the contract address for the external NFT
    /// @param _externalId the UID of the external NFT to view.
    /// @return NFT contract address, External NFT ID.
    //-------------------------------------------------------------------------
    function externalNftIsLinked(address _externalAddress, uint _externalId)
        external
        view
        returns(bool)
    {
        return linkedExternalNfts[_externalAddress][_externalId];
    }

    //-------------------------------------------------------------------------
    /// @notice A descriptive name for a collection of NFTs in this contract
    //-------------------------------------------------------------------------
    function name() external pure returns (string) {
        return "TOY Tokens";
    }

    //-------------------------------------------------------------------------
    /// @notice An abbreviated name for NFTs in this contract
    //-------------------------------------------------------------------------
    function symbol() external pure returns (string) { return "TOY"; }

    //-------------------------------------------------------------------------
    /// @notice A distinct URL for a given asset.
    /// @dev Throws if `_tokenId` is not a valid NFT.
    ///  If:
    ///  * The URI is a URL
    ///  * The URL is accessible
    ///  * The URL points to a valid JSON file format (ECMA-404 2nd ed.)
    ///  * The JSON base element is an object
    ///  then these names of the base element SHALL have special meaning:
    ///  * "name": A string identifying the item to which `_tokenId` grants
    ///    ownership
    ///  * "description": A string detailing the item to which `_tokenId`
    ///    grants ownership
    ///  * "image": A URI pointing to a file of image/* mime type representing
    ///    the item to which `_tokenId` grants ownership
    ///  Wallets and exchanges MAY display this to the end user.
    ///  Consider making any images at a width between 320 and 1080 pixels and
    ///  aspect ratio between 1.91:1 and 4:5 inclusive.
    /// @param _tokenId The TOY Token whose metadata address is being queried
    //-------------------------------------------------------------------------
    function tokenURI(uint _tokenId) 
        external 
        view 
        returns (string) 
    {
        // convert TOY Token UID to a 14 character long string of character bytes
        bytes memory uidString = intToBytes(_tokenId);
        // declare new string of bytes with combined length of url and uid 
        bytes memory fullUrlBytes = new bytes(bytes(metadataUrl).length + uidString.length);
        // copy URL string and uid string into new string
        uint counter = 0;
        for (uint i = 0; i < bytes(metadataUrl).length; i++) {
            fullUrlBytes[counter++] = bytes(metadataUrl)[i];
        }
        for (i = 0; i < uidString.length; i++) {
            fullUrlBytes[counter++] = uidString[i];
        }
        // return full URL
        return string(fullUrlBytes);
    }
    
    //-------------------------------------------------------------------------
    /// @notice Convert int to 14 character bytes
    //-------------------------------------------------------------------------
    function intToBytes(uint _tokenId) 
        private 
        pure 
        returns (bytes) 
    {
        // convert int to bytes32
        bytes32 x = bytes32(_tokenId);
        
        // convert each byte into two, and assign each byte a hex digit
        bytes memory uidBytes64 = new bytes(64);
        for (uint i = 0; i < 32; i++) {
            byte b = byte(x[i]);
            byte hi = byte(uint8(b) / 16);
            byte lo = byte(uint8(b) - 16 * uint8(hi));
            uidBytes64[i*2] = char(hi);
            uidBytes64[i*2+1] = char(lo);
        }
        
        // reduce size to last 14 chars (7 bytes)
        bytes memory uidBytes = new bytes(14);
        for (i = 0; i < 14; ++i) {
            uidBytes[i] = uidBytes64[i + 50];
        }
        return uidBytes;
    }
    
    //-------------------------------------------------------------------------
    /// @notice Convert byte to UTF-8-encoded hex character
    //-------------------------------------------------------------------------
    function char(byte b) private pure returns (byte c) {
        if (b < 10) return byte(uint8(b) + 0x30);
        else return byte(uint8(b) + 0x57);
    }
}
//-----------------------------------------------------------------------------
function updateMetadataUrl(string _newUrl)
    external 
    onlyOwner 
    notZero(bytes(_newUrl).length)
{
    metadataUrl = _newUrl;
}

//-------------------------------------------------------------------------