contract WarriorTokenImpl is CryptoWarriorBase, ERC721 {

    /// @notice Name and symbol of the non fungible token, as defined in ERC721.
    string public constant name = "CryptoWarriors";
    string public constant symbol = "CW";

    bytes4 constant InterfaceSignature_ERC165 =
        bytes4(keccak256('supportsInterface(bytes4)'));

    bytes4 constant InterfaceSignature_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)'));

    /// @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)
    {
        // DEBUG ONLY
        //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9f40b779));

        return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721));
    }

    // Internal utility functions: These functions all assume that their input arguments
    // are valid. We leave it to public methods to sanitize their inputs and follow
    // the required logic.

    /** @dev Checks if a given address is the current owner of the specified Warrior tokenId.
     * @param _claimant the address we are validating against.
     * @param _tokenId warrior id
     */
    function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) {
        return _claimant != address(0) && warriorToOwner[_tokenId] == _claimant;    
    }

    function _ownerApproved(address _claimant, uint256 _tokenId) internal view returns (bool) {
        return _claimant != address(0) &&//0 address means token is burned 
        warriorToOwner[_tokenId] == _claimant && warriorToApproved[_tokenId] == address(0);    
    }

    /// @dev Checks if a given address currently has transferApproval for a particular Warrior.
    /// @param _claimant the address we are confirming warrior is approved for.
    /// @param _tokenId warrior id
    function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) {
        return warriorToApproved[_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 Warriors on auction, and
    ///  there is no value in spamming the log with Approval events in that case.
    function _approve(uint256 _tokenId, address _approved) internal {
        warriorToApproved[_tokenId] = _approved;
    }

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

    /// @notice Transfers a Warrior to another address. If transferring to a smart
    ///  contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or
    ///  CryptoWarriors specifically) or your Warrior may be lost forever. Seriously.
    /// @param _to The address of the recipient, can be a user or contract.
    /// @param _tokenId The ID of the Warrior to transfer.
    /// @dev Required for 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 warriors (except very briefly
        // after a miner warrior is created and before it goes on auction).
        require(_to != address(this));
        // Disallow transfers to the auction contracts to prevent accidental
        // misuse. Auction contracts should only take ownership of warriors
        // through the allow + transferFrom flow.
        require(_to != address(saleAuction));
        // You can only send your own warrior.
        require(_owns(msg.sender, _tokenId));
        // Only idle warriors are allowed 
        require(warriors[_tokenId].action == IDLE);

        // Reassign ownership, clear pending approvals, emit Transfer event.
        _transfer(msg.sender, _to, _tokenId);
    }
    
    function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256) {
        require(_index < balanceOf(_owner));
        return ownedTokens[_owner][_index];
    }

    /// @notice Grant another address the right to transfer a specific Warrior 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 Warrior that can be transferred if this call succeeds.
    /// @dev Required for ERC-721 compliance.
    function approve(address _to, uint256 _tokenId) external whenNotPaused {
        // Only an owner can grant transfer approval.
        require(_owns(msg.sender, _tokenId));
        // Only idle warriors are allowed 
        require(warriors[_tokenId].action == IDLE);

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

        // Emit approval event.
        Approval(msg.sender, _to, _tokenId);
    }

    /// @notice Transfer a Warrior 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 Warrior to be transfered.
    /// @param _to The address that should take ownership of the Warrior. Can be any address,
    ///  including the caller.
    /// @param _tokenId The ID of the Warrior to be transferred.
    /// @dev Required for 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 warriors (except very briefly
        // after a miner warrior is created and before it goes on auction).
        require(_to != address(this));
        // Check for approval and valid ownership
        require(_approvedFor(msg.sender, _tokenId));
        require(_owns(_from, _tokenId));
        // Only idle warriors are allowed 
        require(warriors[_tokenId].action == IDLE);

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

    /// @notice Returns the total number of Warriors currently in existence.
    /// @dev Required for ERC-721 compliance.
    function totalSupply() public view returns (uint256) {
        return warriors.length;
    }

    /// @notice Returns the address currently assigned ownership of a given Warrior.
    /// @dev Required for ERC-721 compliance.
    function ownerOf(uint256 _tokenId)
        external
        view
        returns (address owner)
    {
        require(_tokenId < warriors.length);
        owner = warriorToOwner[_tokenId];
    }

    /// @notice Returns a list of all Warrior IDs assigned to an address.
    /// @param _owner The owner whose Warriors we are interested in.
    function tokensOfOwner(address _owner) external view returns(uint256[] ownerTokens) {
        return ownedTokens[_owner];
    }
    
    function tokensOfOwnerFromIndex(address _owner, uint256 _fromIndex, uint256 _count) external view returns(uint256[] memory ownerTokens) {
        require(_fromIndex < balanceOf(_owner));
        uint256[] storage tokens = ownedTokens[_owner];
        //        
        uint256 ownerBalance = ownersTokenCount[_owner];
        uint256 lenght = (ownerBalance - _fromIndex >= _count ? _count : ownerBalance - _fromIndex);
        //
        ownerTokens = new uint256[](lenght);
        for(uint256 i = 0; i < lenght; i ++) {
            ownerTokens[i] = tokens[_fromIndex + i];
        }
        
        return ownerTokens;
    }
    
    /**
     * @dev Internal function to burn a specific token
     * @dev Reverts if the token does not exist
     * @param _owner owner of the token to burn
     * @param _tokenId uint256 ID of the token being burned by the msg.sender
     */
    function _burn(address _owner, uint256 _tokenId) internal {
        _clearApproval(_tokenId);
        _removeTokenFrom(_owner, _tokenId);
        
        Transfer(_owner, address(0), _tokenId);
    }

}
function _approve(uint256 _tokenId, address _approved) internal {
    warriorToApproved[_tokenId] = _approved;
}

/// @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 Warriors on auction, and
///  there is no value in spamming the log with Approval events in that case.