/* stateNodeTest.c */


/*
 * gcc -o stateNodeTest stateNodeTest.c stateNode.c
 */


#include "stateNode.h"
#include <stdlib.h>


/*
 * Brich Programm vorzeitig ab, falls kein Speicherplatz alloziert
 * werden konnte.
 * (Brachial-Massnahme).
 */
void exitOnObjectCouldNotBeCreated() {
  printf("Fatal Error: Object could not be allocated.\n");
  exit(-1);
}



/*
 * Melde, dass das der Knoten bereits verbunden ist.
 */
void warningOnObjectAlreadyConnected() {
  printf("Warning: Object is already connected.\n");
}



/*
 * Erstelle ein Zustandsdiagramm wie mit dem Diagramm der Aufgabenstellung
 * vorgegeben.
 * Melde Erfolg (TRUE), oder Misserfolg (FALSE).
 */
boolean gangOfFour(StateNode **stateNodeArray) {
  if (!(stateNodeArray[0] = createStateNode("S 0"))) return FALSE;
  if (!(stateNodeArray[1] = createStateNode("S 1"))) return FALSE;
  if (!(stateNodeArray[2] = createStateNode("S 2"))) return FALSE;
  if (!(stateNodeArray[3] = createStateNode("S 3"))) return FALSE;

  if (!(connectStateNode(stateNodeArray[1], stateNodeArray[0]))) return FALSE;
  if (!(connectStateNode(stateNodeArray[2], stateNodeArray[0]))) return FALSE;
  if (!(connectStateNode(stateNodeArray[0], stateNodeArray[1]))) return FALSE;
  if (!(connectStateNode(stateNodeArray[2], stateNodeArray[1]))) return FALSE;
  if (!(connectStateNode(stateNodeArray[3], stateNodeArray[1]))) return FALSE;
  if (!(connectStateNode(stateNodeArray[0], stateNodeArray[2]))) return FALSE;
  if (!(connectStateNode(stateNodeArray[1], stateNodeArray[3]))) return FALSE;
  if (!(connectStateNode(stateNodeArray[2], stateNodeArray[3]))) return FALSE;

  return TRUE;
}



/*
 * Nehme Tests vor.
 */
int main() {
  // Lege drei Knoten an:
  StateNode *sn0 = createStateNode("State Node 0");
  StateNode *sn1 = createStateNode("State Node 1");
  StateNode *sn2 = createStateNode("State Node 2");

  // Stelle Knoten oder Misserfolg am stdout dar:
  if (sn0) {
    printStateNode(sn0);
  }
  else {
    exitOnObjectCouldNotBeCreated();
  }
  if (sn1) {
    printStateNode(sn1);
  }
  else {
    exitOnObjectCouldNotBeCreated();
  }
  if (sn2) {
    printStateNode(sn1);
  }
  else {
    exitOnObjectCouldNotBeCreated();
  }

  // Verbinde Knoten:
  if (!connectStateNode(sn1, sn0)) {
    warningOnObjectAlreadyConnected();
  }
  printStateNode(sn0);
  if (!connectStateNode(sn2, sn0)) {
    warningOnObjectAlreadyConnected();
  }
  printStateNode(sn0);
  // Versuche eine Verbindung ein zweites Mal:
  if (!connectStateNode(sn2, sn0)) {
    warningOnObjectAlreadyConnected();
  }
  printStateNode(sn0);

  // Teste, ob Verbindung besteht und melde Resultat am stdout:
  printf("State Node sn2 <-- sn0 connected: %s.\n", isStateNodeConnected(sn2, sn0) ? "yes" : "no");
  printf("State Node sn0 <-- sn2 connected: %s.\n", isStateNodeConnected(sn0, sn2) ? "yes" : "no");

  // Loese Verbindungen:
  if (disconnectStateNode(sn1, sn0)) {
    printf("Disconnecting dest: sn1, source: sn0 successful\n");
  }
  else {
    printf("Disconnecting dest: sn1, source: sn0 failed\n");
  }
  printStateNode(sn0);
  // Versuche ein zweites Mal:
  if (disconnectStateNode(sn1, sn0)) {
    printf("Disconnecting dest: sn1, source: sn0 successful\n");
  }
  else {
    printf("Disconnecting dest: sn1, source: sn0 failed\n");
  }
  printStateNode(sn0);

  // Loesche Knoten:
  deleteStateNode(sn0);
  sn0 = NULL;
  deleteStateNode(sn1);
  sn1 = NULL;
  deleteStateNode(sn2);
  sn2 = NULL;


  // Aktiviere Gang of Four:
  {
    int i;
    StateNode *sn0, *sn1, *sn2, *sn3;
    StateNode *stateNodeArray[] = {sn0, sn1, sn2, sn3,};

    if (!gangOfFour(stateNodeArray)) {
      puts("Could not create Gang of Four.");
      return -1;
    }

    // Stelle Verbindungen dar:
    for (i = 0; i < sizeof(stateNodeArray) / sizeof(StateNode *); i++) {
      printStateNode(stateNodeArray[i]);
    }
  }
  return 0;
}
