//Name: Muhammad Aiman Bin Abdul Razak
//Matrics No: A20EC0082
//Programming Technique II PROJECT 2
//
//Name: Chong Kah Wei
//Matrics No: A20EC0027
//Programming Technique II PROJECT 2
//
//Name: Heong Yi Qing
//Matrics No: A20EC0043
//Programming Technique II PROJECT 2

#include <iostream>
#include <string>
#include <iomanip>

using namespace std;

class Clothes{
	private :
		string cname;
		int camount;
	public :
		Clothes(){}
		Clothes(string tempcname, int tempcamount){
			cname=tempcname;
			camount=tempcamount;
		}
		string getName(){
			return cname;
		}
		int getAmount(){
			return camount;
		}
};

class Order{
	private :
		int typecode;
		Clothes orderclothes;
	public :
		Order(){}
		Order(int temptypecode, string clothesname, int clothesamount) : orderclothes(clothesname, clothesamount){
			typecode=temptypecode;
		}
		int getCategory(){
			return typecode;
		}
		virtual void printOrderDetails(){
			cout<<"Item Name : "<<orderclothes.getName()<<endl;
			cout<<"Item Amount : "<<orderclothes.getAmount()<<endl;
		}
};

class Men : public Order{
	private :
		int mcode;
	public :
		Men(){}
		Men(int tempmcode, int temptypecode, string clothesname, int clothesamount) : Order(temptypecode, clothesname, clothesamount){
			mcode = tempmcode;	
		}
		int getItemCodeMen(){
			return mcode;
		}
		void printOrderDetails(){
			cout<<"=======================================================================================================================\n";
			cout<<"Item Information"<<endl;
			cout<<"=======================================================================================================================\n";
			Order::printOrderDetails();
			cout<<"Item Type : "<<Order::getCategory()<<endl;
			cout<<"Item Code : M"<<getItemCodeMen()<<endl;
			cout<<"=======================================================================================================================\n";
		}
};

class Women : public Order{
	private :
		int wcode;
	public :
		Women(){}
		Women(int tempwcode, int temptypecode, string clothesname, int clothesamount) : Order(temptypecode, clothesname, clothesamount){
			wcode=tempwcode;
		}
		int getItemCodeWomen(){
			return wcode;
		}
		void printOrderDetails(){
			cout<<"=======================================================================================================================\n";
			cout<<"Item Information"<<endl;
			cout<<"=======================================================================================================================\n";
			Order::printOrderDetails();
			cout<<"Item Type : "<<Order::getCategory()<<endl;
			cout<<"Item Code : W"<<getItemCodeWomen()<<endl;
			cout<<"=======================================================================================================================\n";
		}
};

class Kids : public Order{
	private :
		int kcode;
	public :
		Kids(){}
		Kids(int tempkcode, int temptypecode, string clothesname, int clothesamount) : Order(temptypecode, clothesname, clothesamount){
			kcode=tempkcode;
		}
		int getItemCodeKids(){
			return kcode;
		}
		void printOrderDetails(){
			cout<<"=======================================================================================================================\n";
			cout<<"Item Information"<<endl;
			cout<<"=======================================================================================================================\n";
			Order::printOrderDetails();
			cout<<"Item Type : "<<Order::getCategory()<<endl;
			cout<<"Item Code : K"<<getItemCodeKids()<<endl;
			cout<<"=======================================================================================================================\n";
		}
};

class ShippingDepartment{
	private :
		Men *menshipping;
		Women *womenshipping;
		Kids *kidsshipping;
		string shippingdestination;
	public :
		ShippingDepartment(){}
		ShippingDepartment(string tempshipshippingdestination, Men *tempshipmen, Women *tempshipwomen, Kids *tempshipkids){
			shippingdestination = tempshipshippingdestination;
			menshipping = tempshipmen;
			womenshipping = tempshipwomen;
			kidsshipping = tempshipkids;
		}
		string getShippingDestination(){
			return shippingdestination;
		}
		virtual void getShippingDetails()=0;
};

