contract CSportsBase is CSportsAuth, CSportsRosterPlayer {

    /// @dev This emits when ownership of any NFT changes by any mechanism.
    ///  This event emits when NFTs are created (`from` == 0) and destroyed
    ///  (`to` == 0). Exception: during contract creation, any number of NFTs
    ///  may be created and assigned without emitting Transfer. At the time of
    ///  any transfer, the approved address for that NFT (if any) is reset to none.
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /// @dev This emits when the approved address for an NFT is changed or
    ///  reaffirmed. The zero address indicates there is no approved address.
    ///  When a Transfer event emits, this also indicates that the approved
    ///  address for that NFT (if any) is reset to none.
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /// @dev This emits when an operator is enabled or disabled for an owner.
    ///  The operator can manage all NFTs of the owner.
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /// @dev This emits when a commissioner auction is successfully closed
    event CommissionerAuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner);

    /// @dev This emits when a commissioner auction is canceled
    event CommissionerAuctionCanceled(uint256 tokenId);

    /******************/
    /*** DATA TYPES ***/
    /******************/

    /// @dev The main player token structure. Every released player in the League
    ///  is represented by a single instance of this structure.
    struct PlayerToken {

      // @dev ID of the real world player this token represents. We can only have
      // a max of 4,294,967,295 real world players, which seems to be enough for
      // a while (haha)
      uint32 realWorldPlayerId;

      // @dev Serial number indicating the number of PlayerToken(s) for this
      //  same realWorldPlayerId existed at the time this token was minted.
      uint32 serialNumber;

      // The timestamp from the block when this player token was minted.
      uint64 mintedTime;

      // The most recent sale price of the player token in an auction
      uint128 mostRecentPrice;

    }

    /**************************/
    /*** MAPPINGS (STORAGE) ***/
    /**************************/

    /// @dev A mapping from a PlayerToken ID to the address that owns it. All
    /// PlayerTokens have an owner (newly minted PlayerTokens are owned by
    /// the core contract).
    mapping (uint256 => address) public playerTokenToOwner;

    /// @dev Maps a PlayerToken ID to an address approved to take ownership.
    mapping (uint256 => address) public playerTokenToApproved;

    // @dev A mapping to a given address' tokens
    mapping(address => uint32[]) public ownedTokens;

    // @dev A mapping that relates a token id to an index into the
    // ownedTokens[currentOwner] array.
    mapping(uint32 => uint32) tokenToOwnedTokensIndex;

    /// @dev Maps operators
    mapping(address => mapping(address => bool)) operators;

    // This mapping and corresponding uint16 represent marketing tokens
    // that can be created by the commissioner (up to remainingMarketingTokens)
    // and then given to third parties in the form of 4 words that sha256
    // hash into the key for the mapping.
    //
    // Maps uint256(keccak256) => leagueRosterPlayerMD5
    uint16 public remainingMarketingTokens = MAX_MARKETING_TOKENS;
    mapping (uint256 => uint128) marketingTokens;

    /***************/
    /*** STORAGE ***/
    /***************/

    /// @dev Instance of our CSportsLeagueRoster contract. Can be set by
    ///   the CEO only once because this immutable tie to the league roster
    ///   is what relates a playerToken to a real world player. If we could
    ///   update the leagueRosterContract, we could in effect de-value the
    ///   ownership of a playerToken by switching the real world player it
    ///   represents.
    CSportsRosterInterface public leagueRosterContract;

    /// @dev Addresses of team contract that is authorized to hold player
    ///   tokens for contests.
    CSportsTeam public teamContract;

    /// @dev An array containing all PlayerTokens in existence.
    PlayerToken[] public playerTokens;

    /************************************/
    /*** RESTRICTED C-LEVEL FUNCTIONS ***/
    /************************************/

    /// @dev Sets the reference to the CSportsLeagueRoster contract.
    /// @param _address - Address of CSportsLeagueRoster contract.
    function setLeagueRosterContractAddress(address _address) public onlyCEO {
      // This method may only be called once to guarantee the immutable
      // nature of owning a real world player.
      if (!isDevelopment) {
        require(leagueRosterContract == address(0));
      }

      CSportsRosterInterface candidateContract = CSportsRosterInterface(_address);
      // NOTE: verify that a contract is what we expect (not foolproof, just
      // a sanity check)
      require(candidateContract.isLeagueRosterContract());
      // Set the new contract address
      leagueRosterContract = candidateContract;
    }

    /// @dev Adds an authorized team contract that can hold player tokens
    ///   on behalf of a contest, and will return them to the original
    ///   owner when the contest is complete (or if entry is canceled by
    ///   the original owner, or if the contest is canceled).
    function setTeamContractAddress(address _address) public onlyCEO {
      CSportsTeam candidateContract = CSportsTeam(_address);
      // NOTE: verify that a contract is what we expect (not foolproof, just
      // a sanity check)
      require(candidateContract.isTeamContract());
      // Set the new contract address
      teamContract = candidateContract;
    }

    /**************************/
    /*** INTERNAL FUNCTIONS ***/
    /**************************/

    /// @dev Identifies whether or not the addressToTest is a contract or not
    /// @param addressToTest The address we are interested in
    function _isContract(address addressToTest) internal view returns (bool) {
        uint size;
        assembly {
            size := extcodesize(addressToTest)
        }
        return (size > 0);
    }

    /// @dev Returns TRUE if the token exists
    /// @param _tokenId ID to check
    function _tokenExists(uint256 _tokenId) internal view returns (bool) {
        return (_tokenId < playerTokens.length);
    }

    /// @dev An internal method that mints a new playerToken and stores it
    ///   in the playerTokens array.
    /// @param _realWorldPlayerId ID of the real world player to mint
    /// @param _serialNumber - Indicates the number of playerTokens for _realWorldPlayerId
    ///   that exist prior to this to-be-minted playerToken.
    /// @param _owner - The owner of this newly minted playerToken
    function _mintPlayer(uint32 _realWorldPlayerId, uint32 _serialNumber, address _owner) internal returns (uint32) {
        // We are careful here to make sure the calling contract keeps within
        // our structure's size constraints. Highly unlikely we would ever
        // get to a point where these constraints would be a problem.
        require(_realWorldPlayerId < 4294967295);
        require(_serialNumber < 4294967295);

        PlayerToken memory _player = PlayerToken({
          realWorldPlayerId: _realWorldPlayerId,
          serialNumber: _serialNumber,
          mintedTime: uint64(now),
          mostRecentPrice: 0
        });

        uint256 newPlayerTokenId = playerTokens.push(_player) - 1;

        // It's probably never going to happen, 4 billion playerToken(s) is A LOT, but
        // let's just be 100% sure we never let this happen.
        require(newPlayerTokenId < 4294967295);

        // This will assign ownership, and also emit the Transfer event as
        // per ERC721 draft
        _transfer(0, _owner, newPlayerTokenId);

        return uint32(newPlayerTokenId);
    }

    /// @dev Removes a token (specified by ID) from ownedTokens and
    /// tokenToOwnedTokensIndex mappings for a given address.
    /// @param _from Address to remove from
    /// @param _tokenId ID of token to remove
    function _removeTokenFrom(address _from, uint256 _tokenId) internal {

      // Grab the index into the _from owner's ownedTokens array
      uint32 fromIndex = tokenToOwnedTokensIndex[uint32(_tokenId)];

      // Remove the _tokenId from ownedTokens[_from] array
      uint lastIndex = ownedTokens[_from].length - 1;
      uint32 lastToken = ownedTokens[_from][lastIndex];

      // Swap the last token into the fromIndex position (which is _tokenId's
      // location in the ownedTokens array) and shorten the array
      ownedTokens[_from][fromIndex] = lastToken;
      ownedTokens[_from].length--;

      // Since we moved lastToken, we need to update its
      // entry in the tokenToOwnedTokensIndex
      tokenToOwnedTokensIndex[lastToken] = fromIndex;

      // _tokenId is no longer mapped
      tokenToOwnedTokensIndex[uint32(_tokenId)] = 0;

    }

    /// @dev Adds a token (specified by ID) to ownedTokens and
    /// tokenToOwnedTokensIndex mappings for a given address.
    /// @param _to Address to add to
    /// @param _tokenId ID of token to remove
    function _addTokenTo(address _to, uint256 _tokenId) internal {
      uint32 toIndex = uint32(ownedTokens[_to].push(uint32(_tokenId))) - 1;
      tokenToOwnedTokensIndex[uint32(_tokenId)] = toIndex;
    }

    /// @dev Assigns ownership of a specific PlayerToken to an address.
    /// @param _from - Address of who this transfer is from
    /// @param _to - Address of who to tranfer to
    /// @param _tokenId - The ID of the playerToken to transfer
    function _transfer(address _from, address _to, uint256 _tokenId) internal {

        // transfer ownership
        playerTokenToOwner[_tokenId] = _to;

        // When minting brand new PlayerTokens, the _from is 0x0, but we don't deal with
        // owned tokens for the 0x0 address.
        if (_from != address(0)) {

            // Remove the _tokenId from ownedTokens[_from] array (remove first because
            // this method will zero out the tokenToOwnedTokensIndex[_tokenId], which would
            // stomp on the _addTokenTo setting of this value)
            _removeTokenFrom(_from, _tokenId);

            // Clear our approved mapping for this token
            delete playerTokenToApproved[_tokenId];
        }

        // Now add the token to the _to address' ownership structures
        _addTokenTo(_to, _tokenId);

        // Emit the transfer event.
        emit Transfer(_from, _to, _tokenId);
    }

    /// @dev Converts a uint to its string equivalent
    /// @param v uint to convert
    function uintToString(uint v) internal pure returns (string str) {
      bytes32 b32 = uintToBytes32(v);
      str = bytes32ToString(b32);
    }

    /// @dev Converts a uint to a bytes32
    /// @param v uint to convert
    function uintToBytes32(uint v) internal pure returns (bytes32 ret) {
        if (v == 0) {
            ret = '0';
        }
        else {
            while (v > 0) {
                ret = bytes32(uint(ret) / (2 ** 8));
                ret |= bytes32(((v % 10) + 48) * 2 ** (8 * 31));
                v /= 10;
            }
        }
        return ret;
    }

    /// @dev Converts bytes32 to a string
    /// @param data bytes32 to convert
    function bytes32ToString (bytes32 data) internal pure returns (string) {

        uint count = 0;
        bytes memory bytesString = new bytes(32); //  = new bytes[]; //(32);
        for (uint j=0; j<32; j++) {
            byte char = byte(bytes32(uint(data) * 2 ** (8 * j)));
            if (char != 0) {
                bytesString[j] = char;
                count++;
            } else {
              break;
            }
        }

        bytes memory s = new bytes(count);
        for (j = 0; j < count; j++) {
            s[j] = bytesString[j];
        }
        return string(s);

    }

}
/// @title Base contract for CryptoSports. Holds all common structs, events and base variables.
/// @author CryptoSports, Inc. (http://cryptosports.team)
/// @dev See the CSportsCore contract documentation to understand how the various contract facets are arranged.
function _isContract(address addressToTest) internal view returns (bool) {
        uint size;
        assembly {
            size := extcodesize(addressToTest)
        }
        return (size > 0);
    }
/// @dev Identifies whether or not the addressToTest is a contract or not
/// @param addressToTest The address we are interested in