#include <stdlib.h>

#include "list.h"
#include "error.h"

/***********************************************************************/
/* Fuegt ein beliebiges Objekt in eine Liste ein, es wird ein Zeiger   */
/* auf ein Objekt benoetigt                                            */
/* Es wird in eine doppelt verkettete Liste eingefuegt, deren Anfang   */
/* und ende jeweils auch ubergeben werden muessen                      */
/* Da die ersten und letzten Listenelemente auch geaendert werden      */
/* muessen dies Zeiger auf die Listen sein.                            */
/***********************************************************************/
T_INT d_fuege_in_liste_ein( T_PVOID objekt, T_LISTE **erstes, T_LISTE **letztes, T_INT flag )
{
 T_LISTE *neues = NULL;
 T_LISTE *hilfe = *erstes;
 if ((erstes==NULL)||(letztes==NULL))
 {
  return T_NOT_OK;
 }
 neues = ( T_LISTE * )malloc( sizeof( T_LISTE ) );
 if ( neues == NULL )
 {
  return GENERIC_MEMORY_NOT_AVAILABLE;
 }
 if ( flag == DL_VORNE)
 {
  neues->position=0;
  while ( hilfe != NULL )
  {
   hilfe->position++;
   hilfe = (T_LISTE*) hilfe->naechstes;
  }
  neues->objekt = objekt;
  neues->letztes = NULL;
  neues->naechstes = *erstes;                        /* vorne einfuegen */
  if ( *letztes == NULL )
   *letztes = neues;
  if ( *erstes != NULL )
   ( *erstes )->letztes = neues;
  *erstes = neues;
 }
 if ( flag == DL_HINTEN)
 {
  neues->objekt = objekt;
  neues->letztes = *letztes;                        /* hinten einfuegen */
  neues->naechstes = NULL;
  neues->position=0;
  if ( *erstes == NULL )
  {
   *erstes = neues;
   neues->position=0;
  }
  if ( *letztes != NULL )
  {
   ( *letztes )->naechstes = neues;
   neues->position=( *letztes )->position+1;
  }
  *letztes = neues;
 }
 return T_OK;
}

/***********************************************************************/
/* Die entsprechende Funktion um ein Element aus der Liste zu entfernen*/
/***********************************************************************/
T_INT d_entferne_aus_liste( T_PVOID objekt, T_LISTE **erstes, T_LISTE **letztes, T_INT flag )
{
 T_LISTE *hilfe = *erstes;
 T_LISTE *dieses = NULL;
 while ( hilfe != NULL )
 {
  if ( hilfe->objekt == objekt )
  {
   dieses = hilfe;
   break;
  }
  hilfe = (T_LISTE*)hilfe->naechstes;
 }
 if ( dieses == NULL )
 {
  return LIST_ELEMENT_NOT_FOUND;
 }
 /* Element der Liste bereinigen, sieht aufwendig aus, aber nur weil */
 /* verschiedene Faelle beruecksichtigt werden muessen               */
 hilfe=dieses;
 if (flag==DL_CLEAN_UP)
 {
  while ( hilfe != NULL )
  {
   hilfe->position--;
   hilfe = (T_LISTE*)hilfe->naechstes;
  }
 }
 if ( dieses != *letztes )
 {
  if ( dieses != *erstes )
  {
   hilfe = (T_LISTE*)dieses->letztes;
   hilfe->naechstes = dieses->naechstes;
   hilfe = (T_LISTE*)dieses->naechstes;
   hilfe->letztes = dieses->letztes;
  }
  else
  {
   *erstes = (T_LISTE*)dieses->naechstes;
   (*erstes)->letztes = NULL;
  }
 }
 else
 {
  if ( dieses != *erstes )
  {
   hilfe = (T_LISTE*)dieses->letztes;
   hilfe->naechstes = NULL;
   *letztes = (T_LISTE*)dieses->letztes;
  }
  else
  {
   *erstes = NULL;
   *letztes = NULL;
  }
 }
 free( dieses );
 return T_OK;
}

/***********************************************************************/
/* gibt die Anzahl der Listenelemente zurueck, Eingabeparameter ist im */
/* allgemeinen, das erste element der Liste, da dies zur               */
/* Anzahlberechnung verwendet wird                                     */
/***********************************************************************/
T_INT d_anzahl_liste( T_LISTE *liste )
{
 T_INT i = 0;
 while ( liste != NULL )
 {
  i++;
  liste = (T_LISTE*)liste->naechstes;
 }
 return i;
}

