#include "friends.h"
#include <string.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) {
    if(find_user(name, *user_ptr_add) != NULL){
      return 1;
    }
  else if(strlen(name) >= MAX_NAME){
    return 2;
  }
  else{
    User *curr = *user_ptr_add;
    while(curr->next != NULL){
      curr = curr->next;
    }
    User *new_user = malloc(sizeof(User));
    if(new_user==NULL){
      exit(1);
    }
    strcpy(new_user->name, name);
    strcpy(new_user->profile_pic, "");
    new_user->first_post = NULL;
    for (int i = 0; i < MAX_FRIENDS; i++) {
        new_user->friends[i] = NULL;
    }
    
    new_user->next = NULL;
    curr->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) {
    while (head != NULL) {
      if (strcmp(head->name, name) == 0){
        return (User *)head;
      }
      head = head->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->next != NULL){
    printf("	%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");
    int return_val;
    if (file == NULL) {
      return_val = 1;
    }
    else if(strlen(filename) >= MAX_NAME){
      return_val = 2;
    }
    else{
      return_val = 0;
      strcpy(user->profile_pic, filename);
    }
    fclose(file);
    return return_val;
}


/*
 * 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) {
  if((find_user(name1, head) == NULL) || (find_user(name2, head) == NULL)){
    return 4;
  }
  else if(strcmp(name1, name2) == 0){
    return 3;
  }
  else{
    User *user1 = find_user(name1, head);
    User *user2 = find_user(name2, head);
    
    int existing_name_count = 0;
    int friends1_size = 0;
    int friends2_size = 0;
    
    //checking friends list
    for(int i = 0; i < MAX_FRIENDS; i++){
      if((strcmp(user1->friends[i]->name, name2) == 0) || (strcmp(user2->friends[i]->name, name1) == 0)){
        existing_name_count = existing_name_count + 1;
      }
      if(user1->friends[i] != NULL){
        friends1_size = friends1_size + 1;
      }
      if(user2->friends[i] != NULL){
        friends2_size = friends2_size + 1;
      }
    }
    if(existing_name_count == 0){
      if((friends1_size == MAX_FRIENDS) || (friends2_size == MAX_FRIENDS)){
        return 2;
      }
      else{
        user1->friends[friends1_size] = user2;
        user2->friends[friends2_size] = user1;
        return 0;
      }
    }
    else{
      return 1;
    }
  }
  return -1;
}


/*
 * 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;
    }
    else{
      //Printing profile picture
      FILE *file = fopen(user->profile_pic, "r");
      if(file!=NULL){
        char line[500];
        while (fgets(line, sizeof(line), file)) {
        printf("%s", line);
          }
      }
      fclose(file);
      //Printing name
      printf("%s %s\n%s\n", "Name: ", user->name, "------------------------------------------");
      //Printing friends
      printf("%s\n", "Friends:");
      int i = 0;
      while(user->friends[i] != NULL){
        printf("%s\n", user->friends[i]->name);
      }
      printf("%s\n", "------------------------------------------");
      //Printing posts
      printf("%s\n", "Posts:");
      Post *curr_post = user->first_post;
      while(curr_post != NULL){
        printf("%s%s\n", "From: ", curr_post->author);
        printf("%s%s\n", "Date: ", ctime(curr_post->date));
        printf("\n%s\n", curr_post->contents);
        if(curr_post->next != NULL){
          printf("\n===\n\n");
        }
        curr_post = curr_post->next;
      }
      printf("%s\n", "------------------------------------------");
    }
    return -1;
}


/*
 * 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;
    }
    else{
      //Checking for friendship
      int friends = 0;
      for(int i = 0; i < MAX_FRIENDS; i++){
        if((strcmp(author->friends[i]->name, target->name) == 0) || (strcmp(target->friends[i]->name, author->name) == 0)){
          friends = friends + 1;
        }
      }
      // they are friends
      if(friends > 0){
        Post *new_post = malloc(sizeof(Post));
        if(new_post == NULL){
          exit(1);
        }
        strcpy(new_post->author, author->name);
        new_post->contents = contents;
        time(new_post->date);
        new_post->next = target->first_post;
        target->first_post = new_post;
        return 0;
      }
      // not friends
      else{
        return 1;
      }
    }
}


/*
 * From the list pointed to by *user_ptr_del, delete the user
 * with the given name.
 * Remove the deleted user from any lists of friends.
 *
 * Return:
 *   - 0 on success.
 *   - 1 if a user with this name does not exist.
 */
int delete_user(const char *name, User **user_ptr_del) {
    if(find_user(name, *user_ptr_del) == NULL){
      return 1;
    }
  else{
    User *user = find_user(name, *user_ptr_del);
    //removing target from list of users
    User *curr = *user_ptr_del;
    User *curr2 = *user_ptr_del;
    User *prev_from_target;
    User *target;
    while(curr!=NULL){
        if(strcmp(curr->next->name, name)==0){
          prev_from_target = curr;
          target = curr->next;
        }
        curr = curr->next;
      }
    prev_from_target->next = target->next;
    target->next = NULL;

    //removing target from list of friends
    while(curr2!=NULL){
      for(int i = 0; i < MAX_FRIENDS; i++){
        //user in friends list
        if(strcmp(curr2->friends[i]->name,name)==0){
          //shifting down friends list to overlap/delete the target user
          for(int j = i; i < (MAX_FRIENDS - 1); j++){
            curr2->friends[j] = curr2->friends[j + 1];
          }
          curr2->friends[MAX_FRIENDS - 1] = NULL;
        }
      }
      curr2 = curr2->next;
    }

    //freeing dynamically allocated memory
    free(user);
    Post *curr_post = user->first_post;
    while(curr_post!=NULL){
      free(curr_post);
      curr_post = curr_post->next;
    }
    return 0;
  }
}



adding david to users