/*
 *   UMS-Handling
 *
 * SetAktMsgGroup -- User-Gruppenwunsch setzen
 * FreeGroupList -- "Gruppen"-Liste löschen
 * FreeMsgList -- Liste mit Nachrichtennummern löschen
 *
 * MakeGroupList -- lowlevel "Gruppen"-Liste erzeugen
 * MakeMsgList -- lowlevel "Nachrichten"-Liste erzeugen
 * IsGroupInGlobMsgList -- Tool
 *
 * SetGlobMsgNum -- setzt globale Variable GlobMsgNum
 * GetGlobMsgNum -- holt globale Variable GlobMsgNum
 * SetGlobMsgGroup -- setzt NAME der im RAM gelisteten globalen Gruppe
 * SetGlobMsgList -- setzt neue LISTE, löscht alte
 *
 * GetGroupList -- gibt Zeiger auf Gruppenliste oder NULL zurück
 * GetMsgList -- holt Liste aller Nachrichten aus <group>
 *
 * GetNewGroup -- (obsolet) richtet neue Gruppenliste ein
 *
 * ResetNBDisplay -- löscht GUI Anzeigen und interne Listen
 */


/*
 * SetAktMsgGroup -- User-Gruppenwunsch setzen
 */

STRPTR SetAktMsgGroup (STRPTR name)
{
  if (AktMsgGroup)
    {
      free (AktMsgGroup);
      AktMsgGroup = NULL;
    }

  AktMsgGroup = strdup (name);	// unabhängig machen!!!

  return (AktMsgGroup);
}

STRPTR GetAktMsgGroup (void)
{
  if (AktMsgGroup)
    {
      return(AktMsgGroup);
    }
  else
    {
    return (NULL);
    }
}



/*
 *   FreeGroupList -- "Gruppen"-Liste löschen
 */

void
FreeGroupList (void)
{
  if (GlobGroupList)
    {
      KillListEntries(gad_group);   /* GUI-Listviews leeren */
      KillListEntries(gad_message);
      FreeMyList (GlobGroupList); /* interne Liste löschen */

      GlobGroupList = NULL;
    }
}

/*
 * FreeMsgList -- Liste mit Nachrichtennummern löschen
 */

void
FreeMsgList (void)
{
  if (GlobMsgList)
    {
      KillListEntries(gad_message); /* locken, löschen, unlocken */

      /* danach STRPTR löschen */
      SetGlobMsgList (NULL);	/* Globale korrigieren */
      SetGlobMsgGroup (NULL);	/* String löschen */
    }
}

/* todo: Fehlerbehandlung wg. Speichermangel, sonst Guru! / */

/*
 * MakeGroupList -- "Gruppen"-Liste erzeugen
 *
 * Durchsucht Messagebase und erzeugt eine Liste verfügbarer Netgroups.
 * todo: umssupport.library einbauen
 *
 * INPUTS:
 *   account -- UMS-Handle
 *   list    -- ein mit NewList() initialisierter Exec-Listheader
 *
 * RESULT:
 *   TRUE --  List-Nodes wurden korrekt erzeugt.
 *   FALSE -- Fehler, meistens Speichermangel. Unvollständige Liste ist
 *            eventuell in *list vorhanden, Nodes müssen
 *            von aufrufender Routine  gelöscht werden.
 */

