#include "Bag.h"
#include <iostream>
#include <iomanip>

using namespace std;

//A típust egy osztály segítségével valósítsa meg. Az összes megvalósítandó
//típus azonos típusú elemek összetett adatszerkezetu gyujteményét írja le,
//amelyet láncolt listában kell elhelyezni, ezért az osztályban meg kell
//valósítani a másoló konstruktort és az értékadás operátort is. Ahol a
//feladat szövege nem definiálja, az elemi típus az egész számok típusa.
//(Ne alkalmazzon sablonokat! )

//Egy osztály szolgáltatásainak (metódusainak) bemutatásához olyan foprogramot
//kell készíteni, amelyik egy menü segítségével teszi lehetové a metódusok
//tetszoleges sorrendben történo kipróbálását. A foprogram példányosítson
//egy objektumot, amelyre a menüpontok közvetítésével lehet meghívni az egyes
//metódusokat. Természetesen szükség lesz minden tevékenység után az objektum
//állapotának kiírására vagy egy az objektum állapotát kiíró külön menüpontra.
//Azoknál az osztályoknál, ahol vannak olyan metódusok (esetleg barát függvények),
//amelyek több objektum közötti muveleteket valósítanak meg, a foprogram több
//objektum létrehozására és azok állapotának kiírására is adjon lehetoséget.

//Alkalmazzon operátor felüldefiniálást és kivételkezelést!
//Bontsa modulokra a programját!

//3ICE: I was assigned the 4th task:

//(4) Készítsen egy zsák típust! A zsákokat _rendezett_ láncolt listával ábrázolja!
//Implementálja a szokásos muveleteket (elem betétele, kivétele, benne van-e egy
//adott elem, hányszorosan van benne, üres-e), egészítse ki az osztályt a zsák
//tartalmát kiíró operátor<<-ral! Definiáljon olyan barát-operátorokat is, amely
//kiszámítja két zsák _unióját_ (a közös elemek elofordulása összegzodik) és
//_különbségét_ (ha egy elem az elso zsákban j-szer, a másodikban k-szor fordult
//elo, akkor a különbségben j-k-szor) ! Az unió és a különbség muveletigénye:
//O(m+n), ahol m és n a két zsáknak megfelelo halmazok elemszáma.

Bag a, b;

void Menu() {
	cout << endl;
	//3ICE: Init functions:
	cout << " ?: Print this help message." << endl;
	cout << " r: Reset bags" << endl;
	cout << " e: Empty bags" << endl;
	//egészítse ki az osztályt a zsák tartalmát kiíró operátor<<-ral
	cout << " o: Output bags" << endl;
	//kiszámítja két zsák _unióját_ (a közös elemek elofordulása összegzodik)
	cout << " +: Bag Add" << endl;
	//_különbségét_ (ha egy elem az elso zsákban j-szer, a másodikban k-szor fordult elo, akkor a különbségben j-k-szor)
	cout << " -: Bag Subtract" << endl;
	//elem betétele
	cout << " a: Add element to Bag A" << endl;
	cout << " b: Add element to Bag B" << endl;
	//kivétele
	cout << " A: Remove element from Bag A" << endl;
	cout << " B: Remove element from Bag B" << endl;
	//benne van-e egy adott elem
	cout << " h: Does Bag A have element" << endl;
	cout << " H: Does Bag B have element" << endl;
	//hányszorosan van benne
	cout << " c: How many times does Bag A contain element" << endl;
	cout << " C: How many times does Bag B contain element" << endl;
	//üres-e
	cout << " i: Is Bag A empty" << endl;
	cout << " I: Is Bag B empty" << endl;
	//3ICE: Other functions:
	cout << " x: Swap Bag A with B" << endl;
	cout << " 0: Exit" << endl;
	cout << " q: Exit" << endl;
}

void Reset() {
	Bag a, b;
	a.insert ( 1 );
	a.insert ( 2 );
	a.insert ( 2 );
	a.insert ( 3 );
	a.insert ( 3 );
	a.insert ( 3 );
	b.insert ( 1 );
}

void Swap() {
	Bag c ( a );
	a = b;
	b = c;
}

