contract AnimecardBase is AnimecardAccessControl {
    using SafeMath
    for uint256;

    /*** DATA TYPES ***/

    /// The main anime card struct
    struct Animecard {
        /// Name of the character
        string characterName;
        /// Name of designer & studio that created the character
        string studioName;

        /// AWS S3-CDN URL for character image
        string characterImageUrl;
        /// IPFS hash of character details
        string characterImageHash;
        /// The timestamp from the block when this anime card was created
        uint64 creationTime;
    }


    /*** EVENTS ***/
    /// The Birth event is fired whenever a new anime card comes into existence.
    event Birth(address owner, uint256 tokenId, string cardName, string studio);
    /// Transfer event as defined in current draft of ERC721. Fired every time animecard
    /// ownership is assigned, including births.
    event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
    /// The TokenSold event is fired whenever a token is sold.
    event TokenSold(uint256 tokenId, uint256 oldPrice, uint256 price, address prevOwner, address owner, string cardName);

    /*** STORAGE ***/
    /// An array containing all AnimeCards in existence. The id of each animecard
    /// is an index in this array.
    Animecard[] animecards;

    /// @dev A mapping from anime card ids to the address that owns them.
    mapping(uint256 => address) public animecardToOwner;

    /// @dev A mapping from owner address to count of anime cards that address owns.
    /// Used internally inside balanceOf() to resolve ownership count.
    mapping(address => uint256) public ownerAnimecardCount;

    /// @dev A mapping from anime card ids to an address that has been approved to call
    ///  transferFrom(). Each anime card can only have 1 approved address for transfer
    ///  at any time. A 0 value means no approval is outstanding.
    mapping(uint256 => address) public animecardToApproved;

    // @dev A mapping from anime card ids to their price.
    mapping(uint256 => uint256) public animecardToPrice;

    // @dev Previous sale price of anime card
    mapping(uint256 => uint256) public animecardPrevPrice;

    /// @dev Assigns ownership of a specific anime card to an address.
    function _transfer(address _from, address _to, uint256 _tokenId) internal {
        // Transfer ownership and update owner anime card counts.
        // ownerAnimecardCount[_to] = ownerAnimecardCount[_to].add(1);
        ownerAnimecardCount[_to]++;
        animecardToOwner[_tokenId] = _to;
        // When creating new tokens _from is 0x0, but we can't account that address.
        if (_from != address(0)) {
            // ownerAnimecardCount[_from] = ownerAnimecardCount[_from].sub(1);
            ownerAnimecardCount[_from]--;
            // clear any previously approved ownership exchange
            delete animecardToApproved[_tokenId];
        }
        // Fire the transfer event.
        Transfer(_from, _to, _tokenId);
    }

    /// @dev An internal method that creates a new anime card and stores it.
    /// @param _characterName The name of the character
    /// @param _studioName The studio that created this character
    /// @param _characterImageUrl AWS S3-CDN URL for character image
    /// @param _characterImageHash IPFS hash for character image
    /// @param _price of animecard character
    /// @param _owner The initial owner of this anime card
    function _createAnimecard(
        string _characterName,
        string _studioName,
        string _characterImageUrl,
        string _characterImageHash,
        uint256 _price,
        address _owner
    )
    internal
    returns(uint) {

        Animecard memory _animecard = Animecard({
            characterName: _characterName,
            studioName: _studioName,
            characterImageUrl: _characterImageUrl,
            characterImageHash: _characterImageHash,
            creationTime: uint64(now)
        });
        uint256 newAnimecardId = animecards.push(_animecard);
        newAnimecardId = newAnimecardId.sub(1);

        // Fire the birth event.
        Birth(
            _owner,
            newAnimecardId,
            _animecard.characterName,
            _animecard.studioName
        );

        // Set the price for the animecard.
        animecardToPrice[newAnimecardId] = _price;

        // This will assign ownership, and also fire the Transfer event as per ERC-721 draft.
        _transfer(0, _owner, newAnimecardId);

        return newAnimecardId;

    }
}
function _createAnimecard(
    string _characterName,
    string _studioName,
    string _characterImageUrl,
    string _characterImageHash,
    uint256 _price,
    address _owner
)
internal
returns(uint) {

    Animecard memory _animecard = Animecard({
        characterName: _characterName,
        studioName: _studioName,
        characterImageUrl: _characterImageUrl,
        characterImageHash: _characterImageHash,
        creationTime: uint64(now)
    });
    uint256 newAnimecardId = animecards.push(_animecard);
    newAnimecardId = newAnimecardId.sub(1);

    // Fire the birth event.
    Birth(
        _owner,
        newAnimecardId,
        _animecard.characterName,
        _animecard.studioName
    );

    // Set the price for the animecard.
    animecardToPrice[newAnimecardId] = _price;

    // This will assign ownership, and also fire the Transfer event as per ERC-721 draft.
    _transfer(0, _owner, newAnimecardId);

    return newAnimecardId;

}

/// @dev An internal method that creates a new anime card and stores it.
/// @param _characterName The name of the character
/// @param _studioName The studio that created this character
/// @param _characterImageUrl AWS S3-CDN URL for character image
/// @param _characterImageHash IPFS hash for character image
/// @param _price of animecard character
/// @param _owner The initial owner of this anime card