#include <iostream>
#include <mpi.h>
#include <cstddef>
using namespace std;

struct SensorData{
	int sensor_id;
	double temperature;
	char status;
};

int main(int argc, char** argv){
	MPI_Init(&argc, &argv);
	int world_size, world_rank;
	MPI_Comm_size(MPI_COMM_WORLD, &world_size);
	MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
	if(world_size<2){
		if(world_rank==0) cerr<<"ERROR: Use -np 2"<<endl;
		MPI_Finalize();
		return 1;
	}
	int num_blocks=3;
	int block_lengths[3]={1,1,1};
	MPI_Datatype block_types[3]={MPI_INT, MPI_DOUBLE, MPI_CHAR};
	MPI_Aint displacements[3];
	displacements[0]=offsetof(SensorData, sensor_id);
	displacements[1]=offsetof(SensorData, temperature);
	displacements[2]=offsetof(SensorData, status);
	MPI_Datatype MPI_SENSOR_DATA;
	MPI_Type_create_struct(num_blocks, block_lengths, displacements, block_types, &MPI_SENSOR_DATA);
	MPI_Type_commit(&MPI_SENSOR_DATA);
	if(world_rank==0){
		SensorData my_sensor;
		my_sensor.sensor_id=404;
		my_sensor.temperature=98.6;
		my_sensor.status='A';
		cout<<"[NODE 0] Packaging complex struct (ID: "<<my_sensor.sensor_id<<", Temp: "<<my_sensor.temperature
		<<", Status: "<<my_sensor.status<<")"<<endl;
		MPI_Send(&my_sensor, 1, MPI_SENSOR_DATA, 1, 0, MPI_COMM_WORLD);
		cout<<"[NODE 0] Complex struct transmitted over the network."<<endl;
	}
	else if(world_rank==1){
		SensorData received_sensor;
		MPI_Recv(&received_sensor, 1, MPI_SENSOR_DATA, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
		cout<<"  ->[NODE 1] Complex struct received successfully!"<<endl;
		cout<<"  ->[NODE 1] Extracted Data -> ID: "<<received_sensor.sensor_id<<" | Temp: "
		<<received_sensor.temperature<<" | Status: "<<received_sensor.status<<endl;
	}
	MPI_Type_free(&MPI_SENSOR_DATA);
	MPI_Finalize();
	return 0;
}
