public static void Main()
        {
            IUsersRepository usersRepository = new UsersRepository();
            IRepository<Course> courseRepository = new Repository<Course>();
            IBangaloreUniversityDatebase database = new BangaloreUniversityDatebase(usersRepository, courseRepository);

            var engine = new BangaloreUniversityEngine(database);

            engine.Run();
        }
        /// <summary>
        /// Retrieves the TopTenClients
        /// Level: Data
        /// </summary>
        /// <returns>A collection of type TopTenClients</returns>
        public IQueryable<TopTenClients> RetrieveTopTenClients()
        {
            try
            {
                List<TopTenClients> myTopTen = new List<TopTenClients>();

                List<OrderProduct> myOrderItems = Entities.OrderProducts.ToList();

                foreach (OrderProduct myCurrentOrderItem in myOrderItems)
                {
                    if (myCurrentOrderItem.Order.SupplierFK == null)
                    {
                        if (myTopTen.SingleOrDefault(c => c.ClientID == myCurrentOrderItem.Order.UserFK) != null)
                        {
                            TopTenClients myTopTenClients = myTopTen.SingleOrDefault(c => c.ClientID == myCurrentOrderItem.Order.UserFK);

                            myTopTenClients.ProductCount += myCurrentOrderItem.Quantity;
                        }
                        else
                        {
                            TopTenClients myTopTenClients = new TopTenClients();
                            User myUser = new UsersRepository().RetrieveUserById(Guid.Parse(myCurrentOrderItem.Order.UserFK.ToString()));

                            myTopTenClients.ClientID = Guid.Parse(myCurrentOrderItem.Order.UserFK.ToString());
                            myTopTenClients.ClientName = myUser.Name + " " + myUser.Surname;
                            myTopTenClients.ProductCount += myCurrentOrderItem.Quantity;

                            myTopTen.Add(myTopTenClients);
                        }
                    }
                }

                myTopTen.Sort((x, y) => y.ProductCount.CompareTo(x.ProductCount));

                return myTopTen.AsQueryable();
            }
            catch (Exception Exception)
            {
                throw Exception;
            }
        }
        /// <summary>
        /// Retrieves a User's Orders
        /// Level: Data
        /// </summary>
        /// <param name="Username">The User's Username</param>
        /// <returns>A collection of type UserOrdersView</returns>
        public IQueryable<UserOrdersView> RetrieveOrdersByUsername(string Username)
        {
            try
            {
                User myUser = new UsersRepository().RetrieveUserByUsername(Username);
                List<UserOrdersView> myOrderListViews = new List<UserOrdersView>();

                if (myUser != null)
                {
                    List<Order> myOrderList = Entities.Orders.Where(o => o.UserFK == myUser.Id).ToList();

                    foreach (Order myCurrentOrder in myOrderList)
                    {
                        UserOrdersView myOrdersView = new UserOrdersView();

                        myOrdersView.Id = myCurrentOrder.Id;
                        myOrdersView.OrderDate = myCurrentOrder.OrderDate.ToShortDateString();
                        myOrdersView.OrderStatus = RetrieveOrderStatusByID(myCurrentOrder.OrderStatusFK).Status;
                        myOrdersView.Username = new UsersRepository().RetrieveUserById(Guid.Parse(myCurrentOrder.UserFK.ToString())).UserDetail.Username;

                        myOrderListViews.Add(myOrdersView);
                    }
                }

                return myOrderListViews.AsQueryable<UserOrdersView>();
            }
            catch (Exception Exception)
            {
                throw Exception;
            }
        }
        /// <summary>
        /// Adds an Order
        /// Level: Logic
        /// </summary>
        /// <param name="SupplierFK">Supplier ID</param>
        /// <param name="UserFK">User ID</param>
        /// <param name="myOrderItems">Collection of Order Items</param>
        /// <returns>True if successful false if not successful</returns>
        public bool AddOrder(int? SupplierFK, Guid? UserFK, string CreditCard, List<OrderItem> myOrderItems)
        {
            DbTransaction myTransaction = null;
            OrdersRepository myRepository = new OrdersRepository();

            myRepository.Entities.Connection.Open();

            using (myTransaction = myRepository.Entities.Connection.BeginTransaction())
            {
                try
                {
                    Order myOrder = new Order();

                    myOrder.Id = Guid.NewGuid();
                    myOrder.OrderDate = DateTime.Now;
                    myOrder.OrderStatusFK = myRepository.RetrieveStatusByName("Ordered").Id;
                    myOrder.UserFK = UserFK;
                    myOrder.SupplierFK = SupplierFK;

                    myRepository.AddOrder(myOrder);

                    if (SupplierFK != null)
                    {
                        myRepository.AddOrderItems(myOrder.Id, myOrderItems);

                        myTransaction.Commit();

                        myRepository.Entities.Connection.Close();

                        return true;
                    }
                    else
                    {
                        if (myRepository.AddUserOrderItems(myOrder.Id, myOrderItems)) // if mismatch occurs for quantity rollback
                        {
                            myTransaction.Rollback();

                            myRepository.Entities.Connection.Close();

                            return false;
                        }
                        else //else commit changes
                        {
                            myTransaction.Commit();

                            new UsersLogic().InsertCreditCardNumber(CreditCard, Guid.Parse(UserFK.ToString()));

                            new ShoppingCartLogic().EmptyCart(Guid.Parse(UserFK.ToString()));

                            User myUser = new UsersRepository().RetrieveUserById(Guid.Parse(UserFK.ToString()));
                            new Mailing().PurchaseMail(myUser.UserDetail.Username, myUser.Email, myOrder.Id.ToString(), "*****@*****.**");

                            myRepository.Entities.Connection.Close();

                            return true;
                        }
                    }
                }
                catch (Exception Exception)
                {
                    if (myTransaction != null)
                    {
                        myTransaction.Rollback();
                    }

                    if (myRepository != null)
                    {
                        myRepository.Entities.Connection.Close();
                    }

                    throw Exception;
                }
            }
        }
        /// <summary>
        /// Inserts the Users Credit Card Number
        /// Level: Data
        /// </summary>
        /// <param name="CreditCard">The Credit Cart Number</param>
        /// <param name="UserID">The User ID</param>
        public void InsertCreditCardNumber(string CreditCard, Guid UserID)
        {
            try
            {
                User myUser = new UsersRepository().RetrieveUserById(UserID);
                UserDetail myUserDetail = Entities.UserDetails.SingleOrDefault(d => d.Id == myUser.UserDetailsFK);

                myUserDetail.CreditCardNumber = CreditCard;

                Entities.SaveChanges();
            }
            catch (Exception Exception)
            {
                throw Exception;
            }
        }
        /// <summary>
        /// Retrieves a Users Shopping Cart Total
        /// Level: Data
        /// </summary>
        /// <param name="UserID">The User ID</param>
        /// <returns>The Shopping Cart Total Price</returns>
        public double RetrieveCartTotal(Guid UserID)
        {
            try
            {
                IQueryable<ShoppingCart> myUserCart = RetrieveAllShoppingCartItems(UserID);

                User myUser = new UsersRepository().RetrieveUserById(UserID);

                double TotalPrice = 0;

                foreach (ShoppingCart myShoppingCartItem in myUserCart)
                {
                    UserTypeProduct myPriceType = new PriceTypesRepository().RetrievePriceTypeByID(myUser.UserTypeFK, myShoppingCartItem.ProductFK);

                    if ((DateTime.Now >= myPriceType.DiscountDateFrom) && (DateTime.Now <= myPriceType.DiscountDateTo))
                    {
                        TotalPrice += Convert.ToDouble(myPriceType.Price - ((myPriceType.DiscountPercentage / 100) * myPriceType.Price)) * myShoppingCartItem.Quantity;
                    }
                    else
                    {
                        TotalPrice += myPriceType.Price * myShoppingCartItem.Quantity;
                    }
                }

                return TotalPrice;
            }
            catch (Exception Exception)
            {
                throw Exception;
            }
        }
        /// <summary>
        /// Retrieves all Shopping Cart Items for User
        /// Level: Data
        /// </summary>
        /// <param name="UserID">The User ID</param>
        /// <returns>A collection of type ShoppingCart</returns>
        public IQueryable<ShoppingCart> RetrieveAllShoppingCartItems(Guid UserID)
        {
            try
            {
                User myUser = new UsersRepository().RetrieveUserById(UserID);

                IQueryable<UserTypeProduct> myUserTypeProducts = Entities.UserTypeProducts.Where(up => up.UserType.Id == myUser.UserTypeFK);
                IQueryable<ShoppingCart> myShoppingCartItems = null;

                myShoppingCartItems = Entities.ShoppingCarts.Where(sc => sc.UserFK == UserID && sc.Product.Status == true);

                List<ShoppingCart> myShoppingCartItemsList = myShoppingCartItems.ToList();

                foreach (ShoppingCart myCurrentItem in myShoppingCartItems)
                {
                    if (myUserTypeProducts.SingleOrDefault(t => t.Product.Id == myCurrentItem.ProductFK) == null)
                    {
                        myShoppingCartItemsList.Remove(myCurrentItem);
                    }
                }

                return myShoppingCartItemsList.AsQueryable();

                //return Entities.ShoppingCarts.Where(sc => sc.UserFK == UserID && sc.Product.Status == true);
            }
            catch (Exception Exception)
            {
                throw Exception;
            }
        }
        /// <summary>
        /// De Allocates a Role from a User
        /// Level: Logic
        /// </summary>
        /// <param name="Email">The Email</param>
        /// <param name="RoleID">The RoleID</param>
        /// <returns></returns>
        public UserDeAllocate DeAllocateRole(string Email, int RoleID)
        {
            try
            {
                RolesRepository myRolesRepository = new RolesRepository();

                Role myRole = myRolesRepository.RetrieveRoleByID(RoleID);

                //check if deallocation being done on admin
                if (myRolesRepository.RetrieveRoleByName("Administrator") != myRole)
                {
                    if (myRolesRepository.RetrieveRoleByName("User") != myRole)
                    {
                        new UsersRepository().DeAllocateRole(Email, myRole);
                        return UserDeAllocate.Successful;
                    }
                    else
                    {
                        UsersRepository myUsersRepository = new UsersRepository();

                        if (myUsersRepository.UserIsAdmin(Email))
                        {
                            new UsersRepository().DeAllocateRole(Email, myRole);
                            return UserDeAllocate.Successful;
                        }
                        else
                        {
                            return UserDeAllocate.OnlyUser;
                        }
                    }
                }
                else
                {
                    return UserDeAllocate.UserIsAdmin;
                }
            }
            catch (Exception Exception)
            {
                throw Exception;
            }
        }
        /// <summary>
        /// Finalises user signup
        /// Level: Logic
        /// </summary>
        /// <param name="Name">The Name</param>
        /// <param name="Surname">The Surname</param>
        /// <param name="DateOfBirth">The Date of Birth</param>
        /// <param name="Address">The Address</param>
        /// <param name="Email">The Email</param>
        /// <param name="Town">The Town</param>
        /// <param name="Postcode">The Postcode</param>
        /// <param name="Country">The Country</param>
        /// <param name="Username">The Username</param>
        /// <param name="Password">The Password</param>
        /// <returns>UserSignupEnum</returns>
        public UserSignup FinalizeSignUp(string Name, string Surname, DateTime DateOfBirth, string Address, string Email, string Town,
            string Postcode, string Country, string Username, string Password)
        {
            try
            {
                UsersRepository myRepository = new UsersRepository(false);

                try
                {
                    //Checking if Username Exists
                    if ((myRepository.UsernameExists(Username)) && (myRepository.EmailExists(Email)))
                    {
                        return UserSignup.UsernameAndEmailExist;
                    }
                    else if (myRepository.UsernameExists(Username))
                    {
                        return UserSignup.UsernameExists;
                    }
                    else if (myRepository.EmailExists(Email))
                    {
                        return UserSignup.EmailExists;
                    }
                    else
                    {
                        //Instanciating User
                        User myUser = new User();

                        myUser.Id = Guid.NewGuid();
                        myUser.Name = Name;
                        myUser.Surname = Surname;
                        myUser.DateOfBirth = DateOfBirth;
                        myUser.StreetAddress = Address;
                        myUser.Postcode = Postcode;
                        myUser.Email = Email;

                        //Retrieving UserType
                        myUser.UserType = myRepository.RetrieveUserTypeByName("Retailer");

                        //Retrieving Possible Same Town
                        Town myTown = myRepository.RetrieveTown(Town, Country);

                        //If Town Exists
                        if (myTown != null)
                        {
                            //Assigning Existent Town to User
                            myUser.Town = myTown;
                        }
                        else
                        {
                            //Instanciating New Town
                            myTown = new Town();
                            myTown.Town1 = Town;
                            myTown.Country = myRepository.RetrieveCountry(Country);

                            //Assigning New Town to User
                            myUser.Town = myTown;
                        }

                        //Instanciating User Details
                        UserDetail myUserDetails = new UserDetail();

                        myUserDetails.Id = Guid.NewGuid();
                        myUserDetails.Username = Username;
                        myUserDetails.Password = Password;

                        //Assigning User Details to User
                        myUser.UserDetail = myUserDetails;

                        //Assigning User Role to User
                        myUser.Roles.Add(myRepository.RetrieveRoleByName("User"));

                        //Saving Changes
                        myRepository.FinalizeSignUp(myUser);

                        //Returning Successful
                        return UserSignup.Successful;
                    }
                }
                catch (Exception Exception)
                {
                    //Throwing Exception
                    throw Exception;
                }
            }
            catch (Exception Exception)
            {
                throw Exception;
            }
        }