/***********************************************************************/
/* Wandelt eine Liste in ein entsprechende Array, die Liste wird nicht */
/* geloescht                                                           */
/* Platz fuer array wird mit malloc ermittelt                          */
/***********************************************************************/
T_PVOID *d_liste_to_array( T_LISTE *liste )
{
 T_LISTE *hilfe = liste;
 T_PVOID *array = NULL;
 T_INT i = 0;
 T_INT anzahl = d_anzahl_liste(liste);
 if ( anzahl == 0 )
 {
  return NULL;
 }
 array = ( T_PVOID  *) malloc( anzahl * sizeof( T_PVOID  ) );
 if ( array == NULL )
 {
  return NULL;
 }
 while ( hilfe != NULL )
 {
  array[ i++ ] = hilfe->objekt;
  hilfe = (T_LISTE*)hilfe->naechstes;
 }
 return array;
}

/***********************************************************************/

T_LISTE *d_get_list_pos(T_PVOID objekt, T_LISTE *erstes)
{
 while (erstes!=NULL)
 {
  if (erstes->objekt==objekt)
  {
   return erstes;
  }
  erstes=(T_LISTE*)erstes->naechstes;
 }
 return NULL;
}

/***********************************************************************/
// liefert werte,
// erstes zuerst in liste == 1
// erstes gleich zweites == 0
// erstes danach in der liste  -1
T_INT d_vergleich(T_PVOID objekt1,T_PVOID objekt2, T_LISTE *erstes)
{
 while (erstes!=NULL)
 {
  if (erstes->objekt==objekt1)
   if (erstes->objekt==objekt2)
   {
    return 0;
   }
   else
   {
    return 1;
   }
  else
   if (erstes->objekt==objekt2)
   {
    return -1;
   }
  erstes=(T_LISTE*)erstes->naechstes;
 }
 return 2;
}

/***********************************************************************/
T_INT d_fuege_in_liste_ein_past_position(T_PVOID welches, T_PVOID wohin, T_LISTE **erstes, T_LISTE **letztes)
{
 T_LISTE *hilfe = NULL;
 T_LISTE *naechstes = NULL;
 T_LISTE *hilfe2 = NULL;
 T_LISTE *neues = NULL;
 if ((erstes==NULL)||(letztes==NULL))
 {
  return T_NOT_OK;
 }
 neues = ( T_LISTE * )malloc( sizeof( T_LISTE ) );
 if ( neues == NULL )
 {
  return GENERIC_MEMORY_NOT_AVAILABLE;
 }
 hilfe=d_get_list_pos(wohin,*erstes);
 if (hilfe==NULL)
 {
  return GENERIC_MEMORY_NOT_AVAILABLE;
 }
 naechstes=(T_LISTE*)hilfe->naechstes;
 neues->objekt = welches;
 neues->letztes = hilfe;                        /* hinten einfuegen */
 neues->naechstes = naechstes;
 neues->position=-1;
 if ( *erstes == NULL )
 {
  *erstes = neues;
  neues->position=0;
 }
 if ( *letztes == NULL )
 {
  *letztes=neues;
 }
 if (hilfe!=NULL)
 {
  hilfe->naechstes=neues;
  neues->position=hilfe->position+1;
 }
 if (naechstes!=NULL)
 {
  naechstes->letztes=neues;
  hilfe2=naechstes;
  while ( hilfe2 != NULL )
  {
   hilfe2->position++;
   hilfe2 = (T_LISTE*)hilfe2->naechstes;
  }
 }
 else // dann ist hilfe das letzte gewesen
 {
  *letztes=neues;
 }

 return T_OK;
}

/***********************************************************************/

T_INT d_vertausche_hoch(T_PVOID objekt,T_LISTE *liste)
{
 liste=d_get_list_pos(objekt,liste);
 if ((liste!=NULL)&&(objekt!=NULL)&&(liste->letztes!=NULL))
 {
  liste->objekt=((T_LISTE *)(liste->letztes))->objekt;
  ((T_LISTE *)(liste->letztes))->objekt=objekt;
  return T_OK;
 }
 return T_NOT_OK;
}

/***********************************************************************/

T_INT d_vertausche_runter(T_PVOID objekt,T_LISTE *liste)
{
 liste=d_get_list_pos(objekt,liste);
 if ((liste!=NULL)&&(objekt!=NULL)&&(liste->naechstes!=NULL))
 {
  liste->objekt=((T_LISTE *)(liste->naechstes))->objekt;
  ((T_LISTE *)(liste->naechstes))->objekt=objekt;
  return T_OK;
 }
 return T_NOT_OK;
}
