#include <iostream>
#include <list>
#include "DispatcherFactory.h"
#include "SampleData.h"

int main() {

  // Components
  ComponentId componentA = 111111;
  ComponentId componentB = 222222;

  std::list<const ComponentId *> components;
  components.push_back(&componentA);
  components.push_back(&componentB);

  // Setup Dispatchers (Eth - IP - UDP/TCP automatically set)
  DispatcherFactory::Instance().Get("UDP")->AddExplicitUpperLayer("DNS"/*, Filter("port", 53) */);
  DispatcherFactory::Instance().Get("UDP")->AddExplicitUpperLayer("SIP");
  DispatcherFactory::Instance().Get("TCP")->AddExplicitUpperLayer("SIP");

  // Component A filters
//   ip.RegisterFilter(&componentA, "addr", "10.0.0.1");
//   udp.RegisterFilter(&componentA, "port", 5060);
//   tcp.RegisterFilter(&componentA, "port", 5060);
//   udp.RegisterFilter(&componentA, "port", 5080);
//   tcp.RegisterFilter(&componentA, "port", 5080);

  // Component B filters
//   ip.RegisterFilter(&componentB, "addr", "10.0.0.2");
//   udp.RegisterFilter(&componentB, "port", 5060);
//   tdp.RegisterFilter(&componentB, "port", 5060);


  // Get root dispatcher
  Dispatcher *eth = DispatcherFactory::Instance().Get("Ethernet"); 

  ////////////////////////////////////////////////////////////////
  // Dispatch DNS Query
  {
    std::cout << std::endl << "Dispatch DNS Query" << std::endl;

    DispatchInfo * di = eth->Dispatch(new DispatchInfo(psDnsQuery, 72, components));

    std::cout << "Selected components:" << std::endl;
    std::list<const ComponentId *>::const_iterator it;    
    for(it = di->GetComponents().begin();
	it != di->GetComponents().end();
	++it) {
      std::cout << "---> " << *(*it) << std::endl;
    }    
  }

  ////////////////////////////////////////////////////////////////
  // Dispatch Fragments
  {
    std::cout << std::endl << "Dispatch IP fragments" << std::endl;

    eth->Dispatch(new DispatchInfo(psFragmemt_1_1, 1410, components));
    eth->Dispatch(new DispatchInfo(psFragmemt_1_2, 1410, components));
    DispatchInfo * di = eth->Dispatch(new DispatchInfo(psFragmemt_1_3, 290, components));

    std::cout << "Selected components:" << std::endl;
    std::list<const ComponentId *>::const_iterator it;    
    for(it = di->GetComponents().begin();
	it != di->GetComponents().end();
	++it) {
      std::cout << "---> " << *(*it) << std::endl;
    }    
  
    // Check that fragments have been correctly reassembled
    if(memcmp(psPayload_1, di->GetData(), di->GetDataSize())) {
      std::cout << "OK !" << std::endl;
    }
    else {
      std::cout << "ERROR" << std::endl;
    }
  }

  ////////////////////////////////////////////////////////////////

  return 0;
}