BOOL
MakeGroupList (UMSUserAccount account, struct List *list)
{
  BOOL success = TRUE;		/* erfolgreich oder Fehler? */
  STRPTR group = NULL;		/* Pointer to group name */
  STRPTR buffer = NULL;		/* Stringbuffer */
  UMSMsgNum num = 0;		/* Zwischenspeicher */
  UMSMsgNum count = 0;		/* zählt alle Messages in *group */

  UMSSelectTags (account, UMSTAG_SelReadLocal, TRUE,
		 UMSTAG_SelWriteLocal, TRUE,
		 UMSTAG_SelSet, 0,
		 UMSTAG_SelUnset, (1L << 0),
		 TAG_DONE);

  /* Erste Gruppe: alle privaten Nachrichten */

  if (buffer = malloc (100))
    {
      group = strdup ("");
      if (group)
	{
	  /* Setze local bit 0 in allen Nachrichten OHNE ViewAccess */
	  /* Damit werden diese Nachrichten von der weiteren */
	  /* Bearbeitung ausgeschlossen. */


	  UMSSelectTags (account, UMSTAG_SelWriteLocal, TRUE,
			 UMSTAG_SelSet, (1L << 0),
			 UMSTAG_SelQuick, TRUE,
			 UMSTAG_SelMask, UMSUSTATF_ViewAccess,
			 UMSTAG_SelMatch, 0,
			 TAG_DONE);

	  /* es könnten nun auch andere Nachrichten ausgeschlossen */
	  /* werden, z.B. alle bereits gelesenen: */
	  /*   UMSUSTATF_Old = TRUE */

	  /* kludge */
	  if (GlobalFocus == NeueMsg)
	    {
	      count = UMSSelectTags (account,
				     UMSTAG_SelWriteLocal, TRUE,
				     UMSTAG_SelSet, (1L << 0),
				     UMSTAG_SelQuick, TRUE,
				     UMSTAG_SelMask, UMSUSTATF_Old,
				     UMSTAG_SelMatch, UMSUSTATF_Old,
				     TAG_DONE);
	    }

	  /* Hier beginnt der Aufbau der Gruppenliste */
	  /* die Messagebase wird durchsucht und für jede gefundene */
	  /* Gruppe ein Node in der Liste "list" erzeugt. */

	  for (;;)
	    {
	      /* Setze local bit 0 auf alle Nachrichten in group */
	      /* count liefert die Anzahl der gefundenen Messages in *group */

	      count = UMSSelectTags (account, UMSTAG_SelWriteLocal, TRUE,
				     UMSTAG_SelSet, (1L << 0),
				     UMSTAG_SelQuick, TRUE,
				     UMSTAG_WGroup, group,
				     TAG_DONE);

	      free (group);

	      /* Hole Messagenummer ...                           */
	      /* Suche eine Message mit local bit 0 NICHT gesetzt */

	      num = UMSSearchTags (account, UMSTAG_SearchLocal, TRUE,
				   UMSTAG_SearchMask, (1L << 0),
				   UMSTAG_SearchMatch, 0,
				   UMSTAG_SearchQuick, TRUE,
				   TAG_DONE);

	      if (!num)
		{
		  break;	// num == NULL, bedeutet Nachricht gibts nicht

		}

	      else		// alles OK...

		{
		  /* Hole Gruppenmame group */

		  if (!UMSReadMsgTags (account, UMSTAG_RMsgNum, num,
				       UMSTAG_RGroup, &group,
				       TAG_DONE))
		    {
		      CheckErr ();
		      success = FALSE;
		      break;
		    }
		  else
		    {
		      if (!(group = strdup (group)))
			{
			  success = FALSE;
			  break;
			}
		      else
			{
			  /* Gruppennamen-Ausgabe in einen Exec-Listnode */

/*
   sprintf(buffer,"%s", 
   count,

   UMSSelectTags(account,
   UMSTAG_SelQuick,      TRUE,
   UMSTAG_WGroup,        group,
   TAG_DONE),

   group);

 */

			  success = AddName (list, group);	// Listeneintrag
			  /* KLUDGE, TODO */

			  UMSFreeMsg (account, num);
			  if (!success)
			    break;
			}

		    }		/* else */

		}

	    }			/* for (;;) */

	  if (success)
	    {
	      /* primitive Sortierroutine für Exec-Liste:           */
	      /* -- list   zeigt auf den zu sortierenden Listheader */
	      /* -- mycmp  ist Einsprungadresse einer Vergleichsfunktion */
	      listsort (list, mycmp);

	      GetMyListNames (list, gad_group);	/* fülle BOOPSI Listview */

	    }
	  else
	    {
	      /* überflüssig */
	      success = FALSE;
	    }


	}			/* group */
      else
	{
	  success = FALSE;
	}

      free (buffer);
    }
  else				// !buffer

    {
      success = FALSE;
    }

  if (!success)
    ShowError ("FEHLER -- möglicherweise inkonsistente Gruppenliste \n");

  return (success);
}

