contract AnimecardAccessControl {
    /// @dev Event is fired when contract is forked.
    event ContractFork(address newContract);

    /// - CEO: The CEO can reassign other roles, change the addresses of dependent smart contracts,
    /// and pause/unpause the AnimecardCore contract.
    /// - CFO: The CFO can withdraw funds from its auction and sale contracts.
    /// - Manager: The Animator can create regular and promo AnimeCards.
    address public ceoAddress;
    address public cfoAddress;
    address public animatorAddress;

    /// @dev Keeps track whether the contract is paused. When that is true, most actions are blocked.
    bool public paused = false;

    /// @dev Access-modifier for CEO-only functionality.
    modifier onlyCEO() {
        require(msg.sender == ceoAddress);
        _;
    }

    /// @dev Access-modifier for CFO-only functionality.
    modifier onlyCFO() {
        require(msg.sender == cfoAddress);
        _;
    }

    /// @dev Access-modifier for Animator-only functionality.
    modifier onlyAnimator() {
        require(msg.sender == animatorAddress);
        _;
    }

    /// @dev Access-modifier for C-level-only functionality.
    modifier onlyCLevel() {
        require(
            msg.sender == animatorAddress ||
            msg.sender == ceoAddress ||
            msg.sender == cfoAddress
        );
        _;
    }

    /// Assigns a new address to the CEO role. Only available to the current CEO.
    /// @param _newCEO The address of the new CEO
    function setCEO(address _newCEO) external onlyCEO {
        require(_newCEO != address(0));

        ceoAddress = _newCEO;
    }

    /// Assigns a new address to act as the CFO. Only available to the current CEO.
    /// @param _newCFO The address of the new CFO
    function setCFO(address _newCFO) external onlyCEO {
        require(_newCFO != address(0));

        cfoAddress = _newCFO;
    }

    /// Assigns a new address to the Animator role. Only available to the current CEO.
    /// @param _newAnimator The address of the new Animator
    function setAnimator(address _newAnimator) external onlyCEO {
        require(_newAnimator != address(0));

        animatorAddress = _newAnimator;
    }

    /*** Pausable functionality adapted from OpenZeppelin ***/

    /// @dev Modifier to allow actions only when the contract IS NOT paused
    modifier whenNotPaused() {
        require(!paused);
        _;
    }

    /// @dev Modifier to allow actions only when the contract IS paused
    modifier whenPaused {
        require(paused);
        _;
    }

    /// @dev Called by any "C-level" role to pause the contract. Used only when
    ///  a bug or exploit is detected and we need to limit damage.
    function pause() external onlyCLevel whenNotPaused {
        paused = true;
    }

    /// @dev Unpauses the smart contract. Can only be called by the CEO, since
    ///  one reason we may pause the contract is when CFO or COO accounts are
    ///  compromised.
    /// @notice This is public rather than external so it can be called by
    ///  derived contracts.
    function unpause() public onlyCEO whenPaused {
        // can't unpause if contract was upgraded
        paused = false;
    }

    /*** Destructible functionality adapted from OpenZeppelin ***/
    /**
     * @dev Transfers the current balance to the owner and terminates the contract.
     */
    function destroy() onlyCEO public {
        selfdestruct(ceoAddress);
    }

    function destroyAndSend(address _recipient) onlyCEO public {
        selfdestruct(_recipient);
    }
}
function setAnimator(address _newAnimator) external onlyCEO {
    require(_newAnimator != address(0));

    animatorAddress = _newAnimator;
}

/// Assigns a new address to the Animator role. Only available to the current CEO.
/// @param _newAnimator The address of the new Animator