contract IDealsSupport {

// Any user

  /**
   * @dev Checks whether a deal can be cancelled by merchant
   * @param _dealIndex deal index
   * @return whether a deal can be cancelled by merchant
   */
  function canBeCancelledByMerchant(uint _dealIndex) public view returns(bool);

  /**
   * @dev Returns affiliate reward info
   * @param _referenceHash affiliate's reference hash(index)
   * @param _affiliateRewardIndex affiliate reward index
   * @return affiliate reward info
   */
  function getAffiliateRewardInfo(uint _referenceHash, uint _affiliateRewardIndex) public view returns(uint, uint);

  /**
   * @dev Returns deal index by reference hash
   * @param _referenceHash affiliate's reference hash(index)
   * @return deal index
   */
  function getDealIndex(uint _referenceHash) public view returns(uint);

  /**
   * @dev Returns dynamic deal info: reference hashes.
   * @param _dealIndex deal index
   * @return array of reference hashes in deal
   */
  function getDynamicDealInfo(uint _dealIndex) public view returns(uint[]);

  /**
   * @dev Returns reference hash that should be passed in reference links
   * @param _dealIndex deal index
   * @param _affiliateAddress affiliate address
   * @return reference hash
   */
  function getReferenceHash(uint _dealIndex, address _affiliateAddress) public view returns(uint);

  /**
   * @dev Checks whether deal is cancelled
   * @param _dealIndex deal index
   * @return bool whether deal is cancelled
   */
  function isDealCancelled(uint _dealIndex) public view returns(bool);

  /**
   * @dev Checks whether deal is closed
   * @param _dealIndex deal index
   * @return bool whether deal is closed
   */
  function isDealClosed(uint _dealIndex) public view returns(bool);

// Admin

  /**
   * @dev Blocks/unblocks affiliate. As an admin i would like to block the selected affiliate.
   * @param _referenceHash affiliate's reference hash(index)
   */
  function toggleBlockAffiliate(uint _referenceHash) public;

  /**
   * @dev Cancells deal immediately. As an admin I would like to immediately cancel the selected deal in order to prevent fraudulent behaviour.
   * @notice Will immediately move the selected deal into 'cancelled' state
   * @param _dealIndex deal index
   */
  function cancelDealByAdmin(uint _dealIndex) public;

  /**
   * @dev Changes admin address(transfer ownership)
   * @param _newAdminAddress new admin address
   */
  function changeAdmin(address _newAdminAddress) public;

// Affiliate

  /**
   * @dev Withdraws a reward by affiliate. As an affiliate i would like to get my reward for the selected deal in order to get money.
   * Preconditions:
   *  1. The Deal index is valid.
   *  2. Affiliate is not blocked.
   *  3. The reward amount is non zero for the selected affiliate.
   *  4. The reward amount is non zero for the selected deal.
   * @param _dealIndex deal index
   * Result:
   *   All reward tokens are transferred from the current MultistageCrowdsale contract to the affiliate.
   *   The reward amount for the selected affiliate is set to zero.
   *   The reward amount for the selected deal is decreased.
   */
  function getMyReward(uint _dealIndex) public;

// Merchant

  /**
   * @dev Approves affiliate address for deal. As a merchant i would like to manually approve selected affiliate in order to provide incentives.
   * @notice The same affiliate address can have different reference hashes because the same affiliate address can participate in multiple deals.
   * @param _dealIndex deal index
   * @param _affiliateAddress affiliate address
   */
  function approveAffiliate(uint _dealIndex, address _affiliateAddress) public;

  /**
   * @dev Cancels all deals by merchant
   */
  function cancelAllDealsByMerchant() public;

  /**
   * @dev Marks deal to be cancelled by merchant. As a merchant I would like to request a deal cancelation in order to cancel it after “Cancelation period” is elapsed.
   * @param _dealIndex deal index
   */
  function cancelDealByMerchant(uint _dealIndex) public;

  /**
   * @dev Creates a new deal by merchant. As a merchant i would like to create new deal in order to add incentives for affiliates.
   * @param _rewardTokenAddress ERC20 token address used for affiliates' rewards
   * @param _rewardRatePpm reward rate ppm, 100% == 1000000
   * @param _daysOfCancellation when deal is marked as cancelled it is still live for _daysOfCancellation number of days
   * @param _daysBeforeClose number of days since deal creation when deal is still live, the deal is over and any left over staked tokens can be withdrawn by merchant
   */
  function createDeal(bytes4 _dealID, address _rewardTokenAddress, uint _rewardRatePpm, uint _daysOfCancellation, uint _daysBeforeClose, bool _isAcceptAnyAffiliate) public;

  /**
   * @dev Stakes ERC20 tokens as reward for affiliates by merchant. As a merchant i would like to transfer ERC20 tokens to the selected deal in order to stake them.
   * @notice Merchant should allow _amount of tokens to be withdrawn (use ERC20.approve() method) BEFORE calling this method.
   * Preconditions:
   *  1. The Deal was created by Merchant before
   *  2. isCancelled == false
   *  3. isClosed == false
   *  4. Merchant allowed current MultistageCrowdsale to withdraw correct amount of tokens
   * @param _dealIndex deal index
   * @param _amount amount in wei
   */
  function fillStake(uint _dealIndex, uint _amount) public;

  /**
   * @dev Returns tokens at stake back to merchant if deal is cancelled. As a merchant i would like to get my stake back in order to get my tokens back (if deal is cancelled).
   * Preconditions:
     *  1. The Deal was created by Merchant before.
     *  2. The Deal isCancelled==true.
     *  3. The Deal still has some stake left.
   *  4. The Deal has enough tokens to pay to all affiliates.
   * @param _dealIndex deal index
   * Result:
     *    All staked reward tokens are transferred from the current MultistageCrowdsale contract back to merchant.
     *    The “Current reward stake amount” of the selected Deal is decreased.
   */
  function getMyStakeBack(uint _dealIndex) public;

  /**
   * @dev Updates a deal by merchant
   * @param _dealIndex deal index
   * @param _newRewardRatePpm new reward rate ppm, 100% == 1000000
   */
  function updateDeal(uint _dealIndex, uint _newRewardRatePpm) public;

}
function getDealIndex(uint _referenceHash) public view returns(uint);

/**
 * @dev Returns deal index by reference hash
 * @param _referenceHash affiliate's reference hash(index)
 * @return deal index
 */