/*******
 * linked_list.h
 *
 * header file (API) for the code implemented in the linked_list.c library
 * Look there and in linked_list.py for more comments and descriptions.
 * 
 * Jim Mahoney | cs.bennington.college | MIT License | March 2021
 ******/

#ifndef LINKED_LIST_H    /* guard to ensure that this is only included once */
#define LINKED_LIST_H

typedef struct _mynode *mynode;
struct _mynode {  // named "mynode" so I can use "node" as a variable name.
  int value;
  mynode prev;
  mynode next;
};

typedef struct _linkedlist *linkedlist;
struct _linkedlist {
  mynode begin;
  mynode end;
  int length;
};

mynode new_mynode(int value);
void print_node(mynode self);

int size_recursive(mynode node); // forward length of linked list
int size_iterative(mynode node); // ditto; different implementation

linkedlist new_linkedlist(); 
int length(linkedlist self); // length of list using updated-as-we go property
int is_empty(linkedlist self);
void push_end(linkedlist self, mynode node); // push node onto the end
void push_begin(linkedlist self, mynode node); // push node onto the beginning
void push_end_value(linkedlist self, int value); // create node, push to end
void push_begin_value(linkedlist self, int value); // create node, push at begin
mynode pop_end(linkedlist self); // pop and return end node
mynode pop_begin(linkedlist self); // pop and return begin node
int pop_begin_value(linkedlist self); // pop begin node; return its value
int pop_end_value(linkedlist self); // pop end node; return its value
void insert_after(linkedlist self, mynode new_node, mynode node);
mynode find(linkedlist self, int value); // search from end and return node
void print_list(linkedlist self); // print values as i.e. "(1 2 3)"
void print_list_details(linkedlist self); // print all nodes and addresses
linkedlist new_counting_list(int size); // return list  1, 2, ..., size

// ---- tests ----

void ok(int boolean, char* message);
void linked_list_tests(); // test routines and print results

#endif /* !LINKED_LIST_H */