#include <iostream>
#include <stdlib.h>
#include <ctime>
using namespace std;

class Message {

public:
	int mes_id,prod_id,cons_id;

	Message (int x,int y,int z) :mes_id(x),
									prod_id(y),
										cons_id(z) {
	}
	
	~Message() {
		cout << "Ovo je poruka " << mes_id << " od proizvodjaca " << prod_id << " potrosacu " << cons_id << endl;
	}

};	

class Producer {

public:
	int prod_id,max_mesg,max_cons;
	Producer *next_prod;

	Producer();
	Producer(int x,int y,int z) : prod_id(x),
									max_mesg(y),
										max_cons(z),
											next_prod(NULL) {}

	~Producer() {
		cout << "Producer has been terminated" << endl;
	}

	Message *Make() {
		
		int x;
		
		x=rand();
		Message *poruka =new Message((x%max_mesg)+1,prod_id,(x%max_cons)+1);
					
		return (poruka);
	}

};

class Consumer {
public:
	int cons_id;
	Consumer *next_cons;
	
	Consumer(int x) : cons_id(x),
							next_cons(NULL) {}

	~Consumer() {
		cout << "Consumer has been terminated" << endl;
	}

	Trosi(Message *poruka) {
		
		delete poruka;
	}
};

class Mediator {

public:
	Producer *head_prod;
	Consumer *head_cons;
	Message *poruka;

	Mediator() : head_prod(NULL),head_cons(NULL) {};

	~Mediator() {}

	Producer *Add_Producer(Producer *new_prod,Producer *head_prod) {
		Producer *temp;

		if(head_prod==NULL) {
			head_prod=new_prod;
		}
		else {
			for(temp=head_prod;temp->next_prod!=NULL;temp=temp->next_prod){}
			temp->next_prod=new_prod;
		}
		return (head_prod);
	};

//	void Ispisi_producer (Producer *glava) {
//
//		do {
//			cout << "Ja sam proizvodjac " << glava->prod_id << " na adresi " << glava << endl;
//			glava=glava->next_prod;
//		}
//		while(glava!=NULL);
//	};
	
	void delete_producer (Producer *glava) {
		Producer *temp;
		
		do {
			temp=glava->next_prod;
			delete glava;
			glava=temp;
		}
		while(glava!=NULL);
	};

	Consumer *Add_Consumer(Consumer *new_cons,Consumer *head_cons) {
		Consumer *temp;

		if(head_cons==NULL) {
			head_cons=new_cons;
		}
		else {
			for(temp=head_cons;temp->next_cons!=NULL;temp=temp->next_cons){}
			temp->next_cons=new_cons;
		}
		return (head_cons);
	};

	void delete_consumer (Consumer *glava) {
		Consumer *temp;
		
		do {
			temp=glava->next_cons;
			delete glava;
			glava=temp;
		}
		while(glava!=NULL);
	};

//	void Ispisi_consumer (Consumer *glava) {
//
//		do {
//			cout << "Ja sam potrosac " << glava->cons_id << " na adresi " << glava << endl;
//			glava=glava->next_cons;
//		}
//		while(glava!=NULL);
//	};

	void Salji(Producer *head_prod,Consumer *head_cons,int number_of_messages) {
		Message *poruka;
		Consumer *temp;
		int j=1;
				
		srand( (unsigned)time( NULL ) );
		do {
			for(int i=0;i<number_of_messages;i++) {
				poruka=head_prod->Make();
			
				temp=head_cons;
		
				do {
					if(temp->cons_id==poruka->cons_id) {
						cout << j << " ";
						j++;
						temp->Trosi(poruka);
						break;
					} 
				temp=temp->next_cons;
				}
				while(temp!=NULL);
			}

			head_prod=head_prod->next_prod;
		
		}
		while(head_prod!=NULL);

		
		
	}
};

void main () {
	
	int P,C,M,i;
	Producer *head_producer;
	Consumer *head_consumer;

	cout << "Unesite broj Proizvodjaca" << endl;
	cin >> P;
	cout << "Unesite broj Potrosaca" << endl;
	cin >> C;
	cout << "Unesite broj Poruka" << endl;
	cin >> M;
	
	cout << endl << "P = " << P << endl;
	cout << "C = " << C << endl;
	cout << "M = " << M << endl;
	cout << "Ukupan broj poruka = " << P*M << endl;

	Mediator posrednik;
	cout << "Posrednik kreiran" << endl;

	head_producer=NULL;
	head_consumer=NULL;
	
	for (i=1;i<=P;++i) {
		Producer *new_producer = new Producer(i,M,C);
		if(new_producer) cout << "Proizvodjac " << i << " je stvoren" << endl;
		head_producer=posrednik.Add_Producer(new_producer,head_producer);
	}
//	posrednik.Ispisi_producer(head_producer);
	
	for (i=1;i<=C;++i) {
		Consumer *new_consumer = new Consumer(i);
		if(new_consumer) cout << "Potrosac " << i << " je stvoren" << endl;
		head_consumer=posrednik.Add_Consumer(new_consumer,head_consumer);
	}
//	posrednik.Ispisi_consumer(head_consumer);
	
	posrednik.Salji(head_producer,head_consumer,M);

	posrednik.delete_producer(head_producer);
	posrednik.delete_consumer(head_consumer);

	cout << "Kraj" << endl;

}