contract CardOwnership is CardCore, ERC721 {

    /// @notice Name and symbol of the non fungible token, as defined in ERC721.

    mapping (uint256 => address) cardApprovals;
	/// internal, private

    
    function _transfer(address _from, address _to, uint256 _tokenId) internal {
        ownerCardCount[_to]++;
        // transfer ownership
        cardToOwner[_tokenId] = _to;

        ownerCardCount[_from]--;
        // clear any previously approved ownership exchange
        
        delete cardApprovals[_tokenId];
       
        // Emit the transfer event.
        Transfer(_from, _to, _tokenId);
    }

    function balanceOf(address _owner) public view returns (uint256 count) {
        return ownerCardCount[_owner];
    }

    function transfer(address _to, uint256 _tokenId) public cardOwner(_tokenId)
    {
        // no init address no contract address
        require(_to != address(0));
        require(_to != address(this));
        require(cardApprovals[_tokenId] == address(0));

        // Reassign ownership, clear pending approvals, emit Transfer event.
        _transfer(msg.sender, _to, _tokenId);
    }
      function name() constant returns (string name){
        return "Etherchicks";
      }
       function symbol() constant returns (string symbol){
        return "ETCS";
      }
      
  
    // Only an owner can grant transfer approval.
    function approve(address _to, uint256 _tokenId) public cardOwner(_tokenId) 
    {
        // Register the approval (replacing any previous approval).
        cardApprovals[_tokenId] = _to;
        Approval(msg.sender, _to, _tokenId);
    }


    /// return all erc721 ents unit
    function totalSupply() public view returns (uint) {
        return cards.length - 1;
    }

    function ownerOf(uint256 _tokenId)
        public
        view
        returns (address _owner)
    {
        return cardToOwner[_tokenId];
    }
    
      function transferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    )
        public
    {       
        require(_to != address(0));
        require(_to != address(this));
        require(cardApprovals[_tokenId] == address(this));

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

    /// expensive call count of all tokens per owner
    function tokensOfOwner(address _owner) external view returns(uint256[] ownerTokens) {
        uint256 tokenCount = balanceOf(_owner);

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

            // We count on the fact that all cats have IDs starting at 1 and increasing
            // sequentially up to the totalCat count.
            uint256 tokId;

            for (tokId = 1; tokId <= totalCards ; tokId++) {
                if (cardToOwner[tokId] == _owner) {
                    result[resultIndex] = tokId;
                    resultIndex++;
                }
            }

            return result;
        }
    }
    function appendUintToString(string inStr, uint256 v) constant internal returns (string str) {
        uint maxlength = 100;
        bytes memory reversed = new bytes(maxlength);
        uint i = 0;
        while (v != 0) {
            uint remainder = v % 10;
            v = v / 10;
            reversed[i++] = byte(48 + remainder);
        }
        bytes memory inStrb = bytes(inStr);
        bytes memory s = new bytes(inStrb.length + i + 1);
        uint j;
        for (j = 0; j < inStrb.length; j++) {
            s[j] = inStrb[j];
        }
        for (j = 0; j <= i; j++) {
            s[j + inStrb.length] = reversed[i - j];
        }
        str = string(s);
        return str;
    }
    
    function tokenMetadata(uint256 _tokenId) constant returns (string infoUrl) 
    {
        return appendUintToString(URL, _tokenId);
    }
    

}
/**************************************
 * @title CardOwnership
 * @dev erc721 compatible provides function from inherited interface
 **************************************/
function approve(address _to, uint256 _tokenId) public cardOwner(_tokenId) 
{
    // Register the approval (replacing any previous approval).
    cardApprovals[_tokenId] = _to;
    Approval(msg.sender, _to, _tokenId);
}

// Only an owner can grant transfer approval.