class Local : public ShippingDepartment{
	private :
		string shippingmethod;
	public :
		Local(){}
		Local(string tempshippingmethod, string tempshipshippingdestination, Men *tempshipmen, Women *tempshipwomen, Kids *tempshipkids) : ShippingDepartment(tempshipshippingdestination, tempshipmen, tempshipwomen, tempshipkids){
			shippingmethod = tempshippingmethod;
		}
		string getShippingMethod(){
			return shippingmethod;
		}
		void getShippingDetails(){
			cout<<"Outlet Address : "<<ShippingDepartment::getShippingDestination()<<endl;
			cout<<"Shipping Method : "<<getShippingMethod()<<endl;
		}
		friend class CourierService;
};

class Overseas : public ShippingDepartment{
	private :
		string shippingmethod;
	public :
		Overseas(){}
		Overseas(string tempshippingmethod, string tempshipshippingdestination, Men *tempshipmen, Women *tempshipwomen, Kids *tempshipkids) : ShippingDepartment(tempshipshippingdestination, tempshipmen, tempshipwomen, tempshipkids){
			shippingmethod = tempshippingmethod;
		}
		string getShippingMethod(){
			return shippingmethod;
		}
		void getShippingDetails(){
			cout<<"Outlet Address : "<<ShippingDepartment::getShippingDestination()<<endl;
			cout<<"Shipping Method : "<<getShippingMethod()<<endl;
		}
		friend class CourierService;
};

class CourierService{
	private :
		Local *local;
		Overseas *overseas;
		string receiver;
		double weight;
		double cost;
	public :
		CourierService(string tempreceiver, double tempweight, double tempcost, Local *templocal, Overseas *tempoverseas){
			receiver = tempreceiver;
			cost = tempcost;
			local = templocal;
			overseas = tempoverseas;
			weight = tempweight;
		}
		double getCost(){
			return cost;
		}
		double getWeight(){
			return weight;
		}
		string getReceiver(){
			return receiver;
		}
		void printCourierServiceDetails(){
			cout<<"=======================================================================================================================\n";
			cout<<"Client Information"<<endl;
			cout<<"=======================================================================================================================\n";
			cout<<"Receiver Name : "<<getReceiver()<<endl;
			if (local->shippingmethod.empty())
				overseas->getShippingDetails();
			else
				local->getShippingDetails();
			cout<<fixed<<setprecision(2);
			cout<<"Package Weight : "<<getWeight()<<" KG"<<endl;
			cout<<"Package + Shipping Fee : RM"<<getCost()<<endl;
			cout<<"=======================================================================================================================\n";		
			}
};

