#include <stdio.h>
#include <string.h>

#define CHAR_LEN 20
#define NUM_CARS 10
#define NUM_OWNERS 5

/// Define a struct to store car information
typedef struct 
{
    char mark[CHAR_LEN];
    char model[CHAR_LEN];
    char numberPlate[CHAR_LEN];
    int yearOfIssue;
    char cubature[CHAR_LEN];
    int personalIdentificationNumber;
} car_t;

/// Define a struct to store car owner information
typedef struct 
{
    int personalIdentificationNumber;
    char name[CHAR_LEN];
} owner_t;

/// Function prototypes
int readCarData(FILE*, car_t[], int);
int readOwnerData(FILE*, owner_t[], int);
void findMostPowerfulCar(car_t[], int, car_t*);
void findOldestCar(car_t[], int, car_t*);
void findNewestCar(car_t[], int, car_t*);
void displayResults(car_t, car_t, car_t);
void writeResultsToFile(car_t, car_t, car_t, const char*);
void printErrorOpeningFile(const char*);

int main(void) 
{
    FILE *carFile, *ownerFile;
    car_t cars[NUM_CARS];
    owner_t owners[NUM_OWNERS];
    car_t mostPowerfulCar, oldestCar, newestCar;

    /// Read car data from the input file
    carFile = fopen("cars.txt", "r");
    if (carFile == NULL) 
    {
        printErrorOpeningFile("car data");
        return 1;
    }
    int numCars = readCarData(carFile, cars, NUM_CARS);
    fclose(carFile);

    /// Read owner data from the input file
    ownerFile = fopen("owners.txt", "r");
    if (ownerFile == NULL) 
    {
        printErrorOpeningFile("owner data");
        return 1;
    }
    readOwnerData(ownerFile, owners, NUM_OWNERS);
    fclose(ownerFile);

    /// Find the most powerful, oldest, and newest car
    findMostPowerfulCar(cars, numCars, &mostPowerfulCar);
    findOldestCar(cars, numCars, &oldestCar);
    findNewestCar(cars, numCars, &newestCar);

    /// Display the results
    displayResults(mostPowerfulCar, oldestCar, newestCar);

    /// Write the results to the output file
    writeResultsToFile(mostPowerfulCar, oldestCar, newestCar, "cars_output.txt");

    return 0;
}

/// Read car data from the input file and store it in the cars array
int readCarData(FILE *carFile, car_t cars[], int maxCars) 
{
    char buffer[512];
    int counter = 0;
    while (fgets(buffer, 512, carFile) && counter < maxCars) 
    {
        sscanf(buffer, "%s %s %s %d %s %d", cars[counter].mark, cars[counter].model,
               cars[counter].numberPlate, &cars[counter].yearOfIssue, cars[counter].cubature,
               &cars[counter].personalIdentificationNumber);
        counter++;
    }
    return counter;
}

/// Read owner data from the input file and store it in the owners array
int readOwnerData(FILE *ownerFile, owner_t owners[], int maxOwners) 
{
    char buffer[512];
    int counter = 0;
    while (fgets(buffer, 512, ownerFile) && counter < maxOwners) 
    {
        sscanf(buffer, "%d %s", &owners[counter].personalIdentificationNumber, owners[counter].name);
        counter++;
    }
    return counter;
}

/// Find the most powerful car based on cubature
void findMostPowerfulCar(car_t cars[], int numCars, car_t *mostPowerfulCar) 
{
    *mostPowerfulCar = cars[0];
    for (int i = 1; i < numCars; i++) 
    {
        if (strcmp(cars[i].cubature, mostPowerfulCar->cubature) > 0) 
        {
            *mostPowerfulCar = cars[i];
        }
    }
}

/// Find the oldest car based on year of issue
void findOldestCar(car_t cars[], int numCars, car_t *oldestCar) 
{
    *oldestCar = cars[0];
    for (int i = 1; i < numCars; i++) 
    {
        if (cars[i].yearOfIssue < oldestCar->yearOfIssue) 
        {
            *oldestCar = cars[i];
        }
    }
}

/// Find the newest car based on year of issue
void findNewestCar(car_t cars[], int numCars, car_t *newestCar) 
{
    *newestCar = cars[0];
    for (int i = 1; i < numCars; i++) 
    {
        if (cars[i].yearOfIssue > newestCar->yearOfIssue) 
        {
            *newestCar = cars[i];
        }
    }
}

/// Display the results on the screen
void displayResults(car_t mostPowerfulCar, car_t oldestCar, car_t newestCar) 
{
    printf("Most Powerful Car:\n");
    printf("Mark: %s, Model: %s, Number Plate: %s, Year: %d, Cubature: %s, Owner ID: %d\n",
           mostPowerfulCar.mark, mostPowerfulCar.model, mostPowerfulCar.numberPlate,
           mostPowerfulCar.yearOfIssue, mostPowerfulCar.cubature, mostPowerfulCar.personalIdentificationNumber);

    printf("\nOldest Car:\n");
    printf("Mark: %s, Model: %s, Number Plate: %s, Year: %d, Cubature: %s, Owner ID: %d\n",
           oldestCar.mark, oldestCar.model, oldestCar.numberPlate, oldestCar.yearOfIssue,
           oldestCar.cubature, oldestCar.personalIdentificationNumber);

    printf("\nNewest Car:\n");
    printf("Mark: %s, Model: %s, Number Plate: %s, Year: %d, Cubature: %s, Owner ID: %d\n",
           newestCar.mark, newestCar.model, newestCar.numberPlate, newestCar.yearOfIssue,
           newestCar.cubature, newestCar.personalIdentificationNumber);
}

/// Write the results to an output file
void writeResultsToFile(car_t mostPowerfulCar, car_t oldestCar, car_t newestCar, const char *outputFileName) 
{
    FILE *outputFile = fopen(outputFileName, "w");
    if (outputFile == NULL) 
    {
        printErrorOpeningFile("output");
        return;
    }

    fprintf(outputFile, "Most Powerful Car:\n");
    fprintf(outputFile, "Mark: %s, Model: %s, Number Plate: %s, Year: %d, Cubature: %s, Owner ID: %d\n",
            mostPowerfulCar.mark, mostPowerfulCar.model, mostPowerfulCar.numberPlate,
            mostPowerfulCar.yearOfIssue, mostPowerfulCar.cubature, mostPowerfulCar.personalIdentificationNumber);

    fprintf(outputFile, "\nOldest Car:\n");
    fprintf(outputFile, "Mark: %s, Model: %s, Number Plate: %s, Year: %d, Cubature: %s, Owner ID: %d\n",
            oldestCar.mark, oldestCar.model, oldestCar.numberPlate, oldestCar.yearOfIssue,
            oldestCar.cubature, oldestCar.personalIdentificationNumber);

    fprintf(outputFile, "\nNewest Car:\n");
    fprintf(outputFile, "Mark: %s, Model: %s, Number Plate: %s, Year: %d, Cubature: %s, Owner ID: %d\n",
            newestCar.mark, newestCar.model, newestCar.numberPlate, newestCar.yearOfIssue,
            newestCar.cubature, newestCar.personalIdentificationNumber);

    fclose(outputFile);
}

/// Print error opening file message
void printErrorOpeningFile(const char *fileType) 
{
    printf("Error opening %s file.\n", fileType);
}