/// <summary> /// <inheritdoc/> /// <remarks> /// The current state is the <see cref="T:VendingMachine.SoldState"/>. This means that the user has paid. /// The following scenarios are possible in this case :- /// <list type="bullet"> /// <item> /// <description> /// Case 1. Machine does not have exact change to tender. Hence, refund the user money and set the transition state to /// <see cref="T:VendingMachine.WaitUserSelectionState"/> /// </description> /// </item> /// <item> /// <description> /// Case 2. Everything is fine. Ask the machine to release the drink. /// </description> /// </item> /// <item> /// <description> /// Case 3. After releasing the item, check if the machine owes any amount to the user. If yes, then, /// the state is changed to <see cref="T:VendingMachine.DispenseChangeState"/> /// </description> /// </item> /// <item> /// <description> /// Case 4. After releasing the item, checks if the machine has enough inventory and it owes nothing to the user. /// Transitions the state to <see cref="T:VendingMachine.WaitUserSelectionState"/> /// </description> /// </item> /// <item> /// <description> /// Case 5. After releasing the item, check the total inventory count. /// If its zero, then transition the state to <see cref="T:VendingMachine.SoldOutState"/> /// </description> /// </item> /// </list> /// </remarks> /// </summary> public void DispenseItem() { // Machine does not have exact change to tender, hence do not dispense the item // Change back the state to user selection state, refund the money and show an appropriate message to the user. if (String.IsNullOrEmpty(_machine.TenderChange())) { var refund = _machine.RefundMoney(); _machine.State = _machine.GetUserSelectItemState; throw new ApplicationException(string.Format("Machine does not have sufficient change. Please tender exact change. Please collect your inserted amount{0}", refund)); } _machine.ReleaseItem(); _machine.DisplayMessage("Item has been dispensed. Please do not forget to collect it."); // machine has to refund if (_machine.CustomerBalance < 0) { _machine.State = _machine.GetDispenseChangeState; } // Machine has enough products and has nothing to refund back to the user if (_machine.TotalItemCount > 0 && _machine.CustomerBalance == 0) { _machine.State = _machine.GetUserSelectItemState; } // Machine is empty. Everything is sold out. Hence, change the state to SoldOut if (_machine.TotalItemCount == 0) { _machine.State = _machine.GetSoldOutState; throw new ApplicationException("Sorry, the machine is out of stock."); } }