contract AnimecardOwnership is AnimecardPricing, ERC721 {
    /// Name of the collection of NFTs managed by this contract, as defined in ERC721.
    string public constant NAME = "CryptoAnime";
    /// Symbol referencing the entire collection of NFTs managed in this contract, as
    /// defined in ERC721.
    string public constant SYMBOL = "ANM";

    bytes4 public constant INTERFACE_SIGNATURE_ERC165 =
        bytes4(keccak256("supportsInterface(bytes4)"));

    bytes4 public constant INTERFACE_SIGNATURE_ERC721 =
        bytes4(keccak256("name()")) ^
        bytes4(keccak256("symbol()")) ^
        bytes4(keccak256("totalSupply()")) ^
        bytes4(keccak256("balanceOf(address)")) ^
        bytes4(keccak256("ownerOf(uint256)")) ^
        bytes4(keccak256("approve(address,uint256)")) ^
        bytes4(keccak256("transfer(address,uint256)")) ^
        bytes4(keccak256("transferFrom(address,address,uint256)")) ^
        bytes4(keccak256("tokensOfOwner(address)")) ^
        bytes4(keccak256("tokenMetadata(uint256,string)"));

    /*** EVENTS ***/
    /// Approval event as defined in the current draft of ERC721. Fired every time
    /// animecard approved owners is updated. When Transfer event is emitted, this 
    /// also indicates that approved address is reset to none.
    event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);

    /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165).
    ///  Returns true for any standardized interfaces implemented by this contract. We implement
    ///  ERC-165 (obviously!) and ERC-721.
    function supportsInterface(bytes4 _interfaceID)
    external
    view
    returns(bool) {
        return ((_interfaceID == INTERFACE_SIGNATURE_ERC165) || (_interfaceID == INTERFACE_SIGNATURE_ERC721));
    }

    // @notice Optional for ERC-20 compliance.
    function name() external pure returns(string) {
        return NAME;
    }

    // @notice Optional for ERC-20 compliance.
    function symbol() external pure returns(string) {
        return SYMBOL;
    }

    /// @dev Returns the total number of Animecards currently in existence.
    /// @notice Required for ERC-20 and ERC-721 compliance.
    function totalSupply() public view returns(uint) {
        return animecards.length;
    }

    /// @dev Returns the number of Animecards owned by a specific address.
    /// @param _owner The owner address to check.
    /// @notice Required for ERC-20 and ERC-721 compliance.
    function balanceOf(address _owner)
    public
    view
    returns(uint256 count) {
        return ownerAnimecardCount[_owner];
    }

    /// @dev Returns the address currently assigned ownership of a given Animecard.
    /// @notice Required for ERC-721 compliance.
    function ownerOf(uint256 _tokenId)
    external
    view
    returns(address _owner) {
        _owner = animecardToOwner[_tokenId];
        require(_owner != address(0));
    }

    /// @dev Grant another address the right to transfer a specific Anime card via
    ///  transferFrom(). This is the preferred flow for transfering NFTs to contracts.
    /// @param _to The address to be granted transfer approval. Pass address(0) to
    ///  clear all approvals.
    /// @param _tokenId The ID of the Animecard that can be transferred if this call succeeds.
    /// @notice Required for ERC-20 and ERC-721 compliance.
    function approve(address _to, uint256 _tokenId)
    external
    whenNotPaused {
        // Only an owner can grant transfer approval.
        require(_owns(msg.sender, _tokenId));

        // Register the approval (replacing any previous approval).
        _approve(_tokenId, _to);

        // Fire approval event upon successful approval.
        Approval(msg.sender, _to, _tokenId);
    }

    /// @dev Transfers a Animecard to another address. If transferring to a smart
    ///  contract be VERY CAREFUL to ensure that it is aware of ERC-721 or else your
    /// Animecard may be lost forever.
    /// @param _to The address of the recipient, can be a user or contract.
    /// @param _tokenId The ID of the Animecard to transfer.
    /// @notice Required for ERC-20 and ERC-721 compliance.
    function transfer(address _to, uint256 _tokenId)
    external
    whenNotPaused {
        // Safety check to prevent against an unexpected 0x0 default.
        require(_to != address(0));
        // Disallow transfers to this contract to prevent accidental misuse.
        // The contract should never own any animecard (except very briefly
        // after a Anime card is created).
        require(_to != address(this));

        // You can only transfer your own Animecard.
        require(_owns(msg.sender, _tokenId));
        // TODO - Disallow transfer to self

        // Reassign ownership, clear pending approvals, fire Transfer event.
        _transfer(msg.sender, _to, _tokenId);
    }

    /// @dev Transfer a Animecard owned by another address, for which the calling address
    ///  has previously been granted transfer approval by the owner.
    /// @param _from The address that owns the Animecard to be transfered.
    /// @param _to The address that should take ownership of the Animecard. Can be any
    /// address, including the caller.
    /// @param _tokenId The ID of the Animecard to be transferred.
    /// @notice Required for ERC-20 and ERC-721 compliance.
    function transferFrom(address _from, address _to, uint256 _tokenId)
    external
    whenNotPaused {
        // Safety check to prevent against an unexpected 0x0 default.
        require(_to != address(0));
        // Disallow transfers to this contract to prevent accidental misuse.
        // The contract should never own any animecard (except very briefly
        // after an animecard is created).
        require(_to != address(this));

        // Check for approval and valid ownership
        require(_approvedFor(msg.sender, _tokenId));
        require(_owns(_from, _tokenId));

        // Reassign ownership (also clears pending approvals and fires Transfer event).
        _transfer(_from, _to, _tokenId);
    }

    /// @dev Returns a list of all Animecard IDs assigned to an address.
    /// @param _owner The owner whose Animecards we are interested in.
    ///  This method MUST NEVER be called by smart contract code. First, it is fairly
    ///  expensive (it walks the entire Animecard array looking for Animecard belonging
    /// to owner), but it also returns a dynamic array, which is only supported for web3
    /// calls, and not contract-to-contract calls. Thus, this method is external rather
    /// than public.
    function tokensOfOwner(address _owner)
    external
    view
    returns(uint256[] ownerTokens) {
        uint256 tokenCount = balanceOf(_owner);

        if (tokenCount == 0) {
            // Returns an empty array
            return new uint256[](0);
        } else {
            uint256[] memory result = new uint256[](tokenCount);
            uint256 totalAnimecards = totalSupply();
            uint256 resultIndex = 0;

            uint256 animecardId;
            for (animecardId = 0; animecardId <= totalAnimecards; animecardId++) {
                if (animecardToOwner[animecardId] == _owner) {
                    result[resultIndex] = animecardId;
                    resultIndex++;
                }
            }

            return result;
        }
    }

    /// @dev Checks if a given address is the current owner of a particular Animecard.
    /// @param _claimant the address we are validating against.
    /// @param _tokenId Animecard id, only valid when > 0
    function _owns(address _claimant, uint256 _tokenId)
    internal
    view
    returns(bool) {
        return animecardToOwner[_tokenId] == _claimant;
    }

    /// @dev Marks an address as being approved for transferFrom(), overwriting any previous
    /// approval. Setting _approved to address(0) clears all transfer approval.
    /// NOTE: _approve() does NOT send the Approval event. This is intentional because
    /// _approve() and transferFrom() are used together for putting Animecards on sale and,
    /// there is no value in spamming the log with Approval events in that case.
    function _approve(uint256 _tokenId, address _approved) internal {
        animecardToApproved[_tokenId] = _approved;
    }

    /// @dev Checks if a given address currently has transferApproval for a particular 
    /// Animecard.
    /// @param _claimant the address we are confirming Animecard is approved for.
    /// @param _tokenId Animecard id, only valid when > 0
    function _approvedFor(address _claimant, uint256 _tokenId)
    internal
    view
    returns(bool) {
        return animecardToApproved[_tokenId] == _claimant;
    }

    /// Safety check on _to address to prevent against an unexpected 0x0 default.
    function _addressNotNull(address _to) internal pure returns(bool) {
        return _to != address(0);
    }

}
function _owns(address _claimant, uint256 _tokenId)
internal
view
returns(bool) {
    return animecardToOwner[_tokenId] == _claimant;
}

/// @dev Checks if a given address is the current owner of a particular Animecard.
/// @param _claimant the address we are validating against.
/// @param _tokenId Animecard id, only valid when > 0