contract PreSaleCastle is PreSaleRealm {
    // ----------------------------------------------------------------------------
    // Events
    // ----------------------------------------------------------------------------
    event CastleSaleCreate(uint indexed saleId, uint indexed castleId, uint indexed price, uint realmId, uint rarity);
    event BuyCastle(uint indexed saleId, uint castleId, address indexed buyer, uint indexed currentPrice);
    event CastleOfferSubmit(uint indexed saleId, uint castleId, address indexed bidder, uint indexed price);
    event CastleOfferAccept(uint indexed saleId, uint castleId, address indexed newOwner, uint indexed newPrice);
    event SetCastleSale(uint indexed saleId, uint indexed price, uint realmId, uint rarity);
    
    event CastleAuctionCreate(uint indexed auctionId, uint indexed castleId, uint indexed startPrice, uint realmId, uint rarity);
    event CastleAuctionBid(uint indexed auctionId, address indexed bidder, uint indexed offer);
    
    
    // ----------------------------------------------------------------------------
    // Mappings
    // ----------------------------------------------------------------------------
    mapping (uint => address) public CastleSaleToBuyer;
    mapping (uint => bool) CastleIdToIfCreated;
    
    // ----------------------------------------------------------------------------
    // Variables
    // ----------------------------------------------------------------------------
    struct CastleSale {
        uint castleId;
        uint realmId;
        uint rarity;
        uint price;
        bool ifSold;
        address bidder;
        uint offerPrice;
        uint timestamp;
    }

    CastleSale[] castleSales;

    // ----------------------------------------------------------------------------
    // Modifier
    // ----------------------------------------------------------------------------
    
    // ----------------------------------------------------------------------------
    // Internal Function
    // ----------------------------------------------------------------------------
    function _generateCastleSale(uint _castleId, uint _realmId, uint _rarity, uint _price) internal returns (uint) {
        require(CastleIdToIfCreated[_castleId] == false);
        CastleIdToIfCreated[_castleId] = true;
        CastleSale memory _CastleSale = CastleSale({
            castleId: _castleId,
            realmId: _realmId,
            rarity: _rarity,
            price: _price,
            ifSold: false,
            bidder: address(0),
            offerPrice: 0,
            timestamp: 0
        });
        uint castleSaleId = castleSales.push(_CastleSale) - 1;
        emit CastleSaleCreate(castleSaleId, _castleId, _price, _realmId, _rarity);
        
        return castleSaleId;
    }

    // ----------------------------------------------------------------------------
    // Public Function
    // ----------------------------------------------------------------------------
    function createCastleSale(uint _num, uint _startId, uint _realmId, uint _rarity, uint _price) public onlyAdmin {
        for(uint i = 0; i<_num; i++) {
            _generateCastleSale(_startId + i, _realmId, _rarity, _price);
        }
    }
    
    function buyCastle(uint _castleSaleId, uint _brokerId, uint _subBrokerId) public payable whenNotPaused {
        CastleSale storage _castleSale = castleSales[_castleSaleId];
        require(CastleSaleToBuyer[_castleSale.castleId] == address(0));
        require(_castleSale.ifSold == false);
        uint currentPrice;
        if(pricePause == true) {
            if(_castleSale.timestamp != 0 && _castleSale.timestamp != endTime) {
                uint timePass = safeSub(endTime, startTime);
                _castleSale.price = _computePrice(_castleSale.price, _castleSale.price*raiseIndex[0], preSaleDurance, timePass);
                _castleSale.timestamp = endTime;
            }
            _brokerFeeDistribute(_castleSale.price, 0, _brokerId, _subBrokerId);
            require(msg.value >= _castleSale.price);
            currentPrice = _castleSale.price;
        } else {
            if(_castleSale.timestamp == 0) {
                _castleSale.timestamp = uint(now);
            }
            currentPrice = _computePrice(_castleSale.price, _castleSale.price*raiseIndex[0], preSaleDurance, safeSub(uint(now), startTime));
            _brokerFeeDistribute(currentPrice, 0, _brokerId, _subBrokerId);
            require(msg.value >= currentPrice);
            _castleSale.price = currentPrice;
        }
        CastleSaleToBuyer[_castleSale.castleId] = msg.sender;
        _castleSale.ifSold = true;
        emit BuyCastle(_castleSaleId, _castleSale.castleId, msg.sender, currentPrice);
    }
    
    function OfflineCastleSold(uint _castleSaleId, address _buyer, uint _price) public onlyAdmin {
        CastleSale storage _castleSale = castleSales[_castleSaleId];
        require(_castleSale.ifSold == false);
        CastleSaleToBuyer[_castleSale.castleId] = _buyer;
        _castleSale.ifSold = true;
        emit BuyCastle(_castleSaleId, _castleSale.castleId, _buyer, _price);
    }
    
    function OfferToCastle(uint _castleSaleId, uint _price) public payable whenNotPaused {
        CastleSale storage _castleSale = castleSales[_castleSaleId];
        require(_castleSale.ifSold == true);
        require(_price >= _castleSale.offerPrice*11/10);
        require(msg.value >= _price);
        
        if(_castleSale.bidder == address(0)) {
            _castleSale.bidder = msg.sender;
            _castleSale.offerPrice = _price;
        } else {
            address lastBidder = _castleSale.bidder;
            uint lastOffer = _castleSale.price;
            lastBidder.transfer(lastOffer);
            
            _castleSale.bidder = msg.sender;
            _castleSale.offerPrice = _price;
        }
        
        emit CastleOfferSubmit(_castleSaleId, _castleSale.castleId, msg.sender, _price);
    }
    
    function AcceptCastleOffer(uint _castleSaleId) public whenNotPaused {
        CastleSale storage _castleSale = castleSales[_castleSaleId];
        require(CastleSaleToBuyer[_castleSale.castleId] == msg.sender);
        require(_castleSale.bidder != address(0) && _castleSale.offerPrice > 0);
        msg.sender.transfer(_castleSale.offerPrice);
        CastleSaleToBuyer[_castleSale.castleId] = _castleSale.bidder;
        _castleSale.price = _castleSale.offerPrice;
        
        emit CastleOfferAccept(_castleSaleId, _castleSale.castleId, _castleSale.bidder, _castleSale.offerPrice);
        
        _castleSale.bidder = address(0);
        _castleSale.offerPrice = 0;
    }
    
    function setCastleSale(uint _castleSaleId, uint _price, uint _realmId, uint _rarity) public onlyAdmin {
        CastleSale storage _castleSale = castleSales[_castleSaleId];
        require(_castleSale.ifSold == false);
        _castleSale.price = _price;
        _castleSale.realmId = _realmId;
        _castleSale.rarity = _rarity;
        emit SetCastleSale(_castleSaleId, _price, _realmId, _rarity);
    }
    
    function getCastleSale(uint _castleSaleId) public view returns (
        address owner,
        uint castleId,
        uint realmId,
        uint rarity,
        uint price,
        bool ifSold,
        address bidder,
        uint offerPrice,
        uint timestamp
    ) {
        CastleSale memory _CastleSale = castleSales[_castleSaleId];
        owner = CastleSaleToBuyer[_CastleSale.castleId];
        castleId = _CastleSale.castleId;
        realmId = _CastleSale.realmId;
        rarity = _CastleSale.rarity;
        price = _CastleSale.price;
        ifSold =_CastleSale.ifSold;
        bidder = _CastleSale.bidder;
        offerPrice = _CastleSale.offerPrice;
        timestamp = _CastleSale.timestamp;
    }
    
    function getCastleNum() public view returns (uint) {
        return castleSales.length;
    }
}
function createCastleSale(uint _num, uint _startId, uint _realmId, uint _rarity, uint _price) public onlyAdmin {
        for(uint i = 0; i<_num; i++) {
            _generateCastleSale(_startId + i, _realmId, _rarity, _price);
        }
    }
// ----------------------------------------------------------------------------
// Public Function
// ----------------------------------------------------------------------------