// sorted_list_solution2.c - more flexible than the first solution

#include "dl_list.h"
#include "simple_input_handling.h"
#include "error_handling.h"
#include "sorted_list_solution2.h"

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

DLListIterator *iterator_ = NULL;
int num_elements_ = 0;

//------------------------------------------------------------
int main()
{
  iterator_ = newDLListIterator(newDLList());
  setPrompt("list control> ");
  addToDispatcher('i',callInsertNumber);
  addToDispatcher('d',callDeleteNumber);
  addToDispatcher('s',showList);
  addToDispatcher('r',showReverseList);
  addToDispatcher('h',showHelp);
  addToDispatcher('c',calculateSum);
  addToDispatcher('q',quitProgram);
  run();
  return(0);
}

//------------------------------------------------------------
void callInsertNumber(char *input_line)
{
  // for demonstration purposes we do everything by hand here
  // and to make things easier we don't interpret negative numbers
  char *help = input_line;
  int number = 0;

  while(*++help) // look for the start of the number
  {
    if ((*help >= '0') && (*help <= '9'))
      break;
    if (*help != ' ') // nothing else than spaces allowed here
    {
      commandNotRecognized(input_line);
      return;
    }
  }
  while((*help >= '0') && (*help <= '9')) // extract the number
    number = (number * 10) + (*help++ - '0');
  insertNumber(number); // remainder of the line is the description
}


//------------------------------------------------------------
void callDeleteNumber(char *input_line)
{
  // for demonstration purposes we do everything by hand here
  char *help = input_line;
  unsigned index = 0;

  while(*++help) // look for the start of the number
  {
    if ((*help >= '0') && (*help <= '9'))
      break;
    if (*help != ' ') // nothing else than spaces allowed here
    {
      commandNotRecognized(input_line);
      return;
    }
  }
  while((*help >= '0') && (*help <= '9')) // extract the number
    index = (index * 10) + (*help++ - '0');
  // here we should check, whether something unallowed follows,
  // I leave this up to you
  deleteNumber(index);
}

//------------------------------------------------------------
// creates a new node and inserts it in the correct position
// according to the given priority
void insertNumber(int number)
{
  int *num = (int*)setCurrentToFirstElement(iterator_);
  int *insert = malloc(sizeof(int));
  if (!insert)
    exitOnFatalErrorOutOfMemory();
  *insert = number;

  while(num && (*num <= number))
    num = (int*)gotoNextElement(iterator_);
  if (!num) // either first element in list or last element
  {
    setCurrentToLastElement(iterator_);
    insertElementAfterCurrent(iterator_,insert);
  }
  else
    insertElementBeforeCurrent(iterator_,insert);
  num_elements_++;
}

//------------------------------------------------------------
void deleteNumber(unsigned index)
{
  int *current = (int*)setCurrentToFirstElement(iterator_);

  while(current && index--)
    current = gotoNextElement(iterator_);
  if (!current)
  {
    elementWithGivenIndexNotFound(index);
    return;
  }
  deleteCurrentElement(iterator_);
  num_elements_--;
}

//------------------------------------------------------------
void showList(char *input_line)
{
  int *current = (int*)setCurrentToFirstElement(iterator_);
  unsigned index = 0;

  while(current)
  {
    printf("(%u: %d)",index++,*current);
    current = (int*)gotoNextElement(iterator_);
  }
  printf("\n");
}

//------------------------------------------------------------
void showReverseList(char *input_line)
{
  int *current = (int*)setCurrentToLastElement(iterator_);
  unsigned index = num_elements_;

  while(current)
  {
    printf("(%u: %d)",--index,*current);
    current = (int*)gotoPreviousElement(iterator_);
  }
  printf("\n");
}

//------------------------------------------------------------
void showHelp(char *input_line)
{
  printf("accepted commands:\n");
  printf("i <number>: insert <number>\n");
  printf("d <index>: delete number with index <index>\n");
  printf("s: show list\n");
  printf("r: show reverse list\n");
  printf("c: calculate sum\n");
  printf("h: show this help\n");
  printf("q: quit\n");
}

//------------------------------------------------------------
void calculateSum(char *input_line)
{
  int *current = (int*)setCurrentToFirstElement(iterator_);
  int sum = 0;

  while(current)
  {
    sum += *current;
    current = (int*)gotoNextElement(iterator_);
  }
  printf("%d\n",sum);
}

//------------------------------------------------------------
void quitProgram(char *input_line)
{
  exit(0);
}

//------------------------------------------------------------
void elementWithGivenIndexNotFound(unsigned index)
{
  printf("Error: element with index %d does not exist\n",index);
}
