contract CollectibleBase is LSNFT {

    /*** EVENTS ***/

    /// @dev Event emitted when an attribute of the player is updated
    event AssetUpdated(uint256 tokenId);

    /*** STORAGE ***/

    /// @dev A mapping of Team Id to Team Sequence Number to Collectible
    mapping (uint256 => mapping (uint32 => uint256) ) public nftTeamIdToSequenceIdToCollectible;

    /// @dev A mapping from Team IDs to the Sequqence Number .
    mapping (uint256 => uint32) public nftTeamIndexToCollectibleCount;

    /// @dev Array to hold details on attachment for each LS NFT Collectible
    mapping(uint256 => uint256[]) public nftCollectibleAttachments;

    /// @dev Mapping to control the asset generation per season.
    mapping(uint256 => uint256) public generationSeasonController;

    /// @dev Mapping for generation Season Dict.
    mapping(uint256 => uint256) public generationSeasonDict;

    /// @dev internal function to update player override id
    function _updatePlayerOverrideId(uint256 _tokenId, uint256 _newPlayerOverrideId) internal {

        // Get Token Obj
        NFT storage lsnftObj = allNFTs[_tokenId];
        lsnftObj.playerOverrideId = _newPlayerOverrideId;

        // Update Token Data with new updated attributes
        allNFTs[_tokenId] = lsnftObj;

        emit AssetUpdated(_tokenId);
    }

    /**
     * @dev An internal method that helps in generation of new NFT Collectibles
     * @param _teamId           teamId of the asset/token/collectible
     * @param _attributes       attributes of asset/token/collectible
     * @param _owner            owner of asset/token/collectible
     * @param _isAttached       State of the asset (attached or dettached)
     * @param _nftData          Array of data required for creation
     */
    function _createNFTCollectible(
        uint8 _teamId,
        uint256 _attributes,
        address _owner,
        uint256 _isAttached,
        uint256[5] _nftData
    )
        internal
        returns (uint256)
    {
        uint256 generationSeason = (_attributes % 1000000).div(1000);
        require (generationSeasonController[generationSeason] == 1);

        uint32 _sequenceId = getSequenceId(_teamId);

        uint256 newNFTCryptoId = _createNFT(_nftData, _owner, _isAttached);
        
        nftTeamIdToSequenceIdToCollectible[_teamId][_sequenceId] = newNFTCryptoId;
        nftTeamIndexToCollectibleCount[_teamId] = _sequenceId;

        return newNFTCryptoId;
    }
    
    function getSequenceId(uint256 _teamId) internal returns (uint32) {
        return (nftTeamIndexToCollectibleCount[_teamId] + 1);
    }

    /**
     * @dev Internal function, Helps in updating the Creation Stop Time
     * @param _season    Season UINT Code
     * @param _value    0 - Not allowed, 1 - Allowed
     */
    function _updateGenerationSeasonFlag(uint256 _season, uint8 _value) internal {
        generationSeasonController[_season] = _value;
    }

    /** @param _owner The owner whose ships tokens we are interested in.
      * @dev This method MUST NEVER be called by smart contract code. First, it's fairly
      *  expensive (it walks the entire Collectibles owners array looking for NFT belonging to 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 totalItems = balanceOf(_owner);
            uint256 resultIndex = 0;

            // We count on the fact that all Collectible have IDs starting at 0 and increasing
            // sequentially up to the total count.
            uint256 _assetId;

            for (_assetId = 0; _assetId < totalItems; _assetId++) {
                result[resultIndex] = tokenOfOwnerByIndex(_owner,_assetId);
                resultIndex++;
            }

            return result;
        }
    }

    /// @dev internal function to update MLB player id
    function _updateMLBPlayerId(uint256 _tokenId, uint256 _newMLBPlayerId) internal {

        // Get Token Obj
        NFT storage lsnftObj = allNFTs[_tokenId];
        
        lsnftObj.mlbPlayerId = _newMLBPlayerId;

        // Update Token Data with new updated attributes
        allNFTs[_tokenId] = lsnftObj;

        emit AssetUpdated(_tokenId);
    }

    /// @dev internal function to update asset earnedBy value for an asset/token
    function _updateEarnedBy(uint256 _tokenId, uint256 _earnedBy) internal {

        // Get Token Obj
        NFT storage lsnftObj = allNFTs[_tokenId];
        
        lsnftObj.earnedBy = _earnedBy;

        // Update Token Data with new updated attributes
        allNFTs[_tokenId] = lsnftObj;

        emit AssetUpdated(_tokenId);
    }
}
/** Base contract for DodgersNFT Collectibles. Holds all commons, events and base variables.
 * @title Lucid Sight MLB NFT 2018
 * @author Fazri Zubair & Farhan Khwaja (Lucid Sight, Inc.)
 */
function _updateEarnedBy(uint256 _tokenId, uint256 _earnedBy) internal {

    // Get Token Obj
    NFT storage lsnftObj = allNFTs[_tokenId];
        
    lsnftObj.earnedBy = _earnedBy;

    // Update Token Data with new updated attributes
    allNFTs[_tokenId] = lsnftObj;

    emit AssetUpdated(_tokenId);
}

/// @dev internal function to update asset earnedBy value for an asset/token