#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <ctime>
#include <limits>
#include <vector>
#include <numeric>
using namespace std;

class Menu
{
    public:
        void mainMenu()
        {
            cout<<"Please choose the directory that you wish to go\n"<<endl;
            cout<<"1. Meat Section\n2. Vegetable Section\n3. Beverages Section\n4. Snack\n5. Daily Supply\n6. Proceed with payment\n7. Item List"<<endl;
            cout<<"\nChoice : ";
        }
        void booting()
        {
        	cout<<"==================================================================="<<endl;
        	cout<<"|\t\tWelcome to farm Grocer by Ferma.Inc !\t\t  |"<<endl;
    		cout<<"|\t\t   Are you a member of our store?\t\t  |"<<endl;
    		cout<<"|Member login - 1\t\t\t\t\t\t  |"<<endl;
    		cout<<"|Non-member - 2\t\t\t\t\t\t\t  |"<<endl;
    		cout<<"|Please enter the number according above, thank you :D\t\t  |"<<endl;
    		cout<<"==================================================================="<<endl;
    		cout<<"\n Enter: ";
		}
		void success()
		{
			cout<<"Item Successfully added, please check your item list on the main menu !\n\n";
			system("pause");
			system("cls");
		}
};
class Person
{
    protected:
        string name;
    public:
        Person(string n)
        {
            name = n;
        }
        string getName() const { return name; }
};
class Cashier : public Person
{
    private:
        int cashierID;
    public:
        Cashier(string n, int id) : Person (n)
        {
            cashierID=id;
        }            
        int getCashier()
        {
            return cashierID;
        }
        void display()
        {
            cout<<name<<", "<<cashierID;
        }
};
class Customer : public Person
{
    private:
        int memberID, reply;
        string phoneNum;
    public:
        Customer(int mid, string n, string pn) : Person (n)
        {
            memberID=mid;
            phoneNum=pn;
        }
        int getMemberID()
        {
            return memberID;
        }
        string getPhoneNum()
        {
            return phoneNum;
        }
        void display(int reply)
        {
            if (reply==1)
            {
                cout << "Please enter your member id : ";
				cin >> memberID;
				cout << "Please enter your name: ";
				cin.ignore();
				getline(cin,name);
				cout << "Please enter your phone number: ";
				cin >> phoneNum;
				system("pause");
				system("cls");
            }
            else if(reply==2)
			{
				cout << "Not member" << endl << endl;
				name = "------------";
				system("pause");
				system("cls");
			}
			else
			{
				cout << "Invalid input! Try again." << endl;
				exit(0);
			}
        }       
};
class Payment
{
    private:
        int payMethod;
        Customer custDetails;
    public:
        Payment(int mid, string n, string pn, int m) : custDetails(mid,n,pn)
		{
			payMethod = m;
		}
		void setMethod(int m)
		{
			payMethod = m;
		}
		string getMethod()
		{
			string method;
			//let customer choose payment method
			switch(payMethod)
			{
				case 1: method = "Cash";
						break;
				case 2: method = "Debit card";
						break;
				case 3: method = "Visa pay wave";
						break;
				case 4: method = "Credit card";
						break;
			}
			return method;
		}
		double getChange(double totalPay, double totalP)
		{
			if(payMethod==1)
			{
				cout << "Change: RM " << (totalPay-totalP) << endl << endl;
			}
		}
		void display(int mid)
		{
			if(mid!=0)
			{
				cout << "Payment made by: " << custDetails.getName() << endl;
			}
			cout << "Pay with: " << getMethod() << endl;
		}
};
int displayPaymentOption()
{
	int m;
	
	PaymentSelection:
	cout << "\nPlease select your payment method: \n\n";
	cout << "1. Cash\n";
	cout << "2. Debit card\n";
	cout << "3. Visa pay wave\n";
	cout << "4. Credit card\n\n";
	
	cout << "Please input integer number only (1-4): ";
	cin >> m;
	
	if(m<1 || m>4) //Validate input
	{
		cout << "\nInvalid payment method has been entered!\n";
		cout << "Please enter 1-4 only. Thanks.\n";
		goto PaymentSelection;
	}

	return m;
}
class Items
{
    protected:
        string item;
        double price, total;
        int stock;
    public:
        Items(){item="", price=0.00, stock=0, total=0;}
        Items(string i, double p, int s, double t)
        {
            item=i;
            price=p;
            stock=s;
            total=t;
        }
        string getItem(){return item;}
        double getPrice()const{return price;}
        int getStock(){return stock;}
        double getTotal(){return total;}
        virtual void getMany(double m){total=price*m;}
		virtual void rStock(double m){stock=stock-m;}
};
class Meat: public Items
{
    public:
        Meat(){}
        Meat(string i, double p, int s, double t):Items(i, p, s, t){}
        void getMany(double m){total=price*m;}
		void rStock(double m){stock=stock-m;}
};
class Vegetable: public Items
{
    public:
        Vegetable(){}
        Vegetable(string i, double p, int s, double t):Items(i, p, s, t){}
        void getMany(double m){total=price*m;}
		void rStock(double m){stock=stock-m;}
};
class Beverage: public Items
{
    public:
        Beverage(){}
        Beverage(string i, double p, int s, double t):Items(i, p, s, t){}
        void getMany(double m){total=price*m;}
		void rStock(double m){stock=stock-m;}
};
class Snack: public Items
{
    public:
        Snack(){}
        Snack(string i, double p, int s, double t):Items(i, p, s, t){}
        void getMany(double m){total=price*m;}
		void rStock(double m){stock=stock-m;}
};
class Daily_Supply: public Items
{
    public:
        Daily_Supply(){}
        Daily_Supply(string i, double p, int s, double t):Items(i, p, s, t){}
        void getMany(double m){total=price*m;}
		void rStock(double m){stock=stock-m;}
};
class Receipt
{
	private:
		int quantity;
		double total, discount;
		Items *purchase;
		Cashier *cashier;
		Customer *customer;
	public:
		Receipt(){quantity=0, purchase=0;}
		double getDiscount(double total, int m)
		{
			if(total>=50.00 && total<=100.00 && m==1)
			{
				discount = 10.00;
			}
			if(total>100.00 && total<=300.00 && m==1)
			{
				discount = 30.00;
			}
			if(total>300.00 && m==1)
			{
				discount = 50.00;
			}
			else if(total<50.00)
			{
				discount = 0.00;
			}
			return discount;
		}
};