/*
 * MakeMsgList -- erzeugt eine Liste mit Nachichtennummern
 *
 * Durchsucht Messagebase und erzeugt eine Msg-Liste
 *
 * Inhalt:
 *       - Name-String für Gadtools-Listview
 *       - UMS-MsgNr für UMS-Library
 *
 *
 * INPUTS
 * - account:  UMS-User-account
 * - list:     ein initialisiter Exec-Listheader für Msg-Liste
 * - group:    (STRPTR) Gruppe, für die Msg-Liste gebaut wird.
 *             todo: template und Umssupport
 * - Focus:    (LONG) Einschränkung auf bestimmte Messages. (kludge)
 *
 * todo: Hier könnte die umssupport.library benutzt werden!
 * todo1: Dann sind userkonfigurierbare Listen möglich ("Templates")
 * todo2: Parameter, besonders die Globals müssen weg! (GlobalFocus)
 * siehe auch Textfile <Neue Datenstrukturen>
 */

BOOL
MakeMsgList (UMSUserAccount account, struct List * list, STRPTR group, LONG Focus)
{
  STRPTR buffer = NULL;
  UMSMsgNum num = 0;
  LONG myMaximumMsg = 0xffffff;	// wieviel Nachrichten höchstens selektiert?

  BOOL success = TRUE;
  LONGBITS mySearchMatch = NULL;

  STRPTR msgFrom, msgSubject;	// diese Variablen werden eingelesen

  LONG *msgTextLen;
  LONG SearchLast = 0;


  /* Initialisierung: lösche alle Lokal bzw. Login-Flags */
  UMSSelectTags (account, UMSTAG_SelReadLocal, TRUE,
		 UMSTAG_SelWriteLocal, TRUE,
		 UMSTAG_SelSet, 0,      /* kein Flag setzen */
		 UMSTAG_SelUnset, ~0,	/* alle Flags löschen (32bit!) */
		 TAG_DONE);

/* Focus bearbeiten */
  switch (Focus)
    {
    case (AlleMsg):
      {
	mySearchMatch = (1L << 1);
	break;
      }

    case (NeueMsg):
      {
	mySearchMatch = (1L << 0) | (1L << 1);
	break;
      }

    default:			/* kludge , todo */
      {
	if (Focus >= 10)
	  {
	    mySearchMatch = (1L << 1);
	    myMaximumMsg = Focus;
	  }
	else
	  ShowError ("Fehler\n");
	break;
      }
    }				/* switch (Focus) */

#define UMSMASK_NEW_MESSAGES  UMSUSTATF_ViewAccess | UMSUSTATF_PostPoned | UMSUSTATF_Old

  if (buffer = malloc (150))
    {
      /* wähle aus: alle neuen Nachrichten: */
      num = UMSSelectTags (account,
                           UMSTAG_SelMask, UMSMASK_NEW_MESSAGES,
			   UMSTAG_SelMatch, UMSUSTATF_ViewAccess,
			   UMSTAG_SelWriteLocal, TRUE,
			   UMSTAG_SelSet, (1L << 0),
			   UMSTAG_SelUnset, 0,
			   TAG_DONE);

      /* wähle aus: alle Nachrichten mit gleicher <group> */
      num = UMSSelectTags (account, UMSTAG_WGroup, group,
			   UMSTAG_SelWriteLocal, TRUE,
			   UMSTAG_SelQuick, TRUE,
			   UMSTAG_SelSet, (1L << 1),
			   UMSTAG_SelUnset, 0,
			   TAG_DONE);

      /* wähle aus: letzte 25 Nachrichten einer <group> */
      if (Focus >= 10)
	{
	  LONGBITS myNewSearchMatch = (1L << 2);	// temporär
	  LONG count = myMaximumMsg;

	  num = 0x7fffffff;	/* LONG_MAX */

	  do
	    {
	      num = UMSSearchTags (account,
				   UMSTAG_SearchLocal, TRUE,
				   UMSTAG_SearchMask, (1L << 1),	/* ALLE msg in group */
				   UMSTAG_SearchMatch, (1L << 1),
				   UMSTAG_SearchDirection, -1,	/* rückwärts */
				   UMSTAG_SearchLast, num,	/* welche war schon */
				   TAG_DONE);
	      if (num)
		{
		  if (!UMSSelectTags (account,
				      UMSTAG_SelMsg, num,
				      UMSTAG_SelWriteLocal, TRUE,
				      UMSTAG_SelSet, (1L << 2),
				      UMSTAG_SelUnset, 0,
				      TAG_DONE))
		    {
		      CheckErr ();
		    }

		  count = count - 1;
		}
	      else
		{
		  CheckErr ();
		  count = 0;
		}
	      printf ("Letzte25   num %ld, count %ld\n", num, count);
	    }
	  while (count);

	  mySearchMatch = myNewSearchMatch;
	}

      while (num)		// solange != Null
	{
	  num = UMSSearchTags (account,
			       UMSTAG_SearchLast, SearchLast,
			       UMSTAG_SearchLocal, 0,
			       UMSTAG_SearchMask, mySearchMatch,
			       UMSTAG_SearchMatch, mySearchMatch,
			       TAG_DONE);
	  if (num)
	    {
	      success = UMSReadMsgTags (account,
					UMSTAG_RMsgNum, num,
					UMSTAG_RFromName, &msgFrom,
					UMSTAG_RTextLength, &msgTextLen,
					UMSTAG_RSubject, &msgSubject,
					UMSTAG_RNoUpdate, 1L,
					TAG_DONE);

	      if (success)
		{
                  BOOL result = TRUE;
                  ULONG flen = NULL;

                  #define STRSIZE 20
                  if ( strlen(msgFrom) > STRSIZE )
                     {
                     msgFrom[STRSIZE-1]='.';
                     msgFrom[STRSIZE-2]='.';
                     msgFrom[STRSIZE-3]='.';
                     }

		  sprintf (buffer, "%-20.20s %-.50s  (%ld)",
                           msgFrom, msgSubject, msgTextLen);

		  UMSFreeMsg (account, num);
                  //printf("+");
                  result = AddNameNum (list, buffer, num);
                  //printf("o ");

		  if (!result)
                    {
		    ShowError ("UMS_Handling:\nFehler bei AddNameNum!");
                    success = FALSE;
                    }
		}
	      else
		{
		  CheckErr ();
                  //printf("-  ");
		}

	      SearchLast = num;	// Nachricht (num) nicht mehr wählen
	    }

	}			//while

      free (buffer);
    }
  else
    {
    success = FALSE;
    }

  if (list)
  if (success)
    {
    //printf("\nUMSHandling: Starte Listsort (list, mycmp);\n");

    listsort (list, mycmp);

    //printf("\nUMSHandling: Starte GetMyListNames (list, gad_message);\n");

    GetMyListNames (list, gad_message);	/* fülle BOOPSI Listview */
    }
    else
    {
    ShowError("UMSHandling\nNicht gestartet: GetMyListNames");
    }

  printf ("Ende MakeMsgList, %s", success ? "mit Erfolg!\n" : "ohne Erfolg.\n");
  return (success);		// Dummy!!!
}

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

