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

struct __attribute__((__packed__)) Recipe{
    char name[32];
    const char author[14];
    int32_t cook_time;
    char cuisine[28];
    char ingredients[4][32];
    int64_t rating;
    int8_t ingredient_count;
};

void get_input(char* buffer, int size) {
    fgets(buffer, size, stdin);
    char* n = strchr(buffer, '\n');
    if (n) {
        *n = '\0';
    } else {
        int c;
        while ((c = getchar()) != '\n' && c != EOF);
    }
}

void print_file(const char* filename, int size){
    char buf[size];
    FILE *file = fopen(filename, "r");
    if(file){
        size_t read = fread(buf, 1, size, file);
        buf[read] = '\0';
        printf("%s\n", buf);
    }else{
        printf("%s not found.\n", filename);
    }
}

void recipe_info(struct Recipe* r){
    printf("\nEnter a recipe name: ");
    get_input(r->name, 34);
    printf("Name: %s", r->name);
    
    printf("\nEnter the cook time in minutes: ");
    char cook_time[4];
    get_input(cook_time, 4);
    r->cook_time = strtol(cook_time, NULL, 10);
    printf("Cook time: %d", r->cook_time);

    printf("\nEnter the recipie cuisine: ");
    get_input(r->cuisine, 28);
    printf("Cuisine: %s", r->cuisine);
    
    printf("\nEnter the rating [0-99]: ");
    char rating[3];
    get_input(rating, 3);
    r->rating = strtol(rating, NULL, 10);
    printf("Rating: %ld\n", r->rating);
}

void print_ingredients(struct Recipe* r){
    printf("\nIngredients (%d):\n", r->ingredient_count);
    for(int i=0; i<r->ingredient_count; i++){
        printf("\t- %s\n", r->ingredients[i]);
    }
}

void add_ingredient(struct Recipe* r){
    if(r->ingredient_count >= 4){
        printf("Max ingredients reached.\n");
        return;
    }
    char new_ingredient[0x32];
    printf("\nEnter a new ingredient: ");
    get_input(new_ingredient, sizeof(new_ingredient));
    strcpy(r->ingredients[r->ingredient_count], new_ingredient);
    r->ingredient_count++;
    print_ingredients(r);
}

void remove_ingredient(struct Recipe* r){
    if(r->ingredient_count >= 0){
        r->ingredient_count -= 1;
        print_ingredients(r);
    }else{
        printf("Minimum ingredients reached.\n");
    }
}

void print_recipe(struct Recipe* r){
    printf("\nRecipe name: %s\n", r->name);
    printf("Author: %s\n", r->author);
    printf("Cook time: %d\n", r->cook_time);
    printf("Cuisine: %s\n", r->cuisine);
    printf("Rating: %ld", r->rating);
    print_ingredients(r); 
    
    if(strcmp(r->author, "?") == 0){
        print_file("flag1.txt", 32);
    }
    
    if(r->cook_time == 1162559811){
        print_file("flag2.txt", 32);
    }

    if(r->rating == 2397971403551886657 && r->ingredient_count == 67){
        print_file("flag3.txt", 32);
    }
}

int main(){

    setvbuf(stdout, NULL, _IONBF, 0);
    char user_option[4];

    struct Recipe r = {.name="", .author="Jorge Cardoso", .cook_time=0, .rating=0, .ingredient_count=0};
    
    printf("-------------------------------------\n");
    printf("Virtual Recipie Viewer (VRV) version 0.4.5 alpha.\n");
    print_file("logo.txt", 256);
    while(1){
        printf("\nChoose an action: \n");
        printf("16: Enter recipe information\n31: Add ingredient\n33: Remove ingredient\n42: Print recipe\n50: Quit\n");
        printf("Option: "); 
        get_input(user_option, 4);
        
        int choice = strtol(user_option, NULL, 16);

        switch (choice){
            case 16:
                recipe_info(&r);
                break;
            
            case 31:
                add_ingredient(&r);
                break;

            case 33:
                remove_ingredient(&r);
                break;

            case 42:
                print_recipe(&r);
                break;

            case 50:
                goto quit;

            default:
                printf("Invalid input.\n");
            
        }
    }
    quit:
}