int main(){
	int n_orders;
	
	cout<<"=======================================================================================================================\n";
	cout<<" ****************  **        **   ***    *****    *******  **   **   *****   **   **  *****  *******  ****************\n";
	cout<<" ****************   **  **  **   ** **   **  **   *****    *******  **   **  **   **  **     ****     ****************\n";
	cout<<" ****************    ***  ***   *******  *****    **       **   **  **   **  **   **    ***  **       ****************\n";
	cout<<" ****************     **  **   **     ** **   **  *******  **   **   *****    *****   *****  *******  ****************\n";
	cout<<"=======================================================================================================================\n";
	cout<<endl;
	
	cout<<"How many orders would you like to take?"<<endl;
	cout<<">> ";
	cin>>n_orders;
	cout<<endl;
	
	char choiceshippingmethod[n_orders];
	string clientname[n_orders], clientaddress[n_orders], itemname[n_orders], shippingmethod[n_orders];
	double postagecost[n_orders], weight[n_orders], cost[n_orders];
	int typecode[n_orders], itemcode[n_orders], itemamount[n_orders];
	double weightkids=0.10, weightmenwomen=0.15;
	
	for(int i=0; i<n_orders; i++){
		cout<<"=======================================================================================================================\n";
		cout<<"ORDER "<<i+1<<" (INPUT) :"<<endl;
		cout<<"=======================================================================================================================\n";
	
		cout<<"Please select item type :"<<endl;
		cout<<"1 for MEN'S CLOTHING"<<endl;
		cout<<"2 for WOMEN's CLOTHING"<<endl;
		cout<<"3 for KID'S CLOTHING"<<endl;
		cout<<"***Fixed Price RM25 Per Clothing***"<<endl;
	
		cout<<">> ";
		do{
			cin>>typecode[i];
			if(typecode[i] != 1 && typecode[i] != 2 && typecode[i] != 3){
				cout<<"Choice not recognized. Please try again..."<<endl;
				cout<<">> ";
			}
		}while(typecode[i] != 1 && typecode[i] != 2 && typecode[i] != 3);
	
		cout<<endl;
	
		cout<<"Please select shipping method :"<<endl;
		cout<<"'L' for LOCAL SHIPPING    - RM1.00 per KG"<<endl;
		cout<<"'O' for OVERSEAS SHIPPING - RM3.00 per KG"<<endl;
	
		cout<<">> ";
		do{
			cin>>choiceshippingmethod[i];
			if(choiceshippingmethod[i] != 'L' && choiceshippingmethod[i] != 'O'){
				cout<<"Choice not recognized. Please try again..."<<endl;
				cout<<">> ";
			}
		}while(choiceshippingmethod[i] != 'L' && choiceshippingmethod[i] != 'O');
	
		cout<<"=======================================================================================================================\n";
	
		cout<<"Enter item name : ";
		cin.ignore();
		getline(cin, itemname[i]);
	
		cout<<"Enter item code (e.g. 151214) : ";
		cin>>itemcode[i];
	
		cout<<"Enter item amount : ";
		cin>>itemamount[i];
	
		cout<<"Enter client name : ";
		cin.ignore();
		getline(cin, clientname[i]);
	
		cout<<"Enter client address : ";
		getline(cin, clientaddress[i]);
		
		cout<<"=======================================================================================================================\n\n";
	}
	
    	cout<<"-------------------------------------------------------------------------------------"<<endl<<endl;
	
	for(int i=0; i<n_orders; i++){
		if (choiceshippingmethod[i]=='L')
			shippingmethod[i]="Local";
		else
			shippingmethod[i]="Overseas";
	
		if (typecode[i] == 1 || typecode[i] == 2){
			if(choiceshippingmethod[i]=='L'){
				weight[i]=weightmenwomen*itemamount[i];
				cost[i]=(itemamount[i]*25)+(weight[i]*1);
			}
			else{
				weight[i]=weightmenwomen*itemamount[i];
				cost[i]=(itemamount[i]*25)+(weight[i]*3);
			}
		}
		else{
			if(choiceshippingmethod[i]=='L'){
				weight[i]=weightkids*itemamount[i];
				cost[i]=(itemamount[i]*25)+(weight[i]*1);
			}
			else{
				weight[i]=weightkids*itemamount[i];
				cost[i]=(itemamount[i]*25)+(weight[i]*3);
			}
		}
	
		if (typecode[i] == 1){
			Men menorder(itemcode[i], typecode[i], itemname[i], itemamount[i]);
			Women womenorder;
			Kids kidsorder;
		
			if (choiceshippingmethod[i] == 'L'){
				Local localshipping(shippingmethod[i], clientaddress[i], &menorder, &womenorder, &kidsorder);
				Overseas overseasshipping;
			
				CourierService courierservice(clientname[i], weight[i], cost[i], &localshipping, &overseasshipping);
				
				cout<<"=======================================================================================================================\n";
				cout<<"FOR ORDER "<<i+1<<" :"<<endl;
				cout<<"=======================================================================================================================\n";
				
				courierservice.printCourierServiceDetails();
				if (typecode[i] == 1){
					menorder.printOrderDetails();
					cout<<endl;
				}
				else if (typecode[i] == 2){
					womenorder.printOrderDetails();
					cout<<endl;
				}
				else{
					kidsorder.printOrderDetails();
					cout<<endl;
				}
			}
			else{
				Overseas overseasshipping(shippingmethod[i], clientaddress[i], &menorder, &womenorder, &kidsorder);
				Local localshipping;
			
				CourierService courierservice(clientname[i], weight[i], cost[i], &localshipping, &overseasshipping);
				
				cout<<"=======================================================================================================================\n";
				cout<<"FOR ORDER "<<i+1<<" :"<<endl;
				cout<<"=======================================================================================================================\n";
				
				courierservice.printCourierServiceDetails();
				if (typecode[i] == 1){
					menorder.printOrderDetails();
					cout<<endl;
				}
				else if (typecode[i] == 2){
					womenorder.printOrderDetails();
					cout<<endl;
				}
				else{
					kidsorder.printOrderDetails();
					cout<<endl;
				}
			}
		}
	
		else if (typecode[i] == 2){
			Women womenorder(itemcode[i], typecode[i], itemname[i], itemamount[i]);
			Men menorder;
			Kids kidsorder;
		
			if (choiceshippingmethod[i] == 'L'){
				Local localshipping(shippingmethod[i], clientaddress[i], &menorder, &womenorder, &kidsorder);
				Overseas overseasshipping;
			
				CourierService courierservice(clientname[i], weight[i], cost[i], &localshipping, &overseasshipping);
				
				cout<<"=======================================================================================================================\n";
				cout<<"FOR ORDER "<<i+1<<" :"<<endl;
				cout<<"=======================================================================================================================\n";
				
				courierservice.printCourierServiceDetails();
				if (typecode[i] == 1){
					menorder.printOrderDetails();
					cout<<endl;
				}
				else if (typecode[i] == 2){
					womenorder.printOrderDetails();
					cout<<endl;
				}
				else{
					kidsorder.printOrderDetails();
					cout<<endl;
				}
			}
			else{
				Overseas overseasshipping(shippingmethod[i], clientaddress[i], &menorder, &womenorder, &kidsorder);
				Local localshipping;
			
				CourierService courierservice(clientname[i], weight[i], cost[i], &localshipping, &overseasshipping);
				
				cout<<"=======================================================================================================================\n";
				cout<<"FOR ORDER "<<i+1<<" :"<<endl;
				cout<<"=======================================================================================================================\n";
				
				courierservice.printCourierServiceDetails();
				if (typecode[i] == 1){
					menorder.printOrderDetails();
					cout<<endl;
				}
				else if (typecode[i] == 2){
					womenorder.printOrderDetails();
					cout<<endl;
				}
				else{
					kidsorder.printOrderDetails();
					cout<<endl;
				}
			}
		}
	
		else{
			Kids kidsorder(itemcode[i], typecode[i], itemname[i], itemamount[i]);
			Men menorder;
			Women womenorder;
		
			if (choiceshippingmethod[i] == 'L'){
				Local localshipping(shippingmethod[i], clientaddress[i], &menorder, &womenorder, &kidsorder);
				Overseas overseasshipping;
			
				CourierService courierservice(clientname[i], weight[i], cost[i], &localshipping, &overseasshipping);
				
				cout<<"=======================================================================================================================\n";
				cout<<"FOR ORDER "<<i+1<<" :"<<endl;
				cout<<"=======================================================================================================================\n";
				
				courierservice.printCourierServiceDetails();
				if (typecode[i] == 1){
					menorder.printOrderDetails();
					cout<<endl;
				}
				else if (typecode[i] == 2){
					womenorder.printOrderDetails();
					cout<<endl;
				}
				else{
					kidsorder.printOrderDetails();
					cout<<endl;
				}
			}
			else{
				Overseas overseasshipping(shippingmethod[i], clientaddress[i], &menorder, &womenorder, &kidsorder);
				Local localshipping;
			
				CourierService courierservice(clientname[i], weight[i], cost[i], &localshipping, &overseasshipping);
				
				cout<<"=======================================================================================================================\n";
				cout<<"FOR ORDER "<<i+1<<" :"<<endl;
				cout<<"=======================================================================================================================\n";
				
				courierservice.printCourierServiceDetails();
				if (typecode[i] == 1){
					menorder.printOrderDetails();
					cout<<endl;
				}
				else if (typecode[i] == 2){
					womenorder.printOrderDetails();
					cout<<endl;
				}
				else{
					kidsorder.printOrderDetails();
					cout<<endl;
				}
			}
		}
	}
	return 0;
}
