#include <stdio.h>      // Για printf, scanf, fopen, fclose, fputs, sprintf
#include <stdlib.h>     // Για τη συνάρτηση system() που εκτελεί εντολές του λειτουργικού

// ───────────────────────────────────────────────────────────────────────────
// Δήλωση (prototype) της συνάρτησης που ανοίγει αρχείο για εγγραφή.
//   name : το όνομα του αρχείου (πίνακας χαρακτήρων)
//   f    : δείκτης σε ακέραιο – λειτουργεί ως "flag" ώστε η συνάρτηση να
//          ενημερώσει την main αν το άνοιγμα πέτυχε (1) ή απέτυχε (0).
//          Χρησιμοποιούμε δείκτη επειδή στη C η μεταβίβαση γίνεται "by value"
//          – για να αλλάξουμε την τιμή της μεταβλητής του καλούντος, περνάμε
//          τη διεύθυνσή της.
//"Η open_file είναι μια συνάρτηση που δέχεται δύο ορίσματα (έναν πίνακα χαρακτήρων 
//name και έναν δείκτη σε ακέραιο f) και επιστρέφει έναν δείκτη σε δομή FILE."
// ───────────────────────────────────────────────────────────────────────────
FILE *open_file(char name[], int *f);

int main(void)
{
    FILE *fp;                  // Δείκτης αρχείου – μέσω αυτού γίνονται όλες οι λειτουργίες I/O
    char name[100];            // Buffer για το όνομα του αρχείου που δίνει ο χρήστης
    char openFile[100];        // Buffer για τη σύνθεση της εντολής που θα δοθεί στο system()
    int flag, sel;             // flag: αν άνοιξε το αρχείο (1=ναι, 0=όχι), sel: επιλογή χρήστη (Yes/No)

    flag = 0;                  // Αρχικοποίηση: ξεκινάμε υποθέτοντας ότι ΔΕΝ έχει ανοίξει αρχείο

    // ───────────────────────────────────────────────────────────────────
    // Βρόχος do-while: επαναλαμβάνεται μέχρι να ανοίξει επιτυχώς αρχείο.
    // Χρησιμοποιούμε do-while (αντί για while) επειδή θέλουμε να εκτελεστεί
    // ΤΟΥΛΑΧΙΣΤΟΝ ΜΙΑ φορά – πρέπει πρώτα να ζητήσουμε όνομα και μετά να
    // ελέγξουμε αν πέτυχε.
    // ───────────────────────────────────────────────────────────────────
    do
    {
        printf("\nEnter file name: ");
        scanf("%s", name);     // Διαβάζουμε το όνομα αρχείου (μέχρι το πρώτο κενό)

        // Πρώτα δοκιμάζουμε να το ανοίξουμε για ΑΝΑΓΝΩΣΗ ("r"),
        // ΟΧΙ για να το διαβάσουμε, αλλά απλώς για να ελέγξουμε αν υπάρχει.
        // Αν επιστρέψει NULL, σημαίνει ότι το αρχείο δεν υπάρχει.
        fp = fopen(name, "r");

        if (fp == NULL)
        {
            // Το αρχείο δεν υπάρχει → το δημιουργούμε καλώντας τη βοηθητική
            // συνάρτηση open_file (η οποία το ανοίγει σε λειτουργία "w").
            // Περνάμε &flag ώστε να ενημερωθεί αν πέτυχε ή όχι.
            fp = open_file(name, &flag);
        }
        else
        {
            // Το αρχείο υπάρχει ήδη → πρέπει πρώτα να το κλείσουμε
            // (το είχαμε ανοίξει μόνο για έλεγχο ύπαρξης).
            fclose(fp);

            printf("\nThe file %s already exists.\n", name);
            printf("Would you like to overwrite existing file (Yes:1 - No:0)? ");
            scanf("%d", &sel);

            if (sel == 1)
            {
                // Ο χρήστης δέχεται overwrite → καλούμε ξανά την open_file
                // με "w", η οποία θα ΣΒΗΣΕΙ τα παλιά περιεχόμενα και θα
                // δημιουργήσει νέο αρχείο.
                fp = open_file(name, &flag);
            }
            // Αν sel == 0, το flag παραμένει 0 και ο βρόχος θα ζητήσει
            // ξανά νέο όνομα αρχείου.
        }
    } while (flag == 0);   // Συνέχιση μέχρι να δημιουργηθεί/ανοιχτεί επιτυχώς αρχείο

    // ───────────────────────────────────────────────────────────────────
    // Σε αυτό το σημείο έχουμε σίγουρα έγκυρο fp ανοιχτό σε λειτουργία "w".
    // ───────────────────────────────────────────────────────────────────

    fputs("One", fp);          // Γράφουμε τη συμβολοσειρά "One" στο αρχείο.
                               // Σε αντίθεση με την puts(), η fputs() ΔΕΝ προσθέτει '\n' στο τέλος.

    fclose(fp);                // Κλείσιμο αρχείου – ΠΑΝΤΑ κλείνουμε ό,τι ανοίγουμε
                               // (γίνεται flush των buffers και απελευθερώνεται ο file descriptor)

    // ───────────────────────────────────────────────────────────────────
    // Άνοιγμα του αρχείου με το Σημειωματάριο, για να δει ο χρήστης το αποτέλεσμα.
    // ───────────────────────────────────────────────────────────────────
    sprintf(openFile, "notepad %s", name);  // Σύνθεση της εντολής, π.χ.: "notepad data.txt"
                                            // Η sprintf() γράφει σε string αντί για οθόνη
    //system(openFile);                       // Εκτέλεση της εντολής στο λειτουργικό (μόνο Windows)

    return 0;                  // Επιτυχής τερματισμός του προγράμματος
}

// ═══════════════════════════════════════════════════════════════════════════
// Ορισμός (υλοποίηση) της συνάρτησης open_file.
// Σκοπός: να συγκεντρώσει σε ένα σημείο τον κώδικα που ανοίγει το αρχείο
//         για εγγραφή και ενημερώνει το flag, αποφεύγοντας επανάληψη
//         κώδικα στη main (DRY – Don't Repeat Yourself).
// ═══════════════════════════════════════════════════════════════════════════
FILE *open_file(char name[], int *f)
{
    FILE *fp;                  // Τοπικός δείκτης αρχείου

    // Άνοιγμα/δημιουργία αρχείου σε λειτουργία "w" (write):
    //   - αν δεν υπάρχει → δημιουργείται
    //   - αν υπάρχει     → ΣΒΗΝΟΝΤΑΙ τα παλιά περιεχόμενα (truncate)
    fp = fopen(name, "w");

    if (fp == NULL)
    {
        // Απέτυχε το άνοιγμα, π.χ. λόγω δικαιωμάτων ή μη έγκυρου ονόματος.
        printf("Error: File cannot be created\n");
        *f = 0;   // Δεν άνοιξε
    }
    else
    {
        // Αν πετύχει
        *f = 1;   // Άνοιξε επιτυχώς
    }

    return fp;   // Επιστρέφουμε τον δείκτη αρχείου
}