int main()
{
    int reply, memberID, A;
    string nm, phn;
    vector<string>list;
    vector<double>pricelist;
	vector<int>purchaselist;

	//Create Cashier object
    Cashier cash("Alisya", 0523);
    //Create Customer object
    Customer cust1(memberID, nm, phn);
    //Create Menu object
	Menu main;
	main.booting();
    cin>>reply;
    cout<<endl;
    cust1.display(reply);

    Meat meat[4]{Meat("Beef", 12.50, 20, 0.00),
                 Meat("Chicken", 10.00, 15, 0.00),
                 Meat("Lamb", 20.00, 10, 0.00),
                 Meat("Fish", 10.00 , 15, 0.00)};
    Vegetable vegy[4]{Vegetable("Cabbage", 5.00, 15, 0.00),
                 Vegetable("Carrot", 2.50, 20, 0.00),
                 Vegetable("Broccoli", 1.50, 20, 0.00),
                 Vegetable("Green Pepper", 2.50, 20, 0.00)};
    Beverage beve[4]{Beverage("Fanta", 2.00, 30, 0.00),
					  Beverage("Pepsi", 2.50, 30, 0.00),
					  Beverage("Mineral Water", 1.00, 30, 0.00),
					  Beverage("Capricon Sun", 2.00, 30, 0.00)};
	Snack snack[4]{Snack("Mamee Monster", 1.50, 100, 0.00),
					Snack("Mr Potato", 4.50, 70, 0.00),
					Snack("Super Ring", 2.00, 50, 0.00),
					Snack("Snickers", 4.00, 30, 0.00)};
	Daily_Supply daily[4]{	Daily_Supply{"Shampoo", 10.0, 30, 0.00},
							Daily_Supply("Toothpaste", 3.00, 25, 0.00),
							Daily_Supply("Bodywash", 8.00, 20, 0.00),
							Daily_Supply("Hand Sanitizer", 2.00, 100, 0.00)};
    
    cout<<setprecision(2)<<showpoint<<fixed;
    int m1, m2, m3, m4, m5, m6;
    int choice1, choice2, choice3, choice4, choice5;
    double num1,num2,num3,num4,num5;

    //Main menu section
    MainMenu:
    main.mainMenu();
    cin>>m1;
    system("cls");
    if(m1==1){goto MeatList;}
    if(m1==2){goto Vegetable;}
    if(m1==3){goto Beverages;}
    if(m1==4){goto Snack;}
    if(m1==5){goto Daily;}
    if(m1==6){goto Pay;}
    if(m1==7){goto Item;}
    if(m1<1||m1>7){goto MainMenu;}

    //Meat directory------------------------------------------------------------------------------------------------------
	MeatList:
	cout << "\nHere is our meat list: \n\n";
	cout <<left<< setw(18)<<"Meat"<< setw(10)<<"Price"<<setw(7)<<"Stock"<<endl;
	for(int i=0; i<4; i++)
	{
	    cout<<""<<i+1<<". "<<left<<setw(15)<<meat[i].getItem()<<setw(10)<<meat[i].getPrice()<<setw(8)<<meat[i].getStock()<<endl;;
	}
	cout << "\nPlease kindly input the integer number of the meat you wanted to purchase, press 5 to skip this option: ";
	cin >> m2;
	if (m2<1 || m2>5) //Validate input
	{
		cout << "\nInvalid number has been entered. Please enter only 1-5!\n\n";
		goto MeatList;
    }
    if(m2==5)
    {
    	system("cls");
    	goto MainMenu;
	}
    //Select number of items
    cout<<"How many would you want? : ";
    cin>>num1;
    if(num1>meat[m2-1].getStock())
    {
    	cout<<"\nImpossible request :: Purchase beyond the stock available \n\n"<<endl;
    	system("pause");
    	system("cls");
    	goto MeatList;
	}
	list.push_back(meat[m2-1].getItem());
    meat[m2-1].getMany(num1);
    pricelist.push_back(meat[m2-1].getTotal());
    meat[m2-1].rStock(num1);
	purchaselist.push_back(num1);
	main.success();
    goto MainMenu;
    //----------------------------------------------------------------------------------------------------------------------
    //Vegetable directory------------------------------------------------------------------------------------------------------
	Vegetable:
	cout << "\nHere is our Vegetable list: \n\n";
	cout << setw(18)<<"Vegetables"<< setw(10)<<"Price"<<setw(8)<<"Stock"<<endl;
	for(int i=0; i<4; i++)
	{
	    cout<<""<<i+1<<". "<<left<<setw(15)<<vegy[i].getItem()<<setw(12)<<vegy[i].getPrice()<<setw(8)<<vegy[i].getStock()<<endl;;
	}
	cout << "\nPlease kindly input the integer number of the vegetable you wanted to purchase, press 5 to skip this option: ";
	cin >> m3;
	if (m3<1 || m3>5) //Validate input
	{
		cout << "\nInvalid number has been entered. Please enter only 1-5!\n\n";
		goto Vegetable;
    }
    if(m3==5)
    {
    	system("cls");
    	goto MainMenu;
	}
	
    //Select number of items
    cout<<"How many would you want? : ";
    cin>>num2;
    if(num2>vegy[m3-1].getStock())
    {
    	cout<<"\nImpossible request :: Purchase beyond the stock available \n\n"<<endl;
    	system("pause");
    	system("cls");
    	goto Vegetable;
	}
	list.push_back(vegy[m3-1].getItem());
    vegy[m3-1].getMany(num2);
    pricelist.push_back(vegy[m3-1].getTotal());
    vegy[m3-1].rStock(num2);
	purchaselist.push_back(num2);
	main.success();
    goto MainMenu;
    //----------------------------------------------------------------------------------------------------------------------
    //Beverages directory------------------------------------------------------------------------------------------------------
	Beverages:
	cout << "\nHere is our Beverages list: \n\n";
	cout << setw(18)<<"Beverages"<< setw(11)<<"Price"<<setw(8)<<"Stock"<<endl;
	for(int i=0; i<4; i++)
	{
	    cout<<""<<i+1<<". "<<left<<setw(15)<<beve[i].getItem()<<setw(12)<<beve[i].getPrice()<<setw(8)<<beve[i].getStock()<<endl;;
	}
	cout << "\nPlease kindly input the integer number of the beverages you wanted to purchase, press 5 to skip this option: ";
	cin >> m4;
	if (m4<1 || m4>5) //Validate input
	{
		cout << "\nInvalid number has been entered. Please enter only 1-5!\n\n";
		goto Beverages;
    }
    if(m4==5)
    {
    	system("cls");
    	goto MainMenu;
	}
    //Select number of items
    cout<<"How many would you want? : ";
    cin>>num3;
    if(num3>beve[m4-1].getStock())
    {
    	cout<<"\nImpossible request :: Purchase beyond the stock available \n\n"<<endl;
    	system("pause");
    	system("cls");
    	goto Beverages;
	}
	list.push_back(beve[m4-1].getItem());
    beve[m4-1].getMany(num3);
    pricelist.push_back(beve[m4-1].getTotal());
    beve[m4-1].rStock(num3);
	purchaselist.push_back(num3);
	main.success();
    goto MainMenu;
    //----------------------------------------------------------------------------------------------------------------------
    //Snack directory------------------------------------------------------------------------------------------------------
	Snack:
	cout << "\nHere is our Snack list: \n\n";
	cout << setw(19)<<"Snack"<< setw(10)<<"Price"<<setw(8)<<"Stock"<<endl;
	for(int i=0; i<4; i++)
	{
	    cout<<""<<i+1<<". "<<left<<setw(16)<<snack[i].getItem()<<setw(10)<<snack[i].getPrice()<<setw(8)<<snack[i].getStock()<<endl;;
	}
	cout << "\nPlease kindly input the integer number of the snack you wanted to purchase, press 5 to skip this option: ";
	cin >> m5;
	if (m5<1 || m5>5) //Validate input
	{
		cout << "\nInvalid number has been entered. Please enter only 1-5!\n\n";
		goto Snack;
    }
    if(m5==5)
    {
    	system("cls");
    	goto MainMenu;
	}
    //Select number of items
    cout<<"How many would you want? : ";
    cin>>num4;
    if(num4>snack[m5-1].getStock())
    {
    	cout<<"\nImpossible request :: Purchase beyond the stock available \n\n"<<endl;
    	system("pause");
    	system("cls");
    	goto Snack;
	}
	list.push_back(snack[m5-1].getItem());
    snack[m5-1].getMany(num4);
    pricelist.push_back(snack[m5-1].getTotal());
    snack[m5-1].rStock(num4);
	purchaselist.push_back(num4);
	main.success();
    goto MainMenu;
    //----------------------------------------------------------------------------------------------------------------------
    //Daily supply directory------------------------------------------------------------------------------------------------------
	Daily:
	cout << "\nHere is our Daily Supply list: \n\n";
	cout << setw(18) <<"Daily Supply"<< setw(9)<<"Price"<<setw(7)<<"Stock"<<endl;
	for(int i=0; i<4; i++)
	{
	    cout<<""<<i+1<<". "<<left<<setw(15)<<daily[i].getItem()<<setw(10)<<daily[i].getPrice()<<setw(8)<<daily[i].getStock()<<endl;;
	}
	cout << "\nPlease kindly input the integer number of the daily supply you wanted to purchase, press 5 to skip this option: ";
	cin >> m6;
	if (m6<1 || m6>5) //Validate input
	{
		cout << "\nInvalid number has been entered. Please enter only 1-5!\n\n";
		goto Daily;
    }
    if(m6==5)
    {
    	system("cls");
    	goto MainMenu;
	}
    //Select number of items
    cout<<"How many would you want? : ";
    cin>>num5;
    if(num5>daily[m6-1].getStock())
    {
    	cout<<"\nImpossible request :: Purchase beyond the stock available \n\n"<<endl;
    	system("pause");
    	system("cls");
    	goto Daily;
	}
	list.push_back(daily[m6-1].getItem());
    daily[m6-1].getMany(num5);
    pricelist.push_back(daily[m6-1].getTotal());
    daily[m6-1].rStock(num5);
	purchaselist.push_back(num5);
	main.success();
    goto MainMenu;
    //----------------------------------------------------------------------------------------------------------------------
    
    //Display items that the user choose
	Item:
	cout<<"ITEM LIST\n"<<endl;
	for(int j=0 ; j<list.size() ;j++)
	{
		cout<<j+1<<". "<<left<<setw(15)<<list[j]<<setw(15)<<pricelist[j]<<purchaselist[j]<<endl;
	}
	cout<<"\n\nTotal Price: RM "<<accumulate(pricelist.begin() , pricelist.end(), 0)<<endl;
	system("pause");
    system("cls");
    goto MainMenu;
    
    //Create Payment object
    Pay:
	Payment pay1(cust1.getMemberID(),cust1.getName(),cust1.getPhoneNum(),displayPaymentOption());
	system("cls");
	
	//Create Receipt object
	Receipt rec1;
	//Display the receipt
	cout << "====================================================================\n";
	cout << right << setw(45) << "Farm Grocer by Ferma.Inc" << endl;
	cout << right << setw(55) << "89, Persiaran Horizon, 81350 Johor Bahru, Johor." << endl;
	cout << right << setw(38) << "012-3456789" << endl;
	cout << "====================================================================\n";
	//Display current date and time based on the system
	time_t now = time(0);          
	char* date = ctime(&now);
	cout << right << setw(23) << "Date: " << date << endl;
	//Display cashier info
	cout  << setw(32) << "Cashier: ";
	cash.display();
	cout << endl;
	//Display member info
	if(reply==1)
	{
		cout << right << setw(25) << "Member Info: " << cust1.getMemberID() << ", " << cust1.getName() << ", " << cust1.getPhoneNum() << endl << endl;
	}
	if(reply==2)
	{
		cout << right << setw(42) << "Member Info: -----" << endl << endl;
	}
	
	cout<< "Purchase List: \n\n";
	for(int j=0 ; j<list.size() ;j++)
	{
		cout<<j+1<<". "<<left<<setw(15)<<list[j]<<setw(15)<<pricelist[j]<<purchaselist[j]<<endl;
	}
	cout << "\nTotal number of purchase: " << accumulate(purchaselist.begin() , purchaselist.end(), 0) << endl;
	
	//Calculate the price before discount
	double subtotal;
	subtotal=accumulate(pricelist.begin() , pricelist.end(), 0);
	cout << "\nSubtotal: RM " << subtotal << endl;
	cout << "Discount: RM " << rec1.getDiscount(subtotal, reply) << endl;  
	//Calculate the price after discount 
	double totalP;
	totalP = subtotal-(rec1.getDiscount(subtotal, reply));
	cout << "=======================" << endl;
	cout << "Total: RM " << totalP << endl;
	cout << "=======================" << endl << endl;
	
	//Money paid by customer
	double totalPay;
	cout << "Total Pay: RM "; 
	cin >> totalPay;
	if(totalPay<totalP)
	{
		system("cls");
		cout<<"!!!! Insufficient Funds !!!!\n Please Select Other Method\n"<<endl;
		system("pause");
		system("cls");
		goto Pay;
	}
	pay1.getChange(totalPay, totalP);
	pay1.display(memberID);
	
	cout << "\n\t\tThank you for your purchase ! \n";
	cout << "\t\tHope to see you again! \n";
	
	return 0;
}
