/// <summary>
        /// tries to withdraw money from a client's account
        /// </summary>
        /// <param name="client">Client object to take data from (client's current ammount, ammount of money
        /// the client wants to withdraw and the client's bank account number)</param>
        public void WithdrawMoney(Client client)
        {
            // client does not have enough money, cancel withdrawing
            if (client.AmmountToWithdraw > client.CurrentAmmount)
            {
                client.WithdrawOperationString = string.Format("{0} {1} {2} Negalima išmokėti",
                                                               client.BankAccountNumber, client.CurrentAmmount, client.AmmountToWithdraw);
                return;
            }

            // client has more money than the ammount to be withdrawn
            else
            {
                if (PossibleToWithdraw(client.AmmountToWithdraw))
                {
                    bool success = true;
                    BanknoteContainer banknotes = GetBanknotes(client.AmmountToWithdraw, out success);

                    RemoveBanknotes(banknotes);
                    client.CurrentAmmount         -= client.AmmountToWithdraw;
                    client.WithdrawOperationString = FormSuccessfullWithdrawingOperationString(client, banknotes);
                }
                else
                {
                    client.WithdrawOperationString = string.Format("{0} {1} {2} Negalima išmokėti",
                                                                   client.BankAccountNumber, client.CurrentAmmount, client.AmmountToWithdraw);
                }
            }
        }
 /// <summary>
 /// loops through all Banknote objects in a BanknoteContainer and writes formatted banknote strings to
 /// a StreamWriter
 /// </summary>
 /// <param name="writer">StreamWriter to write to</param>
 /// <param name="banknotes">BanknoteContainer containing banknotes to print</param>
 static void PrintBanknotes(StreamWriter writer, BanknoteContainer banknotes)
 {
     for (int i = 0; i < banknotes.Count; i++)
     {
         writer.WriteLine("{0}", banknotes.GetBanknote(i).ToString());
     }
 }
 /// <summary>
 /// creates BanknoteCount object for each banknote in the data arrays
 ///
 /// EXAMPLE DATA ARRAYS:
 /// banknoteType: ["500", "200", "100"]
 /// banknoteCount: ["10", "7", "15"]
 /// this means there are 10 banknotes worth 500, 7 banknotes worth 200 and 15 banknotes worth 100
 /// </summary>
 /// <param name="banknoteType">array containing banknote wealth values</param>
 /// <param name="banknoteCount">array containing banknote count values</param>
 /// <param name="banknotes">BanknoteContainer to store created BanknoteCount objects in</param>
 static void CreateBankotes(string[] banknoteType, string[] banknoteCount, BanknoteContainer banknotes)
 {
     for (int i = 0; i < NumberOfBanknoteTypes; i++)
     {
         banknotes.AddBanknote(new BanknoteCount(int.Parse(banknoteType[i]),
                                                 int.Parse(banknoteCount[i])));
     }
 }
        /// <summary>
        /// removes banknotes from the ATM
        /// called only after a successfull withdraw operation
        /// </summary>
        /// <param name="banknotes">BanknoteContainer containing BanknoteCount objects with the number of
        /// banknotes to remove from the ATM</param>
        private void RemoveBanknotes(BanknoteContainer banknotes)
        {
            for (int i = 0; i < banknotes.Count; i++)
            {
                Banknote banknote      = banknotes.GetBanknote(i);
                int      banknoteIndex = Banknotes.BanknoteIndex(banknote);

                Banknotes.InsertBanknote(banknoteIndex,
                                         (Banknotes.GetBanknote(banknoteIndex) as BanknoteCount) - (banknote as BanknoteCount));
            }
        }
        /// <summary>
        /// calculates the ammount of money in BanknoteContainer
        /// </summary>
        /// <param name="banknotes">BanknoteContainer to take data from</param>
        /// <returns>the ammount of money from the banknotes</returns>
        public int CalculateMoney(BanknoteContainer banknotes)
        {
            int ammount = 0;

            for (int i = 0; i < banknotes.Count; i++)
            {
                BanknoteCount banknote = banknotes.GetBanknote(i) as BanknoteCount;
                ammount += banknote.Count * banknote.Wealth;
            }

            return(ammount);
        }
        /// <summary>
        /// writes initial data to a seperate text file formatted as two tables:
        /// one for banknote data and another one for client data
        /// </summary>
        /// <param name="fileName">file name to write data to</param>
        /// <param name="banknotes">BanknoteContainer containing initial banknote data</param>
        /// <param name="clients">ClientContainer containing initial client data</param>
        static void PrintInitialDataToTextFile(string fileName, BanknoteContainer banknotes, ClientContainer clients)
        {
            using (StreamWriter writer = new StreamWriter(fileName)) {
                writer.WriteLine("Banknotes:");
                writer.WriteLine("{0, -20} {1, -20}", "Banknote wealth", "Banknote count");
                PrintBanknotes(writer, banknotes);

                writer.WriteLine();
                writer.WriteLine("Clients:");
                writer.WriteLine("{0, -20} {1, -20} {2, -20}",
                                 "Bank account number", "Current ammount", "Ammount to withdraw");
                PrintClients(writer, clients);
            }
        }
        /// <summary>
        /// creates information string from a successfull withdraw operation:
        /// client's bank account number, banknotes the client just received and the ammount of money client has left
        /// </summary>
        /// <param name="client">Client who performed withdraw operation</param>
        /// <param name="banknotes">banknotes the client received from the ATM</param>
        /// <returns>formatted withdrawing operation text</returns>
        private string FormSuccessfullWithdrawingOperationString(Client client, BanknoteContainer banknotes)
        {
            string operation = string.Format("{0} {1}",
                                             client.BankAccountNumber, client.CurrentAmmount + CalculateMoney(banknotes), client.AmmountToWithdraw);

            for (int i = 0; i < banknotes.Count; i++)
            {
                BanknoteCount banknote = banknotes.GetBanknote(i) as BanknoteCount;
                operation = string.Format("{0}-{1}*{2}", operation, banknote.Wealth, banknote.Count);
            }

            operation = string.Format("{0} = {1}", operation, client.CurrentAmmount);

            return(operation);
        }
        public static int NumberOfBanknoteTypes = 6; // number of different banknotes in the data file

        /// <summary>
        /// entry point of the program
        /// </summary>
        /// <param name="args">arguments for the program</param>
        static void Main(string[] args)
        {
            Console.OutputEncoding = Encoding.UTF8;

            BanknoteContainer banknotes = new BanknoteContainer(NumberOfBanknoteTypes);
            ClientContainer   clients   = new ClientContainer(100);

            ReadData("U3.txt", banknotes, clients);
            PrintInitialDataToTextFile("pradDuom.txt", banknotes, clients);

            ATM atm = new ATM(banknotes);

            PerformWithdrawOperations(atm, clients);

            PrintResults("rezult.txt", atm, clients);
        }
        /// <summary>
        /// tries to get enough right banknotes for a withdraw operation
        /// this method does not remove any banknotes from the ATM, it only creates copies of the banknotes
        /// to withdraw
        /// </summary>
        /// <param name="ammount">ammount of money to withdraw</param>
        /// <param name="success">boolean indicating wether there was enough right banknotes to withdraw</param>
        /// <returns>BanknoteContainer of banknotes to be withdrawn (will be used only is success = true)</returns>
        private BanknoteContainer GetBanknotes(int ammount, out bool success)
        {
            BanknoteContainer banknotes = new BanknoteContainer(Program.NumberOfBanknoteTypes);

            for (int i = 0; i < Banknotes.Count; i++)
            {
                BanknoteCount banknote = Banknotes.GetBanknote(i) as BanknoteCount;

                int numberOfBanknotesRequired = ammount / banknote.Wealth;
                int availableBanknotes        = (banknote.Count >= numberOfBanknotesRequired)
                    ? numberOfBanknotesRequired : banknote.Count;

                banknotes.AddBanknote(new BanknoteCount(banknote.Wealth, availableBanknotes));
                ammount -= availableBanknotes * banknote.Wealth;
            }

            success = ammount == 0;

            return(banknotes);
        }
        /// <summary>
        /// reads banknote and client data from a given file and stores it in BanknoteContainer and ClientContainer
        /// </summary>
        /// <param name="fileName">file name to read from</param>
        /// <param name="banknotes">BanknoteContainer to store Banknote objects in</param>
        /// <param name="clients">ClientContainer to store Client objects in</param>
        static void ReadData(string fileName, BanknoteContainer banknotes, ClientContainer clients)
        {
            using (StreamReader reader = new StreamReader(fileName)) {
                CreateBankotes(reader.ReadLine().Split(' '), reader.ReadLine().Split(' '), banknotes);

                int clientCount = int.Parse(reader.ReadLine());

                for (int i = 0; i < clientCount; i++)
                {
                    string   line = reader.ReadLine();
                    string   bankAccountNumber = line.Substring(0, 4);
                    string[] data = line.Substring(4).Split(new char[] { ' ' },
                                                            StringSplitOptions.RemoveEmptyEntries);
                    int currentAmmount    = int.Parse(data[0]);
                    int ammountToWithdraw = int.Parse(data[1]);

                    clients.AddClient(new Client(bankAccountNumber, currentAmmount, ammountToWithdraw));
                }
            }
        }
        }                                                // banknotes in the ATM

        /// <summary>
        /// class constructor
        /// </summary>
        /// <param name="banknotes">BanknoteContainer containing all banknotes in the ATM</param>
        public ATM(BanknoteContainer banknotes)
        {
            Banknotes = banknotes;
        }