#include "friends.h"
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

/*
 * Create a new user with the given name.  Insert it at the tail of the list
 * of users whose head is pointed to by *user_ptr_add.
 *
 * Return:
 *   - 0 if successful
 *   - 1 if a user by this name already exists in this list
 *   - 2 if the given name cannot fit in the 'name' array
 *       (don't forget about the null terminator)
 */
int create_user(const char *name, User **user_ptr_add) {
    User *current = *user_ptr_add;
    while (current != NULL) {
        if (strcmp(current->name, name) == 0) {
            return 1;
        }
        current = current->next;
    }

    if (strlen(name) >= MAX_NAME) {
        return 2;
    }
    // must cast to be of type User*
    User *new_user = (User*) malloc(sizeof(User));
    strcpy(new_user->name, name);
    new_user->next = NULL;

    if (*user_ptr_add == NULL) {
        *user_ptr_add = new_user;
    } else {
        current = *user_ptr_add;
        while (current->next != NULL) {
            current = current->next;
        }
        current->next = new_user;
    }

    return 0;

}


/*
 * Return a pointer to the user with this name in
 * the list starting with head. Return NULL if no such user exists.
 *
 * NOTE: You'll likely need to cast a (const User *) to a (User *)
 * to satisfy the prototype without warnings.
 */
User *find_user(const char *name, const User *head) {

    User *current = (User *) head;

    // Iterate through the list of users starting at head until username is name
    while (current != NULL){
        if (strcmp(current->name, name)== 0){
            return (User *) current;
        }
        current = current -> next;
    }
    return NULL;
}


/*
 * Print the usernames of all users in the list starting at curr.
 * Names should be printed to standard output, one per line.
 */
void list_users(const User *curr) {
    printf("User List: \n");
    while (curr != NULL){
        printf("\t%s\n", curr->name);
        curr = curr->next;
    }
}

/*
 * Change the filename for the profile pic of the given user.
 *
 * Return:
 *   - 0 on success.
 *   - 1 if the file does not exist or cannot be opened.
 *   - 2 if the filename is too long.
 */
int update_pic(User *user, const char *filename) {
    FILE *file = fopen(filename, "r");
    if (file == NULL) {
        return 1;
    }
    if (strlen(filename) >= MAX_NAME) {
        return 2;
    }
    strcpy(user->profile_pic, filename);
    fclose(file);
    return 0;

}


/*
 * Make two users friends with each other.  This is symmetric - a pointer to
 * each user must be stored in the 'friends' array of the other.
 *
 * New friends must be added in the first empty spot in the 'friends' array.
 *
 * Return:
 *   - 0 on success.
 *   - 1 if the two users are already friends.
 *   - 2 if the users are not already friends, but at least one already has
 *     MAX_FRIENDS friends.
 *   - 3 if the same user is passed in twice.
 *   - 4 if at least one user does not exist.
 *
 * Do not modify either user if the result is a failure.
 * NOTE: If multiple errors apply, return the *largest* error code that applies.
 */
int make_friends(const char *name1, const char *name2, User *head) {
    User *user1 = NULL;
    User *user2 = NULL;

    // Find the two users with the given names
    User *current = head;
    while (current != NULL) {
        if (strcmp(current->name, name1) == 0) {
            user1 = current;
        } if (strcmp(current->name, name2) == 0) { 
            user2 = current;
        }
        if (user1 != NULL && user2 != NULL) {
            break;
        }
        current = current->next;
    }

    // Check if at least one user does not exist and return 4 if so is true
    if (user1 == NULL || user2 == NULL) {
        return 4;
    }

    // Check if the same user is passed in twice and return 3 if so is true
    if (user1 == user2) { 
        return 3;
    }

    // Create marker to be used to check if already friends
    int marker = 0;
    int friend_count1 = MAX_FRIENDS;
    int friend_count2 = MAX_FRIENDS;
    // Check if the two users are already friends and return 1 if so is true
    for (int i = 0; i < MAX_FRIENDS; i++) {
        if (user1->friends[i] == user2) {
            marker = 1;
        }
        if (user2->friends[i] == user1) {
            marker = 1;
        }
        if (user1->friends[i] != NULL) {
            friend_count1--;
        }
        if (user2->friends[i] != NULL) {
            friend_count2--;
        }
    }

    // Check if at least one user has MAX_FRIENDS friends
    if (friend_count1 == 0 || friend_count2 == 0) {
        return 2;
    }


    // Return 1 if users are already friends and none of the other error return statements apply
    if (marker == 1) return 1;

    // Make the two users friends with each other
    user1->friends[MAX_FRIENDS - friend_count1] = user2;
    user2->friends[MAX_FRIENDS - friend_count2] = user1;
    return 0;
}



/*
 * Print a user profile.
 * For an example of the required output format, see the example output
 * linked from the handout.
 * Return:
 *   - 0 on success.
 *   - 1 if the user is NULL.
 */
int print_user(const User *user) {
    if (user == NULL) {
        return 1;
    }
    if (user->profile_pic != NULL){
        FILE *fp;
        char line[100000];

        fp = fopen(user->profile_pic, "r");
        if (fp == NULL) {
            printf("Error opening file\n");
            return 1;
        }

        while (fgets(line, 10000, fp) != NULL) {
            printf("%s", line);
        }

        fclose(fp);
    }

    printf("\nName: %s\n", user->name);
    printf("------------------------------------------\n");
    printf("Friends:\n");
    for (int i = 0; i < MAX_FRIENDS; i++) {
        if (user->friends[i] == NULL) {
            break;
        }
        printf("%s\n", user->friends[i]->name);
    }
    printf("------------------------------------------\n");
    printf("Posts:\n");

    Post *curr = user->first_post;
    int counter = 1;
    while (curr != NULL){
        if (counter > 1){
            printf("\n\n===\n\n");
        }
        printf("From: %s\nDate: %s\n%s\n", curr->author, ctime(curr->date), curr->contents);
        curr = curr -> next;
        counter++;
    }
    printf("------------------------------------------\n");
    return 0;
}



/*
 * Make a new post from 'author' to the 'target' user,
 * containing the given contents, IF the users are friends.
 *
 * Insert the new post at the *front* of the user's list of posts.
 *
 * 'contents' is a pointer to heap-allocated memory - you do not need
 * to allocate more memory to store the contents of the post.
 *
 * Return:
 *   - 0 on success
 *   - 1 if users exist but are not friends
 *   - 2 if either User pointer is NULL
 */
int make_post(const User *author, User *target, char *contents) {

    if (author == NULL || target == NULL) {
        return 2;
    }
    bool is_friends = false;
    for (int i = 0; i < MAX_FRIENDS; i++) {
        if (target->friends[i] == author) {
            is_friends = true;
            break;
        }
    }

    if (!is_friends) {
        return 1;
    }

    Post *new_post = (Post *)malloc(sizeof(Post));
    strcpy(new_post->author, author->name);
    new_post->contents = contents;
    new_post->date = (time_t *)malloc(sizeof(time_t));
    time(new_post->date);

    new_post->next = target->first_post;
    target->first_post = new_post;

    return 0;
}



When creating a user profile the profile should be printed correctly after a user was added