contract DragonCore is DragonMinting {

    // Set in case the core contract is broken and an upgrade is required
    address public newContractAddress;

    /// @notice Creates the main BlockDragonz smart contract instance.
    constructor () public {
        // Starts paused.
        paused = true;

        // the creator of the contract is the initial CEO
        ceoAddress = msg.sender;

        // the creator of the contract is also the initial CMO
        cmoAddress = msg.sender;

        // the creator of the contract is also the initial CIO
        cioAddress = msg.sender;

        // the creator of the contract is also the initial CFO
        cfoAddress = msg.sender;

        // the creator of the contract is also the initial COO
        cooAddress = msg.sender;

        // ERC-165 Base
        supportedInterfaces[0x01ffc9a7] = true;

        // ERC-721 Base
        supportedInterfaces[0x80ac58cd] = true;

        // ERC-721 Metadata
        supportedInterfaces[0x5b5e139f] = true;

        // ERC-721 Enumerable
        supportedInterfaces[0x780e9d63] = true;

        //ERC-721 Receiver
        supportedInterfaces[0x150b7a02] = true;

        // start with the mythical dragon 0 - so we don't have generation-0 parent issues
        _createDragon(0, 0, 0, uint256(-1), 0,0,0,0,  address(0));
    }

    function setNewAddress(address _newAddress) external onlyCEO whenPaused {
        newContractAddress = _newAddress;
        emit ContractUpgrade(_newAddress);
    }

    /// @notice No tipping!
    /// @dev Reject all Ether from being sent here, unless it's from one of the
    ///  two auction contracts. (Hopefully, we can prevent user accidents.)
    function() external payable {
        require(
            msg.sender == address(saleAuction) ||
            msg.sender == address(siringAuction)
        );
    }
    /// @notice Returns all the relevant information about a specific dragon.
    /// @param _id The ID of the dragon of interest.
    function getDragon(uint256 _id)
    external
    view
    returns (
        uint256 dna,
        uint256 birthTime,
        uint256 breedTime,
        uint256 matronId,
        uint256 sireId,
        uint256 siringWithId,
        uint256 generation,
        uint256 runeLevel,
        uint256 agility,
        uint256 strength,
        uint256 intelligence
    ) {
        Dragon storage dragon = dragons[_id];
        DragonAssets storage dragonAsset = dragonAssets[_id];

        dna = dragon.dna;
        birthTime = uint256(dragon.birthTime);
        breedTime = uint256(dragon.breedTime);
        matronId = uint256(dragon.matronId);
        sireId = uint256(dragon.sireId);
        siringWithId = uint256(dragon.siringWithId);
        generation = uint256(dragon.generation);
        runeLevel = dragonAsset.runeLevel;
        agility = dragonAsset.agility;
        strength = dragonAsset.strength;
        intelligence = dragonAsset.intelligence;
    }

    /// @dev Override unpause so it requires all external contract addresses
    ///  to be set before contract can be unpaused. Also, we can't have
    ///  newContractAddress set either, because then the contract was upgraded.
    /// @notice This is public rather than external so we can call super.unpause
    ///  without using an expensive CALL.
    function unpause() public onlyCEO whenPaused {
        require(address(saleAuction) != address(0));
        require(address(siringAuction) != address(0));
        require(newContractAddress == address(0));

        // Actually unpause the contract.
        super.unpause();
    }

    // @dev Allows the CIO to capture the balance available to the contract.
    function withdrawBalance() external onlyCLevel {
        uint256 balance = address(this).balance;
        // Subtract all the currently pregnant dragons we have, plus 1 of margin.
        uint256 subtractFees = (pregnantDragons + 1) * autoBirthFee;

        if (balance > subtractFees) {
            //cioAddress.send(balance - subtractFees);
            cfoAddress.transfer(balance - subtractFees);
        }
    }

    /// @dev Shows the contract's current balance.
    function getBalance() external view onlyCLevel returns (uint256) {
        return address(this).balance;
    }
}
function getDragon(uint256 _id)
external
view
returns (
    uint256 dna,
    uint256 birthTime,
    uint256 breedTime,
    uint256 matronId,
    uint256 sireId,
    uint256 siringWithId,
    uint256 generation,
    uint256 runeLevel,
    uint256 agility,
    uint256 strength,
    uint256 intelligence
) {
    Dragon storage dragon = dragons[_id];
    DragonAssets storage dragonAsset = dragonAssets[_id];

    dna = dragon.dna;
    birthTime = uint256(dragon.birthTime);
    breedTime = uint256(dragon.breedTime);
    matronId = uint256(dragon.matronId);
    sireId = uint256(dragon.sireId);
    siringWithId = uint256(dragon.siringWithId);
    generation = uint256(dragon.generation);
    runeLevel = dragonAsset.runeLevel;
    agility = dragonAsset.agility;
    strength = dragonAsset.strength;
    intelligence = dragonAsset.intelligence;
}

/// @notice Returns all the relevant information about a specific dragon.
/// @param _id The ID of the dragon of interest.