BOOL
IsGroupInGlobMsgList (STRPTR group)
{
// group -- neu einzurichtende Liste für Gruppe <group>
// GlobMsgGroup -- die möglicherweise schon (global) vorhandene Liste

  if (group)
    if (strcmp (group, GlobMsgGroup) == 0)	// beide Strings gleich?

      {
	return (TRUE);
      }
  return (FALSE);
}

/*
 * SetGlobMsgNum -- setzt globale Variable GlobMsgNum
 *
 *
 */

void
SetGlobMsgNum (UMSMsgNum myNum)
{
  /* Globale setzen (auf die jetzt angezeigte Message:)  */
  GlobMsgNum = myNum;
}

/*
 * GetGlobMsgNum -- holt globale Variable GlobMsgNum
 */

UMSMsgNum
GetGlobMsgNum (void)
{
  /* Globale MessageNr holen  */
  return (GlobMsgNum);
}

/*
 * SetGlobMsgGroup -- setzt Name der globalen Gruppe
 */

void
SetGlobMsgGroup (STRPTR group)
{
  if (GlobMsgGroup)
    {
      free (GlobMsgGroup);
      GlobMsgGroup = NULL;	/* NULL = es gibt keine MsgListe */
    }
  if (group)
    GlobMsgGroup = strdup (group);
}

