contract WarriorSanctuary is WarriorGenerator {
    uint256 internal constant SUMMONING_SICKENESS = 12 hours;
    uint256 internal constant RITUAL_DURATION = 15 minutes;
    /// @notice The payment required to use startRitual().
    uint256 public ritualFee = 10 finney;
    
    uint256 public constant RITUAL_COMPENSATION = 2 finney;
    
    mapping(address => uint256) public soulCounter;
    //
    mapping(address => uint256) public ritualTimeBlock;
    
    bool public recoveryAllowed = true;
    
    event WarriorBurned(uint256 warriorId, address owner);
    event RitualStarted(address owner, uint256 numberOfSouls);
    event RitualFinished(address owner, uint256 numberOfSouls, uint256 newWarriorId);
    
    
    function WarriorSanctuary(address _coreContract, uint32[] _settings) public {
        uint256 length = _settings.length;
        require(length == 18);
        require(_settings[8] == 4);//check runes max
        require(_settings[10] == 10);//check pets max
        require(_settings[11] == 5);//check border max
        require(_settings[12] == 6);//check background max
        //setup parameters
        for(uint256 i = 0; i < length; i ++) {
            parameters[i] = _settings[i];
        }	
        
        //set core
        CryptoWarriorCore coreCondidat = CryptoWarriorCore(_coreContract);
        require(coreCondidat.isPVPListener());
        coreContract = coreCondidat;
        
    }
    
    function recoverSouls(address[] owners, uint256[] souls, uint256[] blocks) external onlyOwner {
        require(recoveryAllowed);
        
        uint256 length = owners.length;
        require(length == souls.length && length == blocks.length);
        
        for(uint256 i = 0; i < length; i ++) {
            soulCounter[owners[i]] = souls[i];
            ritualTimeBlock[owners[i]] = blocks[i];
        }
        
        recoveryAllowed = false;
    }
    
    
    //burn warrior
    function burnWarrior(uint256 _warriorId) whenNotPaused external {
        coreContract.burnWarrior(_warriorId, msg.sender);
        
        soulCounter[msg.sender] ++;
        
        WarriorBurned(_warriorId, msg.sender);
    }
   
    
    function startRitual() whenNotPaused external payable {
        // Checks for payment.
        require(msg.value >= ritualFee);
        
        uint256 souls = soulCounter[msg.sender];
        // Check that address has at least 10 burned souls
        require(souls >= 10);
        //
        //Check that no rituals are in progress
        require(ritualTimeBlock[msg.sender] == 0);
        
        ritualTimeBlock[msg.sender] = RITUAL_DURATION / coreContract.secondsPerBlock() + block.number;
        
        // Calculate any excess funds included in msg.value. If the excess
        // is anything worth worrying about, transfer it back to message owner.
        // NOTE: We checked above that the msg.value is greater than or
        // equal to the price so this cannot underflow.
        uint256 feeExcess = msg.value - ritualFee;

        // Return the funds. This is not susceptible 
        // to a re-entry attack because of _isReadyToPVE check
        // will fail
        if (feeExcess > 0) {
            msg.sender.transfer(feeExcess);
        }
        //send battle fee to beneficiary
        coreContract.getBeneficiary().transfer(ritualFee - RITUAL_COMPENSATION);
        
        RitualStarted(msg.sender, souls);
    }
    
    
    //arise warrior
    function finishRitual(address _owner) whenNotPaused external {
        // Check ritual time is over
        uint256 timeBlock = ritualTimeBlock[_owner];
        require(timeBlock > 0 && timeBlock <= block.number);
        
        uint256 souls = soulCounter[_owner];
        
        require(souls >= 10);
        
        uint256 identity = _generateIdentity(uint256(_owner), souls, timeBlock - 1, 0);
        
        uint256 warriorId = coreContract.ariseWarrior(identity, _owner, block.number + (SUMMONING_SICKENESS / coreContract.secondsPerBlock()));
    
        soulCounter[_owner] = 0;
        ritualTimeBlock[_owner] = 0;
        //send compensation
        msg.sender.transfer(RITUAL_COMPENSATION);
        
        RitualFinished(_owner, 10, warriorId);
    }
    
    function setRitualFee(uint256 _pveRitualFee) external onlyOwner {
        require(_pveRitualFee > RITUAL_COMPENSATION);
        ritualFee = _pveRitualFee;
    }
}
function finishRitual(address _owner) whenNotPaused external {
    // Check ritual time is over
    uint256 timeBlock = ritualTimeBlock[_owner];
    require(timeBlock > 0 && timeBlock <= block.number);
        
    uint256 souls = soulCounter[_owner];
        
    require(souls >= 10);
        
    uint256 identity = _generateIdentity(uint256(_owner), souls, timeBlock - 1, 0);
        
    uint256 warriorId = coreContract.ariseWarrior(identity, _owner, block.number + (SUMMONING_SICKENESS / coreContract.secondsPerBlock()));
    
    soulCounter[_owner] = 0;
    ritualTimeBlock[_owner] = 0;
    //send compensation
    msg.sender.transfer(RITUAL_COMPENSATION);
        
    RitualFinished(_owner, 10, warriorId);
}

//arise warrior