#include <iostream>
#include "Subjects1-4.h"

// Parent class (introduces children to each other)

class Parent: public Subject
{
  Relay *alice;    // link to Child Alice
  Relay *bob;      // link to Child Bob

public:
  Parent();   // creates a Parent

  void init();     // creates new children

  void setup(Identity *d);    // set up connections to children and between them
};


// Child class

class Child: public Subject
{
  Relay* carol;     // link from parent
  Relay* indirect;  // indirect link to other Child
  Relay* directin;  // direct link from other child
  Relay* directout; // direct link to other child

public:

  Child();       // creates Child

  void init();        // initialize Child

  void connect(Identity *d);        // connect to other Child via Parent

  void indirect_hello(Identity *d); // hello via indirect line

  void direct_hello();              // hello via direct line

};


// Parent methods

  Parent::Parent()
  {
    alice = NULL;
    bob = NULL;
    call(Parent::init, NULL);
  }

  void Parent::init()
  {
    new(Child);
    new(Child);
  }

  void Parent::setup(Identity *d)
  {
    Identity *iab; // Identity of Alice for Bob
    Identity *iba; // Identity of Bob for Alice

    if (alice==NULL) alice = new Relay(d);
    else {
      bob = new Relay(d);
      iab = new Identity(alice, bob);
      iba = new Identity(bob, alice);
      alice->call(Child::connect, iba);
      bob->call(Child::connect, iab);
    }
    delete d;                 // d not needed any more
  }


// Child methods

  Child::Child()
  {
    call(Child::init, NULL);
  }

  void Child::init()
  {
    Identity *d;

    carol = new Relay;
    d = new Identity(carol,parent);
    parent->call(Parent::setup, d);
  }

  void Child::connect(Identity *d)
  {
    indirect = new Relay(d);
    delete d;
    directin = new Relay;
    d = new Identity(directin,indirect);
    indirect->call(Child::indirect_hello, d);
  }

  void Child::indirect_hello(Identity *d)
  {
    directout = new Relay(d);
    std::cout << "I received an indirect hello.\n";
    directout->call(Child::direct_hello, NULL);
  }

  void Child::direct_hello()
  {
    std::cout << "I received a direct hello.\n";
  }


int main()
{
  Subject *s;

  s = new Parent;
  run(s,100);

  sys_pause();
}

