/// <summary>
        /// displays the current account information
        /// </summary>
        public void DisplayAccountDetail(Salesperson salesperson)
        {
            ConsoleUtil.DisplayMessage("First Name: " + salesperson.FirstName);
            ConsoleUtil.DisplayMessage("Last Name: " + salesperson.LastName);
            ConsoleUtil.DisplayMessage("Account ID: " + salesperson.AccountID);
            ConsoleUtil.DisplayMessage("Starting City: " + salesperson.StartingCity);

            if (!salesperson.CurrentStock.OnBackorder)
            {
                ConsoleUtil.DisplayMessage("Products in Inventory: " + salesperson.CurrentStock.NumberOfUnits);
            }
            else
            {
                ConsoleUtil.DisplayMessage("Products on Backorder: " + Math.Abs(salesperson.CurrentStock.NumberOfUnits));
            }
            ConsoleUtil.DisplayMessage("Product Type: " + salesperson.CurrentStock.Type);
            ConsoleUtil.DisplayMessage("");

            ConsoleUtil.DisplayMessage("Cities Traveled: ");
            ConsoleUtil.DisplayMessage("");

            foreach (string city in salesperson.CitiesVisited)
            {
                ConsoleUtil.DisplayMessage(city);
            }
        }
        /// <summary>
        /// prompts the user to save the account and travel log info
        /// </summary>
        public bool DisplaySaveAccountInfo(Salesperson salesperson, out bool maxAttemptsExceeded)
        {
            string userResponse;

            maxAttemptsExceeded = false;

            ConsoleUtil.HeaderText = "Save Account";
            ConsoleUtil.DisplayReset();

            ConsoleUtil.DisplayMessage("Current account information:");
            DisplayAccountDetail(salesperson);

            ConsoleUtil.DisplayMessage("");
            userResponse = ConsoleValidator.GetYesNoFromUser(MAXIMUM_ATTEMPTS, "Save account info?", out maxAttemptsExceeded);

            if (maxAttemptsExceeded)
            {
                ConsoleUtil.DisplayMessage("Max attempts exceeded! You will now be returned to the main menu.");
                return(false);
            }
            else if (userResponse.ToUpper() == "YES")
            {
                return(true);
            }
            {
                return(false);
            }
        }
        /// <summary>
        /// displays a notification upon successful load of the account and travel log info
        /// </summary>
        public void DisplayConfirmLoadAccountInfo(Salesperson salesperson)
        {
            ConsoleUtil.HeaderText = "Load Account";
            ConsoleUtil.DisplayReset();

            ConsoleUtil.DisplayMessage("Account information loaded.");
            ConsoleUtil.DisplayMessage("");

            DisplayAccountDetail(salesperson);

            DisplayContinuePrompt();
        }
        /// <summary>
        /// displays the current inventory
        /// </summary>
        public void DisplayInventory(Salesperson salesperson, Product units)
        {
            ConsoleUtil.HeaderText = "Current Inventory";
            ConsoleUtil.DisplayReset();

            ConsoleUtil.DisplayMessage("");
            ConsoleUtil.DisplayMessage("Products:");
            ConsoleUtil.DisplayMessage("");
            ConsoleUtil.DisplayPromptMessage($"\t- {salesperson.CurrentStock.Type}, # of units: {units.NumberOfUnits.ToString()}");
            ConsoleUtil.DisplayMessage("");

            DisplayContinuePrompt();
        }
        public Controller()
        {
            InitializeController();

            //
            // instantiate a Salesperson object
            //
            _salesperson = new Salesperson();

            //
            // instantiate a ConsoleView object
            //
            _consoleView = new ConsoleView();

            //
            // begins running the application UI
            //
            ManageApplicationLoop();
        }
        /// <summary>
        /// load account info and trvael log
        /// </summary>
        private void DisplayLoadAccountInfo()
        {
            bool maxAttemptsExceeded = false;
            bool loadAccountInfo     = false;

            if (_salesperson.AccountID == null)
            {
                loadAccountInfo = _consoleView.DisplayLoadAccountInfo(out maxAttemptsExceeded);
            }
            else
            {
                loadAccountInfo = _consoleView.DisplayLoadAccountInfo(_salesperson, out maxAttemptsExceeded);
            }

            if (loadAccountInfo && !maxAttemptsExceeded)
            {
                CsvServices csvServices = new CsvServices(DataSettings.dataFilePathCsv);

                _salesperson = csvServices.ReadSalespersonFromDataFile();

                _consoleView.DisplayConfirmLoadAccountInfo(_salesperson);
            }
        }
        /// <summary>
        /// display the current account information
        /// </summary>
        public void DisplayAccountInfo(Salesperson salesperson)
        {
            ConsoleUtil.HeaderText = "Account Info";
            ConsoleUtil.DisplayReset();

            ConsoleUtil.DisplayMessage("First Name: " + salesperson.FirstName);
            ConsoleUtil.DisplayMessage("Last Name: " + salesperson.LastName);
            ConsoleUtil.DisplayMessage("Account ID: " + salesperson.AccountID);
            ConsoleUtil.DisplayMessage("Starting City: " + salesperson.StartingCity);

            if (!salesperson.CurrentStock.OnBackorder)
            {
                ConsoleUtil.DisplayMessage("Products in Inventory: " + salesperson.CurrentStock.NumberOfUnits);
            }
            else
            {
                ConsoleUtil.DisplayMessage("Products on Backorder: " + Math.Abs(salesperson.CurrentStock.NumberOfUnits));
            }
            ConsoleUtil.DisplayMessage("Product Type: ");
            ConsoleUtil.DisplayMessage("");
            ConsoleUtil.DisplayMessage($"\t- {salesperson.CurrentStock.Type}");

            DisplayContinuePrompt();
        }
        /// <summary>
        /// display a list of the cities traveled
        /// </summary>
        public void DisplayCitiesTraveled(Salesperson salesperson)

        {
            ConsoleUtil.HeaderText = "Cities Visited";
            ConsoleUtil.DisplayReset();

            ConsoleUtil.DisplayMessage($"You began you journey in {salesperson.StartingCity}.");
            ConsoleUtil.DisplayMessage($"Since then you have traveled to the following cities:");
            ConsoleUtil.DisplayMessage("");

            if (salesperson.CitiesVisited.Count == 0)
            {
                ConsoleUtil.DisplayMessage("You have not traveled anywhere yet.");
            }
            else
            {
                foreach (string city in salesperson.CitiesVisited)
                {
                    ConsoleUtil.DisplayMessage(city);
                }
            }

            DisplayContinuePrompt();
        }
        /// <summary>
        /// allows the user to update their account information
        /// </summary>
        public Salesperson DisplayUpdateAcountInfo(Salesperson salesperson, out bool maxAttemptsExceeded)
        {
            string userResponse;
            bool   editingAccount = true;

            maxAttemptsExceeded = false;

            ConsoleUtil.HeaderText = "Update Account";
            ConsoleUtil.DisplayReset();

            ConsoleUtil.DisplayMessage("");
            ConsoleUtil.DisplayMessage(" NOTE: You cannot change the number units here. Use the Buy/Sell options \nfrom the main menu to do that.");

            DisplayContinuePrompt();

            while (editingAccount)
            {
                ConsoleUtil.HeaderText = "Update Account";
                ConsoleUtil.DisplayReset();

                //
                // displays current account info wihtout cities and number of units
                //
                #region Current Account Info

                ConsoleUtil.DisplayMessage("Current account info:");
                ConsoleUtil.DisplayMessage("");

                ConsoleUtil.DisplayMessage("First Name: " + salesperson.FirstName);
                ConsoleUtil.DisplayMessage("Last Name: " + salesperson.LastName);
                ConsoleUtil.DisplayMessage("Account ID: " + salesperson.AccountID);
                ConsoleUtil.DisplayMessage("Starting City: " + salesperson.StartingCity);
                ConsoleUtil.DisplayMessage("Product Type: " + salesperson.CurrentStock.Type);

                #endregion

                ConsoleUtil.DisplayMessage("");
                ConsoleUtil.DisplayMessage("Please select a corresonding number to change that part of your account.");
                ConsoleUtil.DisplayMessage("");

                ConsoleUtil.DisplayPromptMessage("1)First Name | 2)Last Name | 3)Account ID | 4)Starting City | 5)Product");

                ConsoleUtil.DisplayMessage("");
                ConsoleUtil.DisplayMessage("");
                ConsoleUtil.DisplayMessage("");
                ConsoleUtil.DisplayPromptMessage("Enter your choice here: ");
                userResponse = Console.ReadLine();
                ConsoleUtil.DisplayMessage("");

                //
                // get a valid answer form user
                //
                while (userResponse != "1" && userResponse != "2" && userResponse != "3" && userResponse != "4" && userResponse != "5")
                {
                    ConsoleUtil.HeaderText = "Invalid Input";
                    ConsoleUtil.DisplayReset();

                    ConsoleUtil.DisplayPromptMessage("1)First Name | 2)Last Name | 3)Account ID | 4)Starting City | 5)Product");
                    ConsoleUtil.DisplayMessage("");
                    ConsoleUtil.DisplayPromptMessage("Please enter a correct corresponding number: ");
                    userResponse = Console.ReadLine();

                    if (userResponse == "1" && userResponse == "2" && userResponse == "3" && userResponse == "4" && userResponse == "5")
                    {
                        break;
                    }
                }

                //
                // edit account info
                //
                switch (userResponse)
                {
                case "1":
                    ConsoleUtil.HeaderText = "Update First Name";
                    ConsoleUtil.DisplayReset();

                    ConsoleUtil.DisplayPromptMessage("Enter your new first name: ");
                    salesperson.FirstName = Console.ReadLine();
                    ConsoleUtil.DisplayMessage("");
                    break;

                case "2":
                    ConsoleUtil.HeaderText = "Update Last Name";
                    ConsoleUtil.DisplayReset();

                    ConsoleUtil.DisplayPromptMessage("Enter your new last name: ");
                    salesperson.LastName = Console.ReadLine();
                    ConsoleUtil.DisplayMessage("");
                    break;

                case "3":
                    ConsoleUtil.HeaderText = "Update Account ID";
                    ConsoleUtil.DisplayReset();

                    ConsoleUtil.DisplayPromptMessage("Enter your new Account ID: ");
                    salesperson.AccountID = Console.ReadLine();
                    ConsoleUtil.DisplayMessage("");
                    break;

                case "4":
                    ConsoleUtil.HeaderText = "Update Starting City";
                    ConsoleUtil.DisplayReset();

                    ConsoleUtil.DisplayPromptMessage("Enter your new starting city: ");
                    salesperson.StartingCity = Console.ReadLine();
                    ConsoleUtil.DisplayMessage("");
                    break;

                case "5":
                    ConsoleUtil.HeaderText = "Update Product Type";
                    ConsoleUtil.DisplayReset();

                    Product.ProductType productType;

                    ConsoleUtil.DisplayMessage("");
                    ConsoleUtil.DisplayPromptMessage("Enter you new product selection: ");

                    //
                    // get new product type from user
                    //
                    if (Enum.TryParse <Product.ProductType>(UppercaseFirst(Console.ReadLine()), out productType))
                    {
                        salesperson.CurrentStock.Type = productType;
                    }
                    else
                    {
                        ConsoleUtil.DisplayReset();
                        ConsoleUtil.DisplayMessage("Seems like you entered an invalid product type.");
                        ConsoleUtil.DisplayMessage("By default, your product type has been set to None.");
                        salesperson.CurrentStock.Type = Product.ProductType.None;
                        DisplayContinuePrompt();
                    }
                    break;

                default:
                    break;
                }
                ConsoleUtil.HeaderText = "Update Account";
                ConsoleUtil.DisplayReset();
                ConsoleUtil.DisplayMessage("Your account has been updated!");
                ConsoleUtil.DisplayMessage("");
                userResponse = ConsoleValidator.GetYesNoFromUser(MAXIMUM_ATTEMPTS, "\tWould you like to make more changes or continue on?", out maxAttemptsExceeded);

                if (maxAttemptsExceeded)
                {
                    ConsoleUtil.DisplayMessage("Max attempts exceeded! You will now be returned to the main menu.");
                    return(salesperson);
                }
                else if (userResponse.ToUpper() == "YES")
                {
                    editingAccount = true;
                }
                else
                {
                    editingAccount = false;
                    return(salesperson);
                }
            }
            return(salesperson);
        }
        /// <summary>
        /// setup the new salesperson object with the initial data
        /// Note: To maintain the pattern of only the Controller changing the data this method should
        ///       return a Salesperson object with the initial data to the controller. For simplicity in
        ///       this demo, the ConsoleView object is allowed to access the Salesperson object's properties.
        /// </summary>
        public Salesperson DisplaySetupAccount()
        {
            Salesperson salesperson = new Salesperson();

            Product.ProductType productType;
            int numberOfUnits;

            ConsoleUtil.HeaderText = "Account Setup";
            ConsoleUtil.DisplayReset();

            ConsoleUtil.DisplayMessage("Setup your account now.");
            ConsoleUtil.DisplayMessage("");

            ConsoleUtil.DisplayPromptMessage("Enter your first name: ");
            salesperson.FirstName = Console.ReadLine();
            ConsoleUtil.DisplayMessage("");

            ConsoleUtil.DisplayPromptMessage("Enter your last name: ");
            salesperson.LastName = Console.ReadLine();
            ConsoleUtil.DisplayMessage("");

            ConsoleUtil.DisplayPromptMessage("Enter your account ID: ");
            salesperson.AccountID = Console.ReadLine();
            ConsoleUtil.DisplayMessage("");

            ConsoleUtil.DisplayPromptMessage("Enter your Starting City: ");
            salesperson.StartingCity = Console.ReadLine();
            ConsoleUtil.DisplayMessage("");

            ConsoleUtil.HeaderText = "Account Setup";
            ConsoleUtil.DisplayReset();

            ConsoleUtil.DisplayMessage("Please select which type of product you want to work with from below.");
            ConsoleUtil.DisplayMessage("");

            ConsoleUtil.DisplayMessage("Product Types:");
            ConsoleUtil.DisplayMessage("");

            Console.Write(
                "\t- Gilded" + Environment.NewLine +
                "\t- Spiked" + Environment.NewLine +
                "\t- Colorful" + Environment.NewLine +
                "\t- Vintage" + Environment.NewLine +
                "\t- Striped" + Environment.NewLine +
                "\t- Used" + Environment.NewLine);

            ConsoleUtil.DisplayMessage("");
            ConsoleUtil.DisplayPromptMessage("Enter product selection: ");

            //
            // get product type from user
            //
            if (Enum.TryParse <Product.ProductType>(UppercaseFirst(Console.ReadLine()), out productType))
            {
                salesperson.CurrentStock.Type = productType;
            }
            else
            {
                ConsoleUtil.DisplayReset();
                ConsoleUtil.DisplayMessage("Seems like you entered an invalid product type.");
                ConsoleUtil.DisplayMessage("By default, your product type has been set to None.");
                salesperson.CurrentStock.Type = Product.ProductType.None;
                DisplayContinuePrompt();
            }

            //
            // get number of products in inventory
            //
            ConsoleUtil.DisplayReset();
            ConsoleUtil.DisplayMessage($"You have selected {productType} as your product type.");

            if (ConsoleValidator.TryGetIntegerFromUser(MINIMUM_BUYSELL_AMOUNT, MAXIMUM_BUYSELL_AMOUNT, MAXIMUM_ATTEMPTS, $"{productType} products to add to your inventory", out numberOfUnits))
            {
                ConsoleUtil.DisplayReset();
                salesperson.CurrentStock.AddProducts(numberOfUnits);
                ConsoleUtil.DisplayMessage($"Thank you! {numberOfUnits} {productType} products are now in your inventory!");
                DisplayContinuePrompt();
            }
            else
            {
                ConsoleUtil.DisplayReset();
                ConsoleUtil.DisplayMessage("Maximum attempts exceeded!");
                ConsoleUtil.DisplayMessage($"By default, the number of {productType} products in your inventory are now set to zero.");
                salesperson.CurrentStock.AddProducts(0);
                DisplayContinuePrompt();
            }

            ConsoleUtil.DisplayReset();

            ConsoleUtil.DisplayMessage("Your account is now setup!");

            DisplayContinuePrompt();

            return(salesperson);
        }
        /// <summary>
        /// reads data from Data.csv into a Salesperson object, then returns that object
        /// </summary>
        public Salesperson ReadSalespersonFromDataFile()
        {
            Salesperson salesperson = new Salesperson();

            Product.ProductType productType = new Product.ProductType();

            string salespersonInfo;

            string[] salespersonInfoArray = new string[7];
            string   citiesTraveled;

            //
            // initialize a FileStream object for writing
            //
            FileStream rFileStream = File.OpenRead(DataSettings.dataFilePathCsv);

            //
            // wrap the FileStream object in a using statement the ensure of the dispose
            //
            using (rFileStream)
            {
                // wrap the FileStream object in a StreamWriter object to simplify wrting strings\
                StreamReader sReader = new StreamReader(rFileStream);

                using (sReader)
                {
                    salespersonInfo = sReader.ReadLine();
                    citiesTraveled  = sReader.ReadLine();
                }
            }

            //
            // convert and write data to salesperson object
            //
            salespersonInfoArray     = salespersonInfo.Split(',');
            salesperson.FirstName    = salespersonInfoArray[0];
            salesperson.LastName     = salespersonInfoArray[1];
            salesperson.AccountID    = salespersonInfoArray[2];
            salesperson.StartingCity = salespersonInfoArray[3];

            if (!Enum.TryParse <Product.ProductType>(salespersonInfoArray[4], out productType))
            {
                productType = Product.ProductType.None;
            }
            salesperson.CurrentStock.Type = productType;

            salesperson.CurrentStock.AddProducts(Convert.ToInt32(salespersonInfoArray[5]));
            salesperson.CurrentStock.OnBackorder = Convert.ToBoolean(salespersonInfoArray[6]);

            //
            // if citiesTraveled is null, then ignore
            //
            if (citiesTraveled == null)
            {
                return(salesperson);
            }
            else
            {
                salesperson.CitiesVisited = citiesTraveled.Split(',').ToList();
            }

            return(salesperson);
        }
        /// <summary>
        /// writes data from the Salesperson object into the Data.csv file
        /// </summary>
        public void WriteSalespersonToDataFile(Salesperson salesperson)
        {
            string salespersonData;
            char   delineator = ',';

            StringBuilder sb = new StringBuilder();

            sb.Clear();
            sb.Append(salesperson.FirstName + delineator);
            sb.Append(salesperson.LastName + delineator);
            sb.Append(salesperson.AccountID + delineator);
            sb.Append(salesperson.StartingCity + delineator);
            sb.Append(salesperson.CurrentStock.Type.ToString() + delineator);
            sb.Append(salesperson.CurrentStock.NumberOfUnits.ToString() + delineator);
            sb.Append(salesperson.CurrentStock.OnBackorder.ToString());
            sb.Append(Environment.NewLine);

            //
            // add cities traveled to sb
            //
            foreach (string city in salesperson.CitiesVisited)
            {
                sb.Append(city + delineator);
            }

            //
            // remove the last delineator
            //
            if (sb.Length != 0)
            {
                sb.Length--;
            }

            //
            // convert StringBuilder object to a string
            //
            salespersonData = sb.ToString();

            try
            {
                using (StreamWriter sWriter = new StreamWriter(DataSettings.dataFilePathCsv, false))
                {
                    sWriter.Write(salespersonData);
                }
            }
            catch (System.IO.DirectoryNotFoundException)
            {
                //
                // create a directory if one is not already present
                //
                Directory.CreateDirectory("Data");

                using (StreamWriter sWriter = new StreamWriter(DataSettings.dataFilePathCsv, false))
                {
                    sWriter.Write(salespersonData);
                }
            }
            finally
            {
            }
        }
        /// <summary>
        /// update account
        /// </summary>
        private void DisplayUpdateAccount()
        {
            bool maxAttemptsExceeded = false;

            _salesperson = _consoleView.DisplayUpdateAcountInfo(_salesperson, out maxAttemptsExceeded);
        }
 /// <summary>
 /// setup account
 /// </summary>
 private void DisplaySetupAccount()
 {
     _salesperson = _consoleView.DisplaySetupAccount();
 }