contract CSportsAuction is CSportsOwnership, SaleClockAuctionListener {

  // Holds a reference to our saleClockAuctionContract
  CSportsAuctionInterface public saleClockAuctionContract;

  /// @dev SaleClockAuctionLIstener interface method concrete implementation
  function implementsSaleClockAuctionListener() public pure returns (bool) {
    return true;
  }

  /// @dev SaleClockAuctionLIstener interface method concrete implementation
  function auctionCreated(uint256 /* tokenId */, address /* seller */, uint128 /* startingPrice */, uint128 /* endingPrice */, uint64 /* duration */) public {
    require (saleClockAuctionContract != address(0));
    require (msg.sender == address(saleClockAuctionContract));
  }

  /// @dev SaleClockAuctionLIstener interface method concrete implementation
  /// @param tokenId - ID of the token whose auction successfully completed
  /// @param totalPrice - Price at which the auction closed at
  /// @param seller - Account address of the auction seller
  /// @param winner - Account address of the auction winner (buyer)
  function auctionSuccessful(uint256 tokenId, uint128 totalPrice, address seller, address winner) public {
    require (saleClockAuctionContract != address(0));
    require (msg.sender == address(saleClockAuctionContract));

    // Record the most recent sale price to the token
    PlayerToken storage _playerToken = playerTokens[tokenId];
    _playerToken.mostRecentPrice = totalPrice;

    if (seller == address(this)) {
      // We completed a commissioner auction!
      leagueRosterContract.commissionerAuctionComplete(playerTokens[tokenId].realWorldPlayerId, totalPrice);
      emit CommissionerAuctionSuccessful(tokenId, totalPrice, winner);
    }
  }

  /// @dev SaleClockAuctionLIstener interface method concrete implementation
  /// @param tokenId - ID of the token whose auction was cancelled
  /// @param seller - Account address of seller who decided to cancel the auction
  function auctionCancelled(uint256 tokenId, address seller) public {
    require (saleClockAuctionContract != address(0));
    require (msg.sender == address(saleClockAuctionContract));
    if (seller == address(this)) {
      // We cancelled a commissioner auction!
      leagueRosterContract.commissionerAuctionCancelled(playerTokens[tokenId].realWorldPlayerId);
      emit CommissionerAuctionCanceled(tokenId);
    }
  }

  /// @dev Sets the reference to the sale auction.
  /// @param _address - Address of sale contract.
  function setSaleAuctionContractAddress(address _address) public onlyCEO {

      require(_address != address(0));

      CSportsAuctionInterface candidateContract = CSportsAuctionInterface(_address);

      // Sanity check
      require(candidateContract.isSaleClockAuction());

      // Set the new contract address
      saleClockAuctionContract = candidateContract;

  }

  /// @dev Allows the commissioner to cancel his auctions (which are owned
  ///   by this contract)
  function cancelCommissionerAuction(uint32 tokenId) public onlyCommissioner {
    require(saleClockAuctionContract != address(0));
    saleClockAuctionContract.cancelAuction(tokenId);
  }

  /// @dev Put a player up for auction. The message sender must own the
  ///   player token being put up for auction.
  /// @param _playerTokenId - ID of playerToken to be auctioned
  /// @param _startingPrice - Starting price in wei
  /// @param _endingPrice - Ending price in wei
  /// @param _duration - Duration in seconds
  function createSaleAuction(
      uint256 _playerTokenId,
      uint256 _startingPrice,
      uint256 _endingPrice,
      uint256 _duration
  )
      public
      whenNotPaused
  {
      // Auction contract checks input sizes
      // If player is already on any auction, this will throw
      // because it will be owned by the auction contract.
      require(_owns(msg.sender, _playerTokenId));
      _approve(_playerTokenId, saleClockAuctionContract);

      // saleClockAuctionContract.createAuction throws if inputs are invalid and clears
      // transfer after escrowing the player.
      saleClockAuctionContract.createAuction(
          _playerTokenId,
          _startingPrice,
          _endingPrice,
          _duration,
          msg.sender
      );
  }

  /// @dev Transfers the balance of the sale auction contract
  /// to the CSportsCore contract. We use two-step withdrawal to
  /// avoid two transfer calls in the auction bid function.
  /// To withdraw from this CSportsCore contract, the CFO must call
  /// the withdrawBalance(...) function defined in CSportsAuth.
  function withdrawAuctionBalances() external onlyCOO {
      saleClockAuctionContract.withdrawBalance();
  }
}
/// @title The facet of the CSports core contract that manages interfacing with auctions
/// @author CryptoSports, Inc. (http://cryptosports.team)
/// See the CSportsCore contract documentation to understand how the various contract facets are arranged.
function auctionCancelled(uint256 tokenId, address seller) public {
  require (saleClockAuctionContract != address(0));
  require (msg.sender == address(saleClockAuctionContract));
  if (seller == address(this)) {
    // We cancelled a commissioner auction!
    leagueRosterContract.commissionerAuctionCancelled(playerTokens[tokenId].realWorldPlayerId);
    emit CommissionerAuctionCanceled(tokenId);
  }
}

/// @dev SaleClockAuctionLIstener interface method concrete implementation
/// @param tokenId - ID of the token whose auction was cancelled
/// @param seller - Account address of seller who decided to cancel the auction