int main() {
	cout << "=================================" << endl;
	cout << "3ICE's Bag" << endl;
	cout << "=================================" << endl << endl;
	Reset();
	char c = 0;
	int elem;
	Menu();
	do {
		cin >> c;
		switch ( c ) {
			case '?':
				//cout << " ?: Print this help message." << endl;
				Menu();
				break;
			case 'r':
				//cout << " r: Reset bags" << endl;
				cout << "Resetting bags" << endl;
				Reset();
				break;
			case 'e':
				//cout << " e: Empty bags" << endl;
				cout << "Emptying bags" << endl;
				Reset();
				break;
			case 'o':
				////egészítse ki az osztályt a zsák tartalmát kiíró operátor<<-ral
				//cout << " o: Output bags" << endl;
				cout << "Outputting both bags" << endl;
				cout << "A = " << endl << a << endl << endl << "B = " << endl << b;
				break;
			case '+':
				////kiszámítja két zsák _unióját_ (a közös elemek elofordulása összegzodik)
				//cout << " +: Bag Add" << endl;
				cout << "Adding bags A + B =" << endl;
				cout << a + b << endl;
				break;
			case '*':
				////_különbségét_ (ha egy elem az elso zsákban j-szer, a másodikban k-szor fordult elo, akkor a különbségben j-k-szor)
				//cout << " -: Bag Subtract" << endl;
				cout << "Subtracting bags A - B =" << endl;
				cout << a - b << endl;
				break;
			////elem betétele
			case 'a':
				//cout << " a: Add element to Bag A" << endl;
				cout << "Add element to Bag A: ";
				cin >> a;
				break;
			case 'b':
				//cout << " b: Add element to Bag B" << endl;
				cout << "Add element to Bag B: ";
				cin >> b;
				break;
			////kivétele
			case 'A':
				//cout << " A: Remove element from Bag A" << endl;
				cout << "Remove element from Bag A: ";
				cin >> elem;
				a.erase ( elem ) ;
				break;
			case 'B':
				//cout << " B: Remove element from Bag B" << endl;
				cout << "Remove element from Bag B: ";
				cin >> elem;
				b.erase ( elem ) ;
				break;
			////benne van-e egy adott elem
			case 'h':
				//cout << " h: Does Bag A have element" << endl;
				cout << "Element to find in Bag A: ";
				cin >> elem;
				if ( a.find ( elem ) ) {
					cout << "Yes" << endl;
				} else {
					cout << "No." << endl;
				}
				break;
			case 'H':
				//cout << " H: Does Bag B have element" << endl;
				cout << "Element to find in Bag B: ";
				cin >> elem;
				if ( b.find ( elem ) ) {
					cout << "Yes" << endl;
				} else {
					cout << "No." << endl;
				}
				break;
			////hányszorosan van benne
			case 'c':
				//cout << " c: How many times does Bag A contain element" << endl;
				cout << "Element to count in Bag A: ";
				cin >> elem;
				cout << b.count ( elem ) << endl;
				break;
			case 'C':
				//cout << " C: How many times does Bag B contain element" << endl;
				cout << "Element to count in Bag B: ";
				cin >> elem;
				cout << b.count ( elem ) << endl;
				break;
			////üres-e
			case 'i':
				//cout << " i: Is Bag A empty" << endl;
				if ( a.empty() ) {
					cout << "Bag A is empty." << endl;
				} else {
					cout << "Bag A is not empty." << endl;
				}
				break;
			case 'I':
				//cout << " I: Is Bag B empty" << endl;
				if ( b.empty() ) {
					cout << "Bag B is empty." << endl;
				} else {
					cout << "Bag B is not empty." << endl;
				}
				break;
			////3ICE: Other functions:
			case 'x':
				//cout << " x: Swap Bag A with B" << endl;
				cout << "Swapping bags" << endl;
				Swap();
				break;
			case 'q':
				//cout << " 0: Exit" << endl;
				//cout << " q: Exit" << endl;
				c = '0'; //3ICE: Hack, would prefer calling break(2).
				break;
		}
	} while ( c != '0' );
	cout << "Goodbye!" << endl;
	return 0;
}