/*
 * SetGlobMsgList -- setzt neue Liste, löscht alte
 */

void
SetGlobMsgList (List * list)
{
  if (GlobMsgList)
    {
      FreeMyList (GlobMsgList);
      GlobMsgList = NULL;
    }
  GlobMsgList = list;
}

/*-------------------------------------------------------------*/

/*
 * GetGroupList -- gibt Zeiger auf Gruppenliste oder NULL zurück
 */

struct List *
GetGroupList (UMSUserAccount account)
{
  struct List *list = NULL;

  if (!GlobGroupList)
    {
      /* baue neue Gruppenliste */

      if (list = AllocMem (sizeof (struct List), MEMF_PUBLIC | MEMF_CLEAR))
	{
	  NewList (list);	/* Init neuer Listheader */
	  MakeGroupList (account, list);	/* Einträge ... */
	  GlobGroupList = list;	/* Globaler Zeiger auf Listheader */
	}
      else
	ShowError ("GetGroupList: Speicher für Liste fehlt!");
    }
  else
/* verwende vorh. Gruppenliste */
    {
      list = GlobGroupList;	/* Globaler Zeiger auf Listheader */
    }
  return (list);
}


// todo: STRPTR group wird ein FILTERSTRING. (umssupport)

/*
 * GetMsgList -- holt Liste aller Nachrichten aus <group>
 *
 */

struct List *
GetMsgList (UMSUserAccount account, STRPTR group, LONG focus)
{
  struct List *list = NULL;
  BOOL success = TRUE;

  if (!(IsGroupInGlobMsgList (group)))
    {
      if (list = AllocMem (sizeof (struct List), MEMF_PUBLIC | MEMF_CLEAR))
	{
	  NewList (list);	// Init neuer Listheader
	  MakeMsgList (account, list, group, focus);

	  SetGlobMsgList (list);	/* alte Liste falls vorh. löschen, neue Liste setzen */
	  SetGlobMsgGroup (group);
	}
      else
	{
	  ShowError ("GetMsgList\nSpeicher ist voll!");
	  success = FALSE;
	}
    }
  else
    /* alte Liste verwenden */
    {
      list = GlobMsgList;
    }

  return (list);
}

/*
 * GetNewGroup -- richte neue Gruppe ein
 *
 * INPUTS
 * RESULT
 *   TRUE  -- neue Gruppe wurde gewählt
 *   FALSE -- keine neue Gruppe gewählt
 */

/*
BOOL
GetNewGroup (UMSUserAccount account)
{
  UMSMsgNum num = 0;
  struct List *list = NULL;
  struct MyNodes *myNode = NULL;
  BOOL success = TRUE;

  list = GetGroupList (account);
  return (success);
}
*/

/*
 * ResetNBDisplay -- löscht GUI Anzeigen und interne Listen
 * todo: zieht listview itemlist Gadgets den Boden unter den Füßen weg-
 */

void
ResetNBDisplay (void)
{
  /* todo: Gadgets löschen oder für ungültig erklären */
  FreeMsgList ();		/* lösche die interne Message-Liste */
  FreeGroupList ();		/* auch Gruppenliste löschen + GlobGroupName */

  /* Display löschen */
  InfoBarClear (Mywindow, infobar_h);	/* todo: Fensterlöschfunktion */
  DisplayTxt (txtfld, Mywindow, "<<Leeres Textfenster>>");
  SetGlobMsgNum (0);
}
