#pragma once
#include "stdafx.h" 

#include <iostream>
using namespace std;

#include <InOutGraph.h>

InOutGraph::InOutGraph()
{
  for (NodeIdT nodeCounter=0; nodeCounter<MAX_NODES; nodeCounter++) {
    node[nodeCounter] = false;
  };
};


NodeIdT InOutGraph::insertNode()
{
  NodeIdT searchCursor=0;

  while (searchCursor<MAX_NODES && node[searchCursor]) {
    searchCursor++;
  };

  if (searchCursor<MAX_NODES) {
    node[searchCursor] = true;
    firstFreeIn[searchCursor]=0;
    firstFreeOut[searchCursor]=0;
  } else {
    cerr << "No nodes left!" << endl;
  };
  return searchCursor;
};


void InOutGraph::deleteNode( NodeIdT victim )
{
  if (victim<MAX_NODES) {
    // alle ein- und auslaufenden Kanten loeschen
    while (firstFreeOut[victim]>0) {
      deleteEdge(victim, out[victim][0]);
      /// es waere effizienter, hier die Kanten direkt zu loeschen
    };
    while (firstFreeIn[victim]>0) {
      deleteEdge(in[victim][0], victim);
    };
    node[victim] = false;
  };
};


void InOutGraph::deleteEdge( NodeIdT from, NodeIdT to )
{
  // Suche in der Adjazenzliste von from nach to
  NodeIdT edgeCursor;
  edgeCursor = 0;
  while (edgeCursor<firstFreeOut[from] && out[from][edgeCursor]!=to) {
    edgeCursor++;
  };
  if (out[from][edgeCursor] == to) {
    /* Erniedrige Anzahl Kanten und ersetze Kante durch letzte der Liste */
    firstFreeOut[from]--;
    out[from][edgeCursor] = out[from][firstFreeOut[from]];
  };

  edgeCursor = 0;
  while (edgeCursor<firstFreeIn[to] && in[to][edgeCursor]!=from) {
    edgeCursor++;
  };
  if (in[to][edgeCursor] == from) {
    /* Erniedrige Anzahl Kanten und ersetze Kante durch letzte der Liste */
    firstFreeIn[to]--;
    in[to][edgeCursor] = in[to][firstFreeIn[to]];
  };
};


void InOutGraph::insertEdge( NodeIdT from, NodeIdT to )
{
  bool found = false;
  NodeIdT edgeCursor;
  // Suche in der Adjazenzliste von from nach to
  for (edgeCursor=0; edgeCursor<firstFreeOut[from]; edgeCursor++) {
    if (out[from][edgeCursor] == to) {
      found = true;
      break;
    };
  };
  if (!found) {
    // Kante an Liste anfuegen
    out[from][firstFreeOut[from]] = to;
    firstFreeOut[from]++;

    // das gleiche fuer einlaufende Kanten
    in[to][firstFreeIn[to]] = from;
    firstFreeIn[to]++;
  };
};


void InOutGraph::print()
{
  NodeIdT nodeCursor, edgeCursor;
  cout << "Knoten: ";
  for (nodeCursor=0; nodeCursor<MAX_NODES; nodeCursor++) {
    if (node[nodeCursor]) {
      cout << nodeCursor << ", ";
    };
  };
  cout << endl;
  cout << "auslaufende Kanten:" << endl;
  for (nodeCursor=0; nodeCursor<MAX_NODES; nodeCursor++) {
    if (node[nodeCursor]) {
      for (edgeCursor=0; edgeCursor<firstFreeOut[nodeCursor]; edgeCursor++) {
	cout << "(" << nodeCursor << ", " << out[nodeCursor][edgeCursor] << ")" << endl;
      };
    };
  };
  cout << "einlaufende Kanten:" << endl;
  for (nodeCursor=0; nodeCursor<MAX_NODES; nodeCursor++) {
    if (node[nodeCursor]) {
      for (edgeCursor=0; edgeCursor<firstFreeIn[nodeCursor]; edgeCursor++) {
	cout << "(" << nodeCursor << ", " << in[nodeCursor][edgeCursor] << ")" << endl;
      };
    